我正在运行Python 2.5。
这是我的文件夹树:
ptdraft/
nib.py
simulations/
life/
life.py
(每个文件夹中都有__init__.py
,为了可读性已省略)
我应该如何从life
模块内部导入nib
模块?我希望能在不修改sys.path的情况下完成。
注意:正在运行的主模块位于ptdraft
文件夹中。
我正在运行Python 2.5。
这是我的文件夹树:
ptdraft/
nib.py
simulations/
life/
life.py
(每个文件夹中都有__init__.py
,为了可读性已省略)
我应该如何从life
模块内部导入nib
模块?我希望能在不修改sys.path的情况下完成。
注意:正在运行的主模块位于ptdraft
文件夹中。
这是与以往答案相同的风格,但代码行数更少 :P
import os, sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0, parentdir)
file 返回你当前所在的位置。
__file__
变量,该变量可能不可靠(并非始终是完整的文件路径,在每个操作系统上都无法工作等),正如StackOverflow用户经常提到的那样。更改答案以不包括它将会导致更少的问题,并且更具跨兼容性。有关更多信息,请参见https://dev59.com/QXRB5IYBdhLWcg3wH0SW#33532002。 - Edward在我看来,你似乎不需要导入父模块。假设在 nib.py 中你有 func1() 和 data1,你需要在 life.py 中使用。
import simulations.life.life as life
def func1():
pass
data1 = {}
life.share(func1, data1)
func1 = data1 = None
def share(*args):
global func1, data1
func1, data1 = args
现在您可以访问life.py中的func1和data。当然,在尝试使用它们之前,您必须小心地在life.py中填充它们。
我们的文件夹结构:
/myproject
project_using_ptdraft/
main.py
ptdraft/
__init__.py
nib.py
simulations/
__init__.py
life/
__init__.py
life.py
ptdraft
,因为它是包含__init__.py
的最高级别目录。
包内的所有文件都可以使用绝对路径(相对于包根目录)进行导入,例如在life.py
中,我们只需简单地写:
import ptdraft.nib
然而,为了在包开发/测试目的下运行life.py
,我们需要使用以下命令,而不是python life.py
:
cd /myproject
python -m ptdraft.simulations.life.life
import sys
sys.path.append("/myproject") # folder that contains ptdraft
import ptdraft
import ptdraft.simulations
使用python main.py
来运行脚本,不会出现问题。
有用的链接:
import sys
from pathlib import Path
sys.path.append(str(Path(f"{__file__}").parent.parent))
import my_module
注意:这是一个框架挑战 - 不需要在代码中完成。
假设有一棵树,
project
└── pkg
└── test.py
其中test.py
包含
import sys, json; print(json.dumps(sys.path, indent=2))
只使用路径执行会包含包目录
python pkg/test.py
[
"/project/pkg",
...
]
但使用模块参数会包括项目目录
python -m pkg.test
[
"/project",
...
]
现在,所有的导入都可以是绝对路径,来自于项目目录。不需要进一步的欺骗手段。
与库一起工作。 创建一个名为nib的库,使用setup.py进行安装,让它驻留在site-packages中,您的问题就解决了。 您不必将所有内容都放在一个包中。将其分解成多个部分。
site-packages
文件夹中。 - Edward我曾经遇到一个问题,需要导入一个Flask应用程序,其中还有一个需要导入单独文件夹中的文件的导入。这部分内容参考了 Remi的回答,但是假设我们有一个像这样的存储库:
.
└── service
└── misc
└── categories.csv
└── test
└── app_test.py
app.py
pipeline.py
然后,在从app.py
文件中导入app对象之前,我们将目录更改为上一级,这样当我们导入app(它会导入pipeline.py
)时,我们也可以读取其他文件,例如csv文件。
import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
os.chdir('../')
from app import app
os.chdir('./test')
以使您的工作目录不改变。这是对我而言最简单有效的解决方案:
from ptdraft import nib
https://github.com/fx-kirin/add_parent_path
# Just add parent path
add_parent_path(1)
# Append to syspath and delete when the exist of with statement.
with add_parent_path(1):
# Import modules in the parent path
pass
虽然这违反了所有规则,但我仍然想提到这种可能性:
您可以先将文件从父目录复制到子目录。接下来导入它,然后删除已复制的文件:
例如在life.py
中:
import os
import shutil
shutil.copy('../nib.py', '.')
import nib
os.remove('nib.py')
# now you can use it just fine:
nib.foo()
sys.path
中(如其他答案中所建议的)。复制/移除文件会引入对文件位置的非常紧密的依赖关系,当未来更改项目时可能会被忽略(从而使脚本不够健壮)。此外,它还会防止文件被缓存,并且当然也会为所需的IO创建轻微的开销。 - Kim
__init__.py
文件了。S.Lott: 我不知道该如何检查... - Ram Rachumsys.path
或者PYTHONPATH
的答案,查看 np8 的优秀回答。是的,它很长。是的,看起来需要很多工作。但这是唯一一个真正正确且干净地解决问题的答案。 - Aran-Fey