对于我目前的python项目,我目前在每个脚本的开头添加这行代码:
import os
import sys
current = os.path.abspath(os.path.dirname(__file__))
(__,folder) = os.path.split(current)
while folder != "my_root_folder_name":
current = os.path.abspath(os.path.join(current, os.path.pardir))
(__, folder) = os.path.split(current)
sys.path.insert(0, current)
此处 my_root_folder_name 是项目根文件夹的名称。在每个脚本中都有这个允许通过写入(导入脚本的任何地方)从任何其他脚本导入它们中的任何一个:
import subfolder1.subfolder2.thescript
其中子文件夹1 位于根文件夹 my_root_folder_name 中(最终路径为 /my_root_folder_name/subfolder1/subfolder2/thescript.py )。
这是一个好习惯吗?你觉得这个伎俩有什么不利吗?我有什么更好的选择?
编辑:让我的项目组织如下:
我使用此技巧的原因是为了确保我可以从另一个子文件夹导入子文件夹的脚本。如果你不注意,这可能会导致循环导入,但导入的python'..'语法也可以。它还使导入更清晰,因为每次导入都是通过将整个绝对路径写入脚本来完成的。
编辑2: 这段代码不会导入所有其他脚本!! 。它只是通过项目的主文件夹替换脚本的第一个(索引0)sys.path值,该值是文件所在的实际文件夹。
答案 0 :(得分:4)
一般不会,出于某些原因,这不是一个好习惯。
答案 1 :(得分:1)
是否需要在Python代码本身内编写解决方案?
设置PYTHONPATH=/path/to/module/root
完全符合您的要求。例如:
$ find /tmp/py/modules/ -type f
/tmp/py/modules/qwerty/a/b/target.py
/tmp/py/modules/asdf/a/b/source
$ pwd
/tmp/py/modules/asdf
$ python /tmp/py/modules/asdf/a/b/source
Traceback (most recent call last):
File "/tmp/py/modules/asdf/a/b/source", line 3, in <module>
import qwerty.a.b.target
ModuleNotFoundError: No module named 'qwerty'
$ export PYTHONPATH=/tmp/py/modules/
$ python /tmp/py/modules/asdf/a/b/source
Hello from target
<强> /tmp/py/modules/qwerty/a/b/target.py 强>
#!/usr/bin/env python
print ("Hello from target")
<强>的/ tmp / PY /模块/ ASDF / A / B /来源
#!/usr/bin/env python
import qwerty.a.b.target
解决方案实际上与您正在进行的操作相同,只是在Python代码之外。
请注意,对于Python2,您需要在结构中的每个目录上创建__init__.py
个文件(文件可能为空)。 Python3的文档也说它们是必需的,但上面的例子没有它们就可以正常工作。
更新的目录内容如下:
./qwerty/__init__.py
./qwerty/a/__init__.py
./qwerty/a/b/__init__.py
./qwerty/a/b/target.py
./asdf/__init__.py
./asdf/a/__init__.py
./asdf/a/b/__init__.py
./asdf/a/b/source
(对于这个简单的示例,__init__.py
下并不严格要求文件asdf
,但是因为您希望能够从所有其他脚本导入所有脚本,这就是您在项目中的操作方式)
作为一个补充说明,如果你保留上面的Python代码,我唯一的建议是检查是否到达根文件夹,以免你在移动脚本的情况下进入无限循环{{1} }不是其新位置路径的组件。对于UNIX,我会做这样的事情:
my_root_folder_name
答案 2 :(得分:1)
前段时间我遇到了同样的问题。在我看来,这是一个Python语言的问题,在像import语句这样的简单操作中变得复杂。我做了同样的选择来解决问题,通过sys.path
命令更新PYTHONPATH环境变量。我以不同的方式对你做,我编写一个递归文件夹资源管理器并将其放入项目根文件夹中的__init__.py
。代码如下:
import os, sys
from pathlib import Path
def recursive_explorer(path):
sys.path.append(path)
subfolders = [subfile for subfile in os.listdir(path) if os.path.isdir(path / subfile)]
for subfolder in subfolders:
recursive_explorer(path / subfolder)
recursive_explorer(Path(__file__).parent / 'your_src_folder')
我认为我的解决方案很好,因为它是可移植的,你需要写一次。
答案 3 :(得分:1)
您的方法的好处并不能证明成本合理。好处是你可以写
BlurTransformation
到处都是
的某种变体import subfolder1.subfolder2.thescript
成本是每个阅读代码的人现在必须找出问题的答案,如
一旦Joe Programmer确信代码没有错误并且没有任何不良影响,他可以不假思索地复制和粘贴它。但是为了避免Joe已经需要了解的略微丑陋的导入语法,是否值得添加5行不那么明显的样板?否。
选择其中一个易于理解的选项: