Home > Software design >  Flask refering to root folder circular import
Flask refering to root folder circular import

Time:07-07

I have a Flask application that is constructed as following:

--- /app
------ /__pycache__
------ /static
--------- /files
--------- /assets
--------- /images
------ /templates
------ api.py
------ utils.py
------ config.py
------ sftp.py
--- wsgi.py 

wsgi.py:

from app.main import app
 
if __name__ == "__main__":
        app.run()

main.py:

from flask import Flask, render_template, request, session, flash, url_for, redirect
from werkzeug.utils import secure_filename
from .utils import *
from .config import *
from .sftp import sync_work_days

app = Flask(__name__)
app.secret_key = b'very_secret_key'
[...]

config.py:

import os
from wsgi import app

ROOT_PATH = app.instance_path

sftp.py:

import pysftp as sftp
from .config import *
from .utils import upload_working_days
import time, os
from datetime import datetime
from config import ROOT_PATH

def sync_work_days():
    cnopts = sftp.CnOpts()
    cnopts.hostkeys = None

    s = sftp.Connection(host=SFTP_HOSTNAME, username=SFTP_USERNAME, password=SFTP_PASSWORD, cnopts=cnopts)
    print("Connection succesfully established...")

    remoteFilePath = '/files/company'
    
    files = s.listdir_attr(remoteFilePath)
    if files == []:
        return "empty"
    else:
        for f in files:
            localFilePath = os.path.join(ROOT_PATH, 'static/files/company')
            # s.get(remoteFilePath, localFilePath)
            upload_working_days(localFilePath)
            time.sleep(5)
            print("UPLOAD DONE")
            s.rename(remoteFilePath   f, remoteFilePath   "/archives/"   f)

When I run the app, I get the following error:

from wsgi import app
ImportError: cannot import name 'app' from partially initialized module 'wsgi' (most likely due to a circular import) (D:\[...redacted...]\wsgi.py)  

All I want to do is to download a file via SSH and put it in app/static/files, and I can't just hardcode the path because the deployment environment is different.

UPDATE 1: I tried to cut off config.py from the loop and I made the following changes:

sftp.py:

import pysftp as sftp
from .config import *
from .main import app
from .utils import upload_working_days
import time, os
from datetime import datetime

def sync_work_days():
    cnopts = sftp.CnOpts()
    cnopts.hostkeys = None
    filename = os.path.join(app.instance_path, 'my_folder', 'my_file.txt')

And this is the error I get:

ImportError: cannot import name 'app' from partially initialized module 'app.main' (most likely due to a circular import) (D:\[...redacted...]\app\main.py)

CodePudding user response:

You have a circular import because you are importing app in config.py from wsgi.py, which gets it from main.py which imports config.py.

And you are importing app in config.py because you need a setting from it. Have you considered keeping all your settings in config.py and importing them in main.py from there? That seems like a logical thing to do.

CodePudding user response:

The solution to this problem is the following:

In sftp.py, replace:

from .main import app

by:

from . import main

and instead of using app.instance_path, use main.app.instance_path

  • Related