我尝试阅读有关同级导入的问题,甚至 package documentation ,但我还没有找到答案。
结构如下:
├── LICENSE.md
├── README.md
├── api
│ ├── __init__.py
│ ├── api.py
│ └── api_key.py
├── examples
│ ├── __init__.py
│ ├── example_one.py
│ └── example_two.py
└── tests
│ ├── __init__.py
│ └── test_one.py
examples
和 tests
目录下的脚本如何从
api
模块并从命令行运行?
另外,我想避免对每个文件进行丑陋的 sys.path.insert
hack。一定
这可以在 Python 中完成,对吧?
最佳答案
厌倦了 sys.path hack?
有很多sys.path.append
-hacks 可用,但我找到了解决手头问题的替代方法。
总结
- 将代码打包到一个文件夹中(例如
packaged_stuff
) - 创建
setup.py
您使用的脚本setuptools.setup() . (请参阅下面的最小setup.py
) - 使用
pip install -e <myproject_folder>
将包安装到可编辑状态 - 使用
from packaged_stuff.modulename import function_name
导入
设置
起点是您提供的文件结构,包含在一个名为 myproject
的文件夹中.
.
└── myproject
├── api
│ ├── api_key.py
│ ├── api.py
│ └── __init__.py
├── examples
│ ├── example_one.py
│ ├── example_two.py
│ └── __init__.py
├── LICENCE.md
├── README.md
└── tests
├── __init__.py
└── test_one.py
我会调用.
根文件夹,在我的示例中,它位于 C:\tmp\test_imports\
.
api.py
作为测试用例,我们使用下面的./api/api.py
def function_from_api():
return 'I am the return value from api.api!'
test_one.py
from api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
尝试运行 test_one:
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\myproject\tests\test_one.py", line 1, in <module>
from api.api import function_from_api
ModuleNotFoundError: No module named 'api'
尝试相对导入也不起作用:
使用 from ..api.api import function_from_api
会导致
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\tests\test_one.py", line 1, in <module>
from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package
步骤
- 将 setup.py 文件添加到根目录
setup.py
的内容会是*
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
- 使用虚拟环境
如果您熟悉虚拟环境,请激活一个,然后跳到下一步。 虚拟环境的使用不是绝对 必需的,但它们会从长远来看,真的 可以帮助您(当您有多个正在进行的项目时......)。最基本的步骤是(在根文件夹中运行)
- 创建虚拟环境
-
python -m venv venv
-
- 激活虚拟环境
-
source ./venv/bin/activate
(Linux, macOS) 或./venv/Scripts/activate
(赢)
-
要了解更多信息,只需谷歌搜索“python 虚拟环境教程”或类似内容。除了创建、激活和停用之外,您可能永远不需要任何其他命令。
创建并激活虚拟环境后,您的控制台应在括号中给出虚拟环境的名称
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
你的文件夹树应该是这样的**
.
├── myproject
│ ├── api
│ │ ├── api_key.py
│ │ ├── api.py
│ │ └── __init__.py
│ ├── examples
│ │ ├── example_one.py
│ │ ├── example_two.py
│ │ └── __init__.py
│ ├── LICENCE.md
│ ├── README.md
│ └── tests
│ ├── __init__.py
│ └── test_one.py
├── setup.py
└── venv
├── Include
├── Lib
├── pyvenv.cfg
└── Scripts [87 entries exceeds filelimit, not opening dir]
- 以可编辑状态 pip 安装您的项目
安装您的顶级软件包myproject
使用 pip
.诀窍是使用 -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
- 添加
myproject.
进入你的进口
请注意,您必须添加 myproject.
仅适用于否则无法正常工作的进口。不使用 setup.py
的导入& pip install
仍然可以正常工作。请参阅下面的示例。
测试解决方案
现在,让我们使用 api.py
测试解决方案上面定义的,和 test_one.py
定义如下。
test_one.py
from myproject.api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
运行测试
(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!
* 见 setuptools docs获取更详细的 setup.py 示例。
** 实际上,您可以将虚拟环境放在硬盘上的任何位置。
关于python - 兄弟包导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6323860/