我无法从另一个目录中的Python文件导入。目录结构:
some_root/
- __init__.py
- dir_0/
- __init__.py
- dir_1/
- __init__.py
- file_1.py
- dir_2/
- __init__.py
- file_2.py
file_1.py
有一些导出成员:
# file_1.py
def foo():
pass
file_2.py
尝试从file_1.py
:导入成员
# file_2.py
from dir_0.dir_1.file_1 import foo
但无论是绝对的还是相对的重要性似乎都不起作用。如何正确导入Python?如果我能避免使用sys.path.insert
,那就太好了,但如果没有办法,我想事情就是这样。
不要打乱搜索路径
你没有摆弄sys.path
是对的。这是不推荐的,而且总是一个丑陋的变通方法。对此有更好的解决方案。
重新构造文件夹布局
请参阅关于打包的Python官方文档。
区分项目文件夹和 包文件夹在你的情况下,它应该是这样的。 使用该内容创建一个 创建包含以下内容的 这不是一个常见的安装。请参阅"开发模式"来了解这到底意味着什么。包未复制到 导航到项目文件夹 不要忘记最后的 您的 但正如其他人在评论中所说。改进文件和文件夹的结构并降低其复杂性。some_project
└── src
└── some_root
├── dir_0
│ ├── dir_1
│ │ ├── file_1.py
│ │ └── __init__.py
│ ├── dir_2
│ │ ├── file_2.py
│ │ └── __init__.py
│ └── __init__.py
└── __init__.py
使您的软件包可安装
some_project/setup.cfg
。在第5行和第6行保留换行符和缩进。他们必须是这样,但我不知道为什么。[metadata]
name = some_project
[options]
package_dir=
=src
packages = find:
zip_safe = False
python_requires = >= 3
[options.packages.find]
where = src
exclude =
tests*
.gitignore
some_project/setup.py
:from setuptools import setup
setup()
"安装";包裹
/usr/lib/python/site-packages
;只创建链接。some_project
并运行python3 -m pip install --editable .
.
。根据您的操作系统和环境,可能需要将python3
替换为py -3
或python
或其他内容。导入
file_2.py
import some_root
import some_root.dir_0
import some_root.dir_0.dir_1
from some_root.dir_0.dir_1 import file_1
file_1.foo()
默认情况下,Python搜索路径包括在安装Python时有效固定的目录:如/usr/lib/python/site-packages
。
运行脚本时,包含正在执行的脚本的目录会添加到路径中。最重要的是,为了安全起见,当前工作目录是,而不是添加到路径中。(您不希望您的脚本以不同的方式工作,可能会根据其调用环境导入您意想不到的模块。这与强烈建议将.
排除在PATH
变量之外的原因相同。(
执行file_2.py
时,some_root/dir_0/dir_2
会添加到路径中,但如果some_root
是当前工作目录,则some_root
本身不在搜索路径上。这就是import dir_0.dir_1.file_1
失败的原因。相对导入也会失败,因为some_root
不是用于解析相对导入的根(或任何(包。
通常,如果你想在不安装代码的情况下运行代码,你可以将脚本保存在some_root
中:
some_root/
file_a.py
- __init__.py
- dir_0/
- __init__.py
- dir_1/
- __init__.py
- file_1.py
- dir_2/
- __init__.py
file_2.py
file_a.py
可以像一样简单
from dir_0.dir_2.file_2 import main
if __name__ == '__main__':
main()
CCD_ 30提供了一个入口点。(它仍然可以自己执行;它只是使用main
,就像导入file_2.py
的任何其他脚本一样,而不仅仅是直接跳到它的代码中。(