我如何 运行 一个 Python 3 脚本从子文件夹导入?

How can I run a Python 3 script with imports from a subfolder?

无论我尝试什么,自从我切换到 Python 3 我可以 运行 脚本只从项目的根文件夹导入,但不能从子文件夹。我知道这里有很多关于我收到的错误消息的问题,但建议的解决方案对我不起作用。有人可以为这个小示例项目提供示例解决方案吗?相信很多人都会喜欢的。

proj
├── foofolder
│   ├── __init__.py
│   └── foofile.py
├── subfolder
│   ├── __init__.py
│   └── run.py
└── __init__.py

我在foofile.py中定义了函数foofun(),想在run.py中调用它。

如果 run.py 直接在 proj 中就可以了。但是(只是为了让事情井井有条)我想把它放在一个子文件夹中——令人惊讶的是,这似乎是不可能的。

烦人的是我的 IDE (PyCharm) 中的自动完成提示 from foofolder.foofile import foofun 应该有效。但事实并非如此。也没有我能想象的任何其他进口:

from foofolder.foofile import foofun --> ImportError: No module named 'foofolder'

from .foofolder.foofile import foofun --> SystemError: Parent module '' not loaded, cannot perform relative import (同前两点)

from proj.foofolder.foofile import foofun --> ImportError: No module named 'proj'

甚至绝对导入都不起作用。为什么找不到 proj?

sys.path 是:['/parent/proj/subfolder', '/parent/env/lib/python35.zip', '/parent/env/lib/python3.5', '/parent/env/lib/python3.5/plat-x86_64-linux-gnu', '/parent/env/lib/python3.5/lib-dynload', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/parent/env/lib/python3.5/site-packages']

我在虚拟环境中使用 Python 3.5.2。


编辑:我说这个问题是特定于Python时我错了 3.问题和解决方案在我检查时是一样的Python 2.7.12.

Pevogam 给出的解决方案有效。第一个从字面上只是将 '..' 添加到 'sys.path',它描述了执行 run.py 的父文件夹。第二个明确添加 '/parent/proj'.

我能想到的最快的方法是:

# subfolder/run.py
import sys
sys.path.append("..")

from foofolder.foofile import foofun

foofun()

但是请注意,只有从其文件夹中 运行 run.py 才有效。不依赖于此的更详细的方法是

# subfolder/run.py
import sys
import os.path as o
sys.path.append(o.abspath(o.join(o.dirname(sys.modules[__name__].__file__), "..")))

from foofolder.foofile import foofun

foofun()

您可以从任何位置访问函数的位置。对于所有此类模块,最简单的做法是使用相同的指向根包的指针,在您的情况下,通过添加“..”来实现。然后您可以从这个根包的角度执行任何导入。

我倾向于避免使用相对导入,因为它们会造成混淆并降低可读性,但希望其中一些有所帮助。

[*] 某些 IDE 可能会执行他们自己的项目扫描,这就是只要您 运行 python 中的 python 代码,他们仍可能找到导入的原因=26=].

我通常在 Django 项目中需要这个,并且刚刚意识到 Django 提供了一个非常方便的解决方案,为我解决了这个问题:

$ python manage.py shell < app/utils/scripts/script.py 

script.py 中,我的进口商品如下:

from app.utils.functions.do_things import do_this, do_that

在此处找到:How to execute a Python script from the Django shell?

问:如何运行 python 子文件夹中的脚本?

A:调用使用PYTHONPATH=. python3 subfolder/run.py

添加到 bashrc:alias pys = PYTHONPATH=. python3。然后 pys subfolder/run.py 有效!

评论:对我来说,脚本就是执行任务的东西。它永远不会被其他东西调用或导入。我有很多。 其中一些是相似的(例如 taskA_reset.pytaskB_reset.py)。我更喜欢将其组织为 taskA/reset.py 等。但是,那就不可能再运行他们了!但是,在路径前面加上一个简单的解决方案,它不需要我更改任何 python-代码。