[英]Three-way Python import chain results in ModuleNotFoundError or ImportError
Consider a project structure --考虑一个项目结构——
\root
__init__.py
bar.py
\package1
__init__.py
abstractFoo.py
implementedFoo.py
And a few file definitions for context --还有一些上下文的文件定义——
Lastly, the imports --最后,进口——
The clash occurs in bar.py, when trying to import implementedFoo.py on-demand, specifically when implementedFoo.py itself tries importing from abstractFoo.py.冲突发生在 bar.py 中,当尝试按需导入implementedFoo.py 时,特别是当implementedFoo.py 本身尝试从abstractFoo.py 导入时。
It seems both relative (eg implementedFoo.py: from . import abstractFoo) and absolute (eg implementedFoo.py: from root.package1 import abstractFoo) imports fail as they are no longer "correct" from the vantage point of bar.py at runtime.似乎相对(例如implementedFoo.py:from .import abstractFoo)和绝对(例如implementedFoo.py:from root.package1 import abstractFoo)导入都失败了,因为从bar.py的有利位置在运行时它们不再“正确” .
Note I am running Python 3.10.x.注意我正在运行 Python 3.10.x。 Please let me know if I can provide any additional information.
如果我可以提供任何其他信息,请告诉我。 I am appending below a sample error...
我在下面附加一个示例错误...
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'
Thank you in advance.先感谢您。
Creating a subpackage directory subpackage1 under package1,and placing abstractFoo in subpackage1 allows me to accomplish what I'm looking for via absolute imports.在 package1 下创建一个子包目录 subpackage1,并将 abstractFoo 放在 subpackage1 中允许我通过绝对导入来完成我正在寻找的东西。 I would probably have been content with this solution if I'd come across it before posting this question, but still open for any enhancements/alternatives.
如果在发布此问题之前遇到此解决方案,我可能会对此解决方案感到满意,但仍对任何增强/替代方案持开放态度。
For some additional context on why the structure is so convoluted: root is a database folder, bar is the database driver, abstractFoo abstracts as much as possible from pulling data via third party sources, and implementedFoo files are created on a 1:1 basis against third parties, each implementing common functions and returning data in a common format for database consumption.关于为什么结构如此复杂的一些额外上下文:root 是数据库文件夹,bar 是数据库驱动程序,abstractFoo 尽可能从通过第三方来源提取数据进行抽象,并且以 1:1 的方式创建implementedFoo 文件第三方,每个都实现通用功能并以通用格式返回数据以供数据库使用。 The database driver (bar) and API implementations (implementedFoo) must both import abstract classes and/or helper functions from abstractFoo.
数据库驱动程序 (bar) 和 API 实现 (implementedFoo) 都必须从 abstractFoo 导入抽象类和/或辅助函数。 Upstream (ie beyond the root folder), only bar.py (or the root folder itself, TBD) will be imported to handle database i/o back-end.
上游(即超出根文件夹),只会导入 bar.py(或根文件夹本身,待定)来处理数据库 i/o 后端。
You could use my new, experimental import library ultraimport and rather use relative imports你可以使用我的新的、实验性的导入库ultraimport ,而不是使用相对导入
In implementedFoo.py you would then write:在implementedFoo.py中,你会写:
import ultraimport
abstractFoo = ultraimport('__dir__/abstractFoo.py')
This import will always work, no matter how you run your script or what is your current working directory.无论您如何运行脚本或当前工作目录是什么,此导入都将始终有效。 You also don't need to create a new directory.
您也不需要创建新目录。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.