具有 OS 特定依赖项的 pip 包
pip package with OS specififc dependency
我想创建一个依赖于某些 OS 特定文件的 pip 包:
假设有:
- dependency_Windows_x86_64.zip
- dependency_Linux_x86_64.zip
- dependency_MAC_OS_X.zip
我不想将所有三个存档都包含在一个包项目中,而是在 pip install my-package
期间根据用户的 OS 动态下载它们。我怎样才能做到这一点 ?我应该把负责 downloading/unzipping 这些文件的代码放在哪里?
我的setup.py看起来像这样:
from setuptools import setup
setup(
name='my-package',
version='0.0.1',
description='Package description',
py_modules=['my_package'],
package_dir={'': 'src'},
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7'
],
python_requires='>=3.7'
)
第一个答案是放弃并使用 setuptools
。查看 Platform specific dependencies 以详细了解该怎么做。
第二个答案是制作单独的包,例如'mylib-mac'、'mylib-win'、'mylib-linux'。
第三个答案是使用 "console_script" 方法。这会破裂。虽然它在 Windows 上生成 .exe 文件,但它有奇怪的故障模式。此外,一些用户将无法动态下载文件,因为他们从存储库的内部克隆工作。生产环境中随机 运行 来自 Internet 的代码会吓到人。
希望对您有所帮助!
一个解决方案可能是发布您项目的平台特定 Python wheels。可以通过自定义 setuptools 命令(可能是 build 的子命令,或者 安装).
这不是一个完整的解决方案,但这样的事情可能是一个好的开始:
#!/usr/bin/env python3
import distutils.command.build
import setuptools
class build_something(setuptools.Command):
user_options = [
('plat-name=', 'p', "platform name to build for"),
]
def initialize_options(self):
self.plat_name = None
def finalize_options(self):
self.set_undefined_options('bdist_wheel', ('plat_name', 'plat_name'))
def run(self):
print(" *** plat_name: {} ***".format(self.plat_name))
print(" *** download the platform specific bits to 'build' ***")
class build(distutils.command.build.build):
sub_commands = [(
'build_something',
None,
)] + distutils.command.build.build.sub_commands
setuptools.setup(
cmdclass={
'build_something': build_something,
'build': build,
},
# ...
)
然后 Python 轮子可以这样构建:
$ ./setup.py bdist_wheel -p win_amd64
平台特定的依赖项可以保存在单独的 Python 项目中(围绕仅数据包的包装器),然后从主项目中需要,如下所示:
# setup.cfg
# ...
[options]
install_requires =
my_package_win_amd64 ; platform_system=="Windows" and platform_machine=="x86_64"
my_package_linux-x86_64 ; platform_system=="Linux" and platform_machine=="x86_64"
此方法不依赖于 setuptools,可以与其他构建系统一起使用。
我想创建一个依赖于某些 OS 特定文件的 pip 包:
假设有:
- dependency_Windows_x86_64.zip
- dependency_Linux_x86_64.zip
- dependency_MAC_OS_X.zip
我不想将所有三个存档都包含在一个包项目中,而是在 pip install my-package
期间根据用户的 OS 动态下载它们。我怎样才能做到这一点 ?我应该把负责 downloading/unzipping 这些文件的代码放在哪里?
我的setup.py看起来像这样:
from setuptools import setup
setup(
name='my-package',
version='0.0.1',
description='Package description',
py_modules=['my_package'],
package_dir={'': 'src'},
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7'
],
python_requires='>=3.7'
)
第一个答案是放弃并使用 setuptools
。查看 Platform specific dependencies 以详细了解该怎么做。
第二个答案是制作单独的包,例如'mylib-mac'、'mylib-win'、'mylib-linux'。
第三个答案是使用 "console_script" 方法。这会破裂。虽然它在 Windows 上生成 .exe 文件,但它有奇怪的故障模式。此外,一些用户将无法动态下载文件,因为他们从存储库的内部克隆工作。生产环境中随机 运行 来自 Internet 的代码会吓到人。
希望对您有所帮助!
一个解决方案可能是发布您项目的平台特定 Python wheels。可以通过自定义 setuptools 命令(可能是 build 的子命令,或者 安装).
这不是一个完整的解决方案,但这样的事情可能是一个好的开始:
#!/usr/bin/env python3
import distutils.command.build
import setuptools
class build_something(setuptools.Command):
user_options = [
('plat-name=', 'p', "platform name to build for"),
]
def initialize_options(self):
self.plat_name = None
def finalize_options(self):
self.set_undefined_options('bdist_wheel', ('plat_name', 'plat_name'))
def run(self):
print(" *** plat_name: {} ***".format(self.plat_name))
print(" *** download the platform specific bits to 'build' ***")
class build(distutils.command.build.build):
sub_commands = [(
'build_something',
None,
)] + distutils.command.build.build.sub_commands
setuptools.setup(
cmdclass={
'build_something': build_something,
'build': build,
},
# ...
)
然后 Python 轮子可以这样构建:
$ ./setup.py bdist_wheel -p win_amd64
平台特定的依赖项可以保存在单独的 Python 项目中(围绕仅数据包的包装器),然后从主项目中需要,如下所示:
# setup.cfg
# ...
[options]
install_requires =
my_package_win_amd64 ; platform_system=="Windows" and platform_machine=="x86_64"
my_package_linux-x86_64 ; platform_system=="Linux" and platform_machine=="x86_64"
此方法不依赖于 setuptools,可以与其他构建系统一起使用。