使用公共常量模块导致循环导入
Using common constants module leads to circular import
我想从两个不同模块的 constants
模块导入常量,但出现以下错误:
Traceback (most recent call last):
File "C:\Temp\tmp\pycircular\pycircular\pycircular.py", line 2, in <module>
from my_classes.foo import Foo
File "C:\Temp\tmp\pycircular\pycircular\my_classes\foo.py", line 1, in <module>
from pycircular.constants import ANOTHER_CONSTANT
File "C:\Temp\tmp\pycircular\pycircular\pycircular.py", line 2, in <module>
from my_classes.foo import Foo
ImportError: cannot import name 'Foo' from partially initialized module 'my_classes.foo' (most likely due to a circular import) (C:\Temp\tmp\pycircular\pycircular\my_classes\foo.py)
我的项目结构如下:
|-constants.py
|-my_classes
| |-foo.py
| |-__init__.py
|-pycircular.py
|-__init__.py
# =============
# pycircular.py
# =============
from constants import SOME_CONSTANT
from my_classes.foo import Foo
def main():
print(SOME_CONSTANT)
my_foo = Foo()
my_foo.do_something()
if __name__ == "__main__":
main()
# =============
# foo.py
# =============
from pycircular.constants import ANOTHER_CONSTANT
class Foo:
def do_something(self):
print(ANOTHER_CONSTANT)
# =============
# constants.py
# =============
ANOTHER_CONSTANT = "ANOTHER"
SOME_CONSTANT = "CONSTANT"
我认为这与此处解决的问题相同 。
但是我真的不明白为什么 pycircular.py
中的 from my_classes.foo import Foo
被调用了第二次。
更新:
将包 pycircular
重命名为 pycircular_pack
后,它在 PyCharm 中工作。
但它之所以有效,是因为在 Pycharm 中自动设置了选项 Add content roots to to PYTHONPATH
。
sys.path
的输出是['C:\Temp\tmp\pycircular\pycircular_pack', 'C:\Temp\tmp\pycircular', 'C:\Tools\miniconda\envs\my_env\python39.zip', 'C:\Tools\miniconda\envs\my_env\DLLs', 'C:\Tools\miniconda\envs\my_env\lib', 'C:\Tools\miniconda\envs\my_env', 'C:\Tools\miniconda\envs\my_env\lib\site-packages']
没有选项输出是['C:\Temp\tmp\pycircular\pycircular_pack', 'C:\Tools\miniconda\envs\my_env\python39.zip', 'C:\Tools\miniconda\envs\my_env\DLLs', 'C:\Tools\miniconda\envs\my_env\lib', 'C:\Tools\miniconda\envs\my_env', 'C:\Tools\miniconda\envs\my_env\lib\site-packages']
如果没有这个选项,我只能使用绝对导入。
# pycircular.py
from constants import SOME_CONSTANT
from my_classes.foo import Foo
...
# foo.py
from constants import ANOTHER_CONSTANT
根据评论和编辑进行详细说明:
After renaming the package pycircular to pycircular_pack it worked in PyCharm. But it only works because in Pycharm the option Add content roots to to PYTHONPATH is automatically set.
您应确保包目录未设置为内容根或源根。托管包目录的目录应设置为源根目录。
C:\Temp\tmp\pycircular # <- source root
|- pycircular_pack # <- not set as anything
| |- constants.py
| |- my_classes
| | |- foo.py
| | |- __init__.py
| |- pycircular.py
| |- __init__.py
|- other_file.py # <- for illustration's sake
现在您的 sys.path
将被设置为仅包含 C:\Temp\tmp\pycircular
并且只有一种方法可以从您的模块中导入内容。
即
other_file.py
(包外)将可以使用包为pycircular_pack
pycircular_pack/*.py
可以引用 pycircular_pack
包中的模块
- (例如)
from .constants import ...
(从当前包相对导入),或
- (例如)
from pycircular_pack.constants import ...
(绝对导入)
pycircular_pack/my_classes/*.py
可以引用 pycircular_pack
包中的模块
- (例如)
from ..constants import ...
(从父包相对导入),或
- (例如)
from pycircular_pack.constants import ...
(绝对导入)
如果您的 pycircular_pack
包包含 运行 可用脚本,例如CLI 作为 pycircular_pack/cli.py
,那么在命令行上 运行 该脚本的正确方法是使用 python -m pycircular_pack.cli
;这已经 Python 设置了我们想要的路径,其中 python pycircular_pack/cli.py
不会做正确的事情。
我想从两个不同模块的 constants
模块导入常量,但出现以下错误:
Traceback (most recent call last):
File "C:\Temp\tmp\pycircular\pycircular\pycircular.py", line 2, in <module>
from my_classes.foo import Foo
File "C:\Temp\tmp\pycircular\pycircular\my_classes\foo.py", line 1, in <module>
from pycircular.constants import ANOTHER_CONSTANT
File "C:\Temp\tmp\pycircular\pycircular\pycircular.py", line 2, in <module>
from my_classes.foo import Foo
ImportError: cannot import name 'Foo' from partially initialized module 'my_classes.foo' (most likely due to a circular import) (C:\Temp\tmp\pycircular\pycircular\my_classes\foo.py)
我的项目结构如下:
|-constants.py
|-my_classes
| |-foo.py
| |-__init__.py
|-pycircular.py
|-__init__.py
# =============
# pycircular.py
# =============
from constants import SOME_CONSTANT
from my_classes.foo import Foo
def main():
print(SOME_CONSTANT)
my_foo = Foo()
my_foo.do_something()
if __name__ == "__main__":
main()
# =============
# foo.py
# =============
from pycircular.constants import ANOTHER_CONSTANT
class Foo:
def do_something(self):
print(ANOTHER_CONSTANT)
# =============
# constants.py
# =============
ANOTHER_CONSTANT = "ANOTHER"
SOME_CONSTANT = "CONSTANT"
我认为这与此处解决的问题相同 pycircular.py
中的 from my_classes.foo import Foo
被调用了第二次。
更新:
将包 pycircular
重命名为 pycircular_pack
后,它在 PyCharm 中工作。
但它之所以有效,是因为在 Pycharm 中自动设置了选项 Add content roots to to PYTHONPATH
。
sys.path
的输出是['C:\Temp\tmp\pycircular\pycircular_pack', 'C:\Temp\tmp\pycircular', 'C:\Tools\miniconda\envs\my_env\python39.zip', 'C:\Tools\miniconda\envs\my_env\DLLs', 'C:\Tools\miniconda\envs\my_env\lib', 'C:\Tools\miniconda\envs\my_env', 'C:\Tools\miniconda\envs\my_env\lib\site-packages']
没有选项输出是['C:\Temp\tmp\pycircular\pycircular_pack', 'C:\Tools\miniconda\envs\my_env\python39.zip', 'C:\Tools\miniconda\envs\my_env\DLLs', 'C:\Tools\miniconda\envs\my_env\lib', 'C:\Tools\miniconda\envs\my_env', 'C:\Tools\miniconda\envs\my_env\lib\site-packages']
如果没有这个选项,我只能使用绝对导入。
# pycircular.py
from constants import SOME_CONSTANT
from my_classes.foo import Foo
...
# foo.py
from constants import ANOTHER_CONSTANT
根据评论和编辑进行详细说明:
After renaming the package pycircular to pycircular_pack it worked in PyCharm. But it only works because in Pycharm the option Add content roots to to PYTHONPATH is automatically set.
您应确保包目录未设置为内容根或源根。托管包目录的目录应设置为源根目录。
C:\Temp\tmp\pycircular # <- source root
|- pycircular_pack # <- not set as anything
| |- constants.py
| |- my_classes
| | |- foo.py
| | |- __init__.py
| |- pycircular.py
| |- __init__.py
|- other_file.py # <- for illustration's sake
现在您的 sys.path
将被设置为仅包含 C:\Temp\tmp\pycircular
并且只有一种方法可以从您的模块中导入内容。
即
other_file.py
(包外)将可以使用包为pycircular_pack
pycircular_pack/*.py
可以引用pycircular_pack
包中的模块- (例如)
from .constants import ...
(从当前包相对导入),或 - (例如)
from pycircular_pack.constants import ...
(绝对导入)
- (例如)
pycircular_pack/my_classes/*.py
可以引用pycircular_pack
包中的模块- (例如)
from ..constants import ...
(从父包相对导入),或 - (例如)
from pycircular_pack.constants import ...
(绝对导入)
- (例如)
如果您的 pycircular_pack
包包含 运行 可用脚本,例如CLI 作为 pycircular_pack/cli.py
,那么在命令行上 运行 该脚本的正确方法是使用 python -m pycircular_pack.cli
;这已经 Python 设置了我们想要的路径,其中 python pycircular_pack/cli.py
不会做正确的事情。