当我在flask的create_app方法里import同一个模块的两个文件时出现不同的情况。
def create_app(config_name=None):
...
with app.app_context():
if is_debug_mode() and not is_werkzeug_reloader_process():
pass
else:
from app.sched import etl # 或tasks
scheduler.start()
from app.sched import scheduler_config
init_jobs()
return app
etl和tasks里面都有:
from app import scheduler
但是,如果是import tasks不会报错,import etl会报如下错误:
importError: cannot import name 'scheduler' from 'app'
那么,etl和tasks到底有啥区别:
task.py模块
from flask import current_app
from app import scheduler
from app.sched.etl import etl_resource_data
from app.sched.scheduler_config import ETL_JOB_PARAMS
@scheduler.task(id="etl_daily_tyedu_st_resource_data", **ETL_JOB_PARAMS,
args=[{"src": current_app.config.get("SQLALCHEMY_DATAbase_URI"),
"dest": current_app.config.get("CH_DATAbase_URI")}])
def etl_resource_data_daily(args):
etl_resource_data(args['src'], args['dest'])
tasks直接是一个装饰器的task
etl.py模块:代码有点多,省略一下:
import petl as etl
from flask import current_app
from app import scheduler
from app.sched.scheduler_config import ETL_JOB_PARAMS
from sqlalchemy import create_engine, desc
from clickhouse_driver import connect
from sqlalchemy.orm import sessionmaker
from config import EngineConfig
from agents.models import ResourceData
chdb_http = sessionmaker(bind=create_engine(EngineConfig.CH_HTTP_URI))()
def fill_resdata_from_recalldata(datas):
...
@scheduler.task(id="etl_daily_tyedu_st_resource_data", **ETL_JOB_PARAMS,
args=[{"src": current_app.config.get("SQLALCHEMY_DATAbase_URI"),
"dest": current_app.config.get("CH_DATAbase_URI")}])
def etl_resource_data_daily(args):
etl_resource_data(args['src'], args['dest'])
我判断
import tasks的时候,是把@scheduler.task这段代码拿过去了
import etl的时候,
File "C:Users15871Projectspythonrmsapp__init__.py", line 18, infrom app.blueprints.jobs import jobs_bp File "C:Users15871Projectspythonrmsappblueprintsjobs.py", line 11, in from app.sched.job_controller import start_job File "C:Users15871Projectspythonrmsappschedjob_controller.py", line 11, in from app.sched.etl import etl_recall_data File "C:Users15871Projectspythonrmsappschedetl.py", line 13, in from app import scheduler importError: cannot import name 'scheduler' from 'app'
实际上是在前面,注册blueprint时候就报错。
局部import为什么不报错?因为局部import的是其父级模块(import它的模块)里面import了scheduler对象。
说明局部import代码可以利用父级模块的import对象,因为局部import是父级模块完成了它的import才发生。而全局import是不能这样的,全局import整个import是一块,没有先后。
这是这个问题的原因,理解了吗?
所以,复杂项目的import很复杂,一定要小心。



