Python项目包/模块结构依赖重复初始化问题求助
Python项目依赖初始化重复触发问题及结构优化求助
项目结构
Sitka │ DataTickers.py │ example.csv │ FinDates.py │ SitkaMongo.py │ tickers_csv.csv │ __init__.py │ ├───Fin │ │ main.py │ │ md_provider_control.py │ │ Tofino.py │ │ __init__.py │ │ │ ├───Instruments │ │ │ market_standard_instruments.py │ │ └ __init__.py │ │ │ ├───Env │ │ │ CurveClass.py │ │ │ ├───Utils │ │ charting.py │ │ exchange_identifier_mapper.py │ │ fin_mapper.py │ │ md_provider_simulation.py │ └ __init__.py
关键模块代码
Tofino.py
from .Env.CurveClass import CurveData as _CurveData class Tofino(): def __init__(self, mdp, VAL_ENV = None): mdp.tofino = self # link Tofino # Public VE Refernce self.val_env = VAL_ENV self.ir_config = VAL_ENV.market
market_standard_instruments.py
# Standard Imports import Sitka.FinDates as fdate import datetime as dt import re from itertools import product # bunch of functions after this.
CurveClass.py
import pandas as pd import datetime as dt from dateutil.relativedelta import relativedelta class CurveData(): def __init__(self): self.do_stuff= self._stuff()
main.py
from Sitka.FinDates import getMainDates # Sitka- Custom Imports from .md_provider_control import MD_ProviderV3 from .Tofino import Tofino import Sitka.Fin.Instruments.market_standard_instruments as mkt_std def main() -> Tofino: # < ---- do a bunch of stuff ---- > return Tofino(mdp = mdp, VAL_ENV=ve.GLOBAL_VALN_ENV)
Sitka.Fin.init.py
import logging import traceback # Run Valuation Environment Startup from .main import main # Global Variables: from .Tofino import Tofino as _Tofino tofino : _Tofino tofino = None try: tofino = main() # I was trying some stuff out here, hence the weird traceback in try except: print(traceback.format_exc())
问题描述
- 执行
import Sitka.Fin as fin时,main.py中的import Sitka.Fin.Instruments.market_standard_instruments as mkt_std会在进入try块前再次触发Sitka.Fin.__init__流程,导致初始化运行2次。 - 仅为了IDE智能提示/自动补全添加子目录
__init__.py,希望优化代码结构使其更简洁。 - 补充:在IPython控制台仅执行
import Sitka.Fin.Instruments.market_standard_instruments as mkt_std,就会触发整个Sitka.Fin.__init__流程,不符合预期。
问题原因及解决方法
初始化重复触发的核心原因
Python导入模块时,若通过绝对导入引用子模块,会先加载父模块并执行其__init__.py。当前Sitka.Fin.__init__.py导入了main.py,而main.py又用绝对导入加载market_standard_instruments,混合使用绝对/相对导入可能导致模块被视为不同实例重复加载;同时__init__.py中直接执行业务初始化逻辑,只要父模块被触发加载就会执行该逻辑。
修复重复初始化
统一使用相对导入:将
main.py中的绝对导入改为相对导入,避免触发父模块重复加载:# 替换main.py中的绝对导入 from .Instruments import market_standard_instruments as mkt_std剥离
__init__.py中的业务逻辑:把初始化tofino的逻辑移到单独函数,让用户手动触发,而非导入时自动执行:# 修改后的Sitka.Fin.__init__.py import logging from .Tofino import Tofino as _Tofino tofino: _Tofino = None def init_tofino(): global tofino from .main import main try: tofino = main() except Exception as e: import traceback print(traceback.format_exc())使用时需手动调用
fin.init_tofino(),避免不必要的自动初始化。规范Python路径:确保项目根目录(包含
Sitka的目录)在sys.path中,可在启动脚本中添加:import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent))
代码结构优化
简化
__init__.py职责:仅保留必要的导出声明,让__init__.py作为模块入口的导出层,不执行业务逻辑:# 优化后的Sitka.Fin.__init__.py from .Tofino import Tofino from .main import main from .Instruments.market_standard_instruments import * # 按需导出常用内容精简子模块
__init__.py:对于Instruments、Utils等子目录,__init__.py可仅导出常用类/函数,或保留为空(Python 3.3+支持命名空间包,空文件不影响兼容性):# Sitka/Fin/Instruments/__init__.py from .market_standard_instruments import *
内容的提问来源于stack exchange,提问作者keynesiancross
相关产品推荐
相关产品推荐

