Akr*_*nix 14 import package python-3.x
好的,这个场景非常简单.我有这个文件结构:
.
??? interface.py
??? pkg
? ??? __init__.py
? ??? mod1.py
? ??? mod2.py
Run Code Online (Sandbox Code Playgroud)
现在,这些是我的条件:
因此,在Python 2,我只想做import mod1
内部mod2.py两者python2 mod2.py
并python2 interface.py
预期会工作.
但是,如果我这样做,这是我不太了解的部分,使用Python 3.5.2 import mod1
; 然后我可以做python3 mod2.py
,但python3 interface.py
抛出:ImportError: No module named 'mod1'
:(
所以,显然,python 3建议import pkg.mod1
用来避免与内置模块的冲突.好的,如果我使用我可以做的python3 interface.py
; 但后来我不能python3 mod2.py
因为:ImportError: No module named 'pkg'
同样,如果我使用相对导入:
from . import mod1
然后python3 interface.py
工作; 但mod2.py说SystemError: Parent module '' not loaded, cannot perform relative import
:( :(
唯一的"解决方案",我发现是上一个文件夹python -m pkg.mod2
,然后它可以工作.但是,我们是否必须将包前缀添加到该包pkg
中其他模块的每个导入?更重要的是,要在包中运行任何脚本,我是否必须记得去一个文件夹并使用-m开关?这是唯一的出路?
我糊涂了.这个场景在python 2中非常简单,但在python 3中看起来很尴尬.
更新:我已经上传了这些文件(上面称为"解决方案")工作源代码:https://gitlab.com/Akronix/test_python3_packages.请注意,我仍然不喜欢它,并且看起来比python2解决方案更加丑陋.
我已经读过的相关SO问题:
相关链接:
TLDR:
python -m pkg.mod2
。from . import mod1
。我发现,唯一的“解决方案”是向上移动一个文件夹然后执行即可
python -m pkg.mod2
。
使用-m
交换机确实是“唯一的”解决方案-以前它已经是唯一的解决方案。过去的行为仅仅是出于运气而已。甚至不修改您的代码就可以破坏它。
进入“一个文件夹”只是将您的包添加到搜索路径。安装软件包或修改搜索路径也可以。有关详情,请参见下文。
但是我们是否必须将包前缀pkg添加到该包内其他模块的每次导入中?
您必须对包有一个引用-否则,您想要哪个模块就不明确。软件包引用可以是绝对引用,也可以是相对引用。
相对导入通常是您想要的。它pkg
显着节省了编写工作,从而使重构和移动模块变得更加容易。
# inside mod1.py
# import mod2 - this is wrong! It can pull in an arbitrary mod2 module
# these are correct, they uniquely identify the module
import pkg.mod2
from pkg import mod2
from . import mod2
from .mod2 import foo # if pkg.mod2.foo exists
Run Code Online (Sandbox Code Playgroud)
请注意,您始终<import> as <name>
可以将导入绑定到其他名称。例如,import pkg.mod2 as mod2
让您仅使用模块名称。
甚至更多,要运行程序包中的任何脚本,我是否还必须记住将一个文件夹向上并使用-m开关?那是唯一的方法吗?
如果您的软件包安装正确,则可以-m
从任何地方使用该开关。例如,您可以随时使用python3 -m json.tool
。
echo '{"json":"obj"}' | python -m json.tool
Run Code Online (Sandbox Code Playgroud)
如果尚未安装软件包,则可以将PYTHONPATH
其设置为基本目录。这包括您的包在搜索路径中,并允许-m
交换机正确找到它。
如果位于可执行文件的目录中,则可以执行export PYTHONPATH="$(pwd)/.."
以快速装入要导入的软件包。
我糊涂了。对于python 2,这种情况非常简单,但是在python 3中看起来很尴尬。
这种情况基本上是在python 2中打破的。虽然在许多情况下很简单,但在任何其他情况下都很难或根本无法修复。
在简单的情况下,新的行为会比较尴尬,但在任何情况下都非常可靠。