簡體   English   中英

三路 Python 導入鏈導致 ModuleNotFoundError 或 ImportError

[英]Three-way Python import chain results in ModuleNotFoundError or ImportError

考慮一個項目結構——

\root
    __init__.py
    bar.py
    \package1
        __init__.py
        abstractFoo.py
        implementedFoo.py
   

還有一些上下文的文件定義——

  • bar.py:項目的主要功能
  • abstractFoo.py:定義 Foo
  • implementsFoo.py:實現 Foo (在 package1 下存在許多這些文件,對應於 Foo 的不同實現)

最后,進口——

  • bar.py 從 abstractFoo.py 導入輔助函數(即從 package1.abstractFoo import validateFoo, loadFoo ...); bar.py 利用上述輔助函數按需導入各種implementedFoo.py
  • implementedFoo.py 從 abstractFoo.py 導入抽象類(見下文嘗試)
  • abstractFoo.py 什么都不進口

沖突發生在 bar.py 中,當嘗試按需導入implementedFoo.py 時,特別是當implementedFoo.py 本身嘗試從abstractFoo.py 導入時。

似乎相對(例如implementedFoo.py:from .import abstractFoo)和絕對(例如implementedFoo.py:from root.package1 import abstractFoo)導入都失敗了,因為從bar.py的有利位置在運行時它們不再“正確” .

注意我正在運行 Python 3.10.x。 如果我可以提供任何其他信息,請告訴我。 我在下面附加一個示例錯誤...

In [2]: Source('bloomberg')
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-2-c290b4e239b8> in <cell line: 1>()
----> 1 Foo('Foo')

<ipython-input-1-a0ec8d9f6e48> in __init__(self, Foo_name)
     85     def __init__(self, name: str):
     86         self.Foo_name = Foo_name
---> 87         self.Foo = package1.abstractFoo.load_Foo(self._Foo_path(self.Foo_name))
     88
     89     def read(self, s: str):

path\to\root\package1\abstractFoo.py in load_Foo(Foo_path)
     33     foo = importlib.util.module_from_spec(spec)
     34     sys.modules['foo'] = foo
---> 35     spec.loader.exec_module(foo)
     36     return foo

C:\Python310\lib\importlib\_bootstrap_external.py in exec_module(self, module)

C:\Python310\lib\importlib\_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

path\to\root\package1\implementedFoo.py in <module>
----> 3 import abstractFoo
      4 from typing import Optional, Union
      5 from datetime import date, datetime

ModuleNotFoundError: No module named 'abstractFoo'

先感謝您。

在 package1 下創建一個子包目錄 subpackage1,並將 abstractFoo 放在 subpackage1 中允許我通過絕對導入來完成我正在尋找的東西。 如果在發布此問題之前遇到此解決方案,我可能會對此解決方案感到滿意,但仍對任何增強/替代方案持開放態度。

關於為什么結構如此復雜的一些額外上下文:root 是數據庫文件夾,bar 是數據庫驅動程序,abstractFoo 盡可能從通過第三方來源提取數據進行抽象,並且以 1:1 的方式創建implementedFoo 文件第三方,每個都實現通用功能並以通用格式返回數據以供數據庫使用。 數據庫驅動程序 (bar) 和 API 實現 (implementedFoo) 都必須從 abstractFoo 導入抽象類和/或輔助函數。 上游(即超出根文件夾),只會導入 bar.py(或根文件夾本身,待定)來處理數據庫 i/o 后端。

你可以使用我的新的、實驗性的導入庫ultraimport ,而不是使用相對導入

在implementedFoo.py中,你會寫:

import ultraimport
abstractFoo = ultraimport('__dir__/abstractFoo.py')

無論您如何運行腳本或當前工作目錄是什么,此導入都將始終有效。 您也不需要創建新目錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM