我运行的是Python 2.5。
这是我的文件夹树:
ptdraft/
nib.py
simulations/
life/
life.py
(我在每个文件夹中都有__init__.py,为了可读性,这里省略了)
我如何从生命模块内导入nib模块?我希望不需要修改sys.path就可以做到。
注意:正在运行的主模块在ptdraft文件夹中。
我运行的是Python 2.5。
这是我的文件夹树:
ptdraft/
nib.py
simulations/
life/
life.py
(我在每个文件夹中都有__init__.py,为了可读性,这里省略了)
我如何从生命模块内导入nib模块?我希望不需要修改sys.path就可以做到。
注意:正在运行的主模块在ptdraft文件夹中。
当前回答
关于从兄弟包导入的问题,我也发表了类似的回答。你可以在这里看到。
不使用sys.解决方案。路径黑客
总结
将代码打包到一个文件夹中(例如packaged_stuff) 创建一个setup.py脚本,其中使用setuptools.setup()。 使用Pip install -e <myproject_folder>将包安装到可编辑状态 从packaged_stuff导入using。Modulename import function_name
设置
我假设与问题中的文件夹结构相同
.
└── ptdraft
├── __init__.py
├── nib.py
└── simulations
├── __init__.py
└── life
├── __init__.py
└── life.py
我打电话给。在我的例子中,它位于C:\tmp\test_imports。
步骤
在根文件夹中添加一个setup.py文件 -- py的内容可以很简单
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
基本上“任何”setup.py都可以工作。这只是一个最小的工作示例。
使用虚拟环境
如果您熟悉虚拟环境,请激活一个,然后跳转到下一步。使用虚拟环境并不是绝对必需的,但从长远来看,它们确实会帮助你(当你有多个正在进行的项目时)。最基本的步骤是(在根文件夹中运行)
创建虚拟环境 Python -m venv venv 激活虚拟环境 . venv/bin/activate (Linux)或。/venv/Scripts/activate (Win) 禁用虚拟环境 禁用(Linux)
要了解更多信息,请参考谷歌“python virtualenv教程”或类似内容。除了创建、激活和取消激活之外,您可能永远不需要任何其他命令。
创建并激活虚拟环境后,控制台应该在括号中给出虚拟环境的名称
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
PIP在可编辑状态下安装项目
使用pip安装你的顶级包myproject。诀窍是在进行安装时使用-e标志。通过这种方式,它被安装在可编辑状态下,对.py文件的所有编辑都将自动包含在已安装的包中。
在根目录下运行
PIP install -e。(注意这个点,它代表“当前目录”)
您还可以看到它是通过使用pip freeze安装的
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
导入预挂主文件夹到每次导入
在本例中,主文件夹是ptdraft。这样做的好处是,你不会遇到与其他模块名称(来自python标准库或第三方模块)的名称冲突。
示例使用
nib.py
def function_from_nib():
print('I am the return value from function_from_nib!')
life.py
from ptdraft.nib import function_from_nib
if __name__ == '__main__':
function_from_nib()
运行life.py
(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_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
我有一个专门针对git存储库的解决方案。
首先,我使用sys.path.append('..')和类似的解决方案。如果你导入的文件本身使用sys.path.append('..')导入文件,这会导致特别的问题。
然后我决定总是附加git存储库的根目录。在一行中是这样的:
sys.path.append(git.Repo('.', search_parent_directories=True).working_tree_dir)
或者更详细一点,像这样:
import os
import sys
import git
def get_main_git_root(path):
main_repo_root_dir = git.Repo(path, search_parent_directories=True).working_tree_dir
return main_repo_root_dir
main_repo_root_dir = get_main_git_root('.')
sys.path.append(main_repo_root_dir)
对于最初的问题:根据存储库的根目录,导入将是
import ptdraft.nib
or
import nib
虽然这是违反所有规则的,但我还是想提一下这种可能性:
您可以先将文件从父目录复制到子目录。接下来导入它,然后删除复制的文件:
例如,在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()
当然,当nibs尝试使用相对导入/路径导入/读取其他文件时,可能会出现一些问题。
这个问题似乎与模块位于父目录或类似的内容无关。
您需要将包含ptdraft的目录添加到PYTHONPATH
您说导入nib与您一起工作,这可能意味着您将ptdraft本身(而不是其父)添加到PYTHONPATH。
这是对我来说最简单的解决方法:
from ptdraft import nib