如何使用子包正确打包 Python3 应用程序
How to correctly package Python3 app with subpackages
我有一个包 s3_backend
,它包含一个模块 api.py
,还有一个子包 util
,它本身包含 5 个模块。我想将它打包并上传到 PyPI,这样人们就可以 pip install package
并在顶级包中使用脚本 api、api.py
。两个包(s3_backend
和 's3_backend.util')都包含 _init__.py 个文件。
整个项目保存在目录名称project
中,结构如下
project
|- s3_backend (package)
|- __init__.py
|- util (package)
|- __init__.py
|- module1.py
|...
|- module5.py
|- api.py
|- setup.py
api.py
本身导入 modules1-4
.
在本地,在 project
内,我可以做到
导入 api
api.func1()...
没有错误。当我将包上传到 TestPyPI,并将包安装在新目录的 virtualenv 中时,我 运行 遇到了问题,这些问题可以追溯到 api.py
中的导入语句,该语句从 modules1-4
子包 s3_backend.util
。
这一行
从 util 导入模块 1、模块 2、模块 3、模块 4
抛出这个错误
没有模块名称 "util"
当我 运行 这个命令
从 s3_backend 导入实用程序
我可以成功
import s3_backend
和
help(s3_backend)
显示
api.py
util (package)
我的setup.py内容如下图。在我的 setup.py 中处理子包的正确方法是什么?我是否写错了导入语句?
为了修复,我尝试替换
from util import ...
和
from .util import ...
和
from s3_backend.util import ...
但是那些在本地引起了问题。
setup.py 的源代码:
# project/setup.py
from distutils.core import setup
setup(
name='s3_backend',
version='0.1.7',
license='MIT',
description='scripting api for file upload to s3',
author='SkippyElvis',
author_email='Skippy@Elvis.com',
url='https://github.com/jackhwolf/s3_backend',
keywords=['aws', 's3', 'file upload'],
packages=['s3_backend', 's3_backend.util'],
classifiers=[
'Programming Language :: Python :: 3',
],
)
在 api.py 中导入语句:
from util import module1, module2, module3, module4
如果您还需要帮助我,请告诉我。谢谢!
SkippyElvis
您可以尝试使用 setuptools 代替吗? find_packages 函数可以很好地工作,只要你在每个要包含的文件夹中都有一个 init.py 文件。
这是您需要在 setup.py
中使用的内容
# project/setup.py
from setuptools import setup, find_packages
setup(
name='s3_backend',
version='0.1.7',
license='MIT',
description='scripting api for file upload to s3',
author='SkippyElvis',
author_email='Skippy@Elvis.com',
url='https://github.com/jackhwolf/s3_backend',
keywords=['aws', 's3', 'file upload'],
packages=find_packages(),
classifiers=[
'Programming Language :: Python :: 3',
],
)
否则,您可以编写一个函数来模仿 find_packages。我不建议这样做。
至于您的导入,我提倡使用绝对 root-level 导入。这强制执行两件事:它确保您在内部使用您的库的方式与您的用户使用它的方式相同。此外,它还确保您不会尝试从某个文件夹中测试您的代码,而是通过测试调用它。 "enforces" 的方式就是,您的绝对导入在某些文件夹内不起作用。它需要通过外部 file/function 调用来调用。
我有一个包 s3_backend
,它包含一个模块 api.py
,还有一个子包 util
,它本身包含 5 个模块。我想将它打包并上传到 PyPI,这样人们就可以 pip install package
并在顶级包中使用脚本 api、api.py
。两个包(s3_backend
和 's3_backend.util')都包含 _init__.py 个文件。
整个项目保存在目录名称project
中,结构如下
project
|- s3_backend (package)
|- __init__.py
|- util (package)
|- __init__.py
|- module1.py
|...
|- module5.py
|- api.py
|- setup.py
api.py
本身导入 modules1-4
.
在本地,在 project
内,我可以做到
导入 api
api.func1()...
没有错误。当我将包上传到 TestPyPI,并将包安装在新目录的 virtualenv 中时,我 运行 遇到了问题,这些问题可以追溯到 api.py
中的导入语句,该语句从 modules1-4
子包 s3_backend.util
。
这一行 从 util 导入模块 1、模块 2、模块 3、模块 4 抛出这个错误 没有模块名称 "util" 当我 运行 这个命令 从 s3_backend 导入实用程序
我可以成功
import s3_backend
和
help(s3_backend)
显示
api.py
util (package)
我的setup.py内容如下图。在我的 setup.py 中处理子包的正确方法是什么?我是否写错了导入语句?
为了修复,我尝试替换
from util import ...
和
from .util import ...
和
from s3_backend.util import ...
但是那些在本地引起了问题。
setup.py 的源代码:
# project/setup.py
from distutils.core import setup
setup(
name='s3_backend',
version='0.1.7',
license='MIT',
description='scripting api for file upload to s3',
author='SkippyElvis',
author_email='Skippy@Elvis.com',
url='https://github.com/jackhwolf/s3_backend',
keywords=['aws', 's3', 'file upload'],
packages=['s3_backend', 's3_backend.util'],
classifiers=[
'Programming Language :: Python :: 3',
],
)
在 api.py 中导入语句:
from util import module1, module2, module3, module4
如果您还需要帮助我,请告诉我。谢谢!
SkippyElvis
您可以尝试使用 setuptools 代替吗? find_packages 函数可以很好地工作,只要你在每个要包含的文件夹中都有一个 init.py 文件。
这是您需要在 setup.py
中使用的内容# project/setup.py
from setuptools import setup, find_packages
setup(
name='s3_backend',
version='0.1.7',
license='MIT',
description='scripting api for file upload to s3',
author='SkippyElvis',
author_email='Skippy@Elvis.com',
url='https://github.com/jackhwolf/s3_backend',
keywords=['aws', 's3', 'file upload'],
packages=find_packages(),
classifiers=[
'Programming Language :: Python :: 3',
],
)
否则,您可以编写一个函数来模仿 find_packages。我不建议这样做。
至于您的导入,我提倡使用绝对 root-level 导入。这强制执行两件事:它确保您在内部使用您的库的方式与您的用户使用它的方式相同。此外,它还确保您不会尝试从某个文件夹中测试您的代码,而是通过测试调用它。 "enforces" 的方式就是,您的绝对导入在某些文件夹内不起作用。它需要通过外部 file/function 调用来调用。