setup.py 中的条件要求
Conditional requirements in setup.py
我正在编写一个 library that's dependent on file-magic, which works just fine for most platforms, but in Alpine Linux, file-magic won't work so I need to instead use the python-magic 库。
现在我知道如何编写自己的代码来处理不同的 Python 库 API,但我不知道如何编写我的 setup.cfg
或 setup.py
根据我们进行安装的系统有不同的要求。
我认为最好的选择是使用 PEP 508 规则,但我不知道如何说 "libmagic like Alpine" 或该语法中的其他内容,更不用说它是否适用于一个包的 setup.py。事实上,如果不安装 file-magic
并看着它死掉,我什至无法弄清楚如何分辨架构之间的区别:-(
当然,对于这种事情一定有最佳实践吗?
更新
在从下面的 Tim 那里获得了更广泛的理解之后,我拼凑了这个 hack 来让它工作:
def get_requirements():
"""
Alpine is problematic in how it doesn't play nice with file-magic -- a
module that appears to be the standard for most other Linux distros. As a
work-around for this, we swap out file-magic for python-magic in the Alpine
case.
"""
config = configparser.ConfigParser()
config.read("setup.cfg")
requirements = config["options"]["install_requires"].split()
os_id = None
try:
with open("/etc/os-release") as f:
os_id = [_ for _ in f.readlines() if _.startswith("ID=")][0] \
.strip() \
.replace("ID=", "")
except (FileNotFoundError, OSError, IndexError):
pass
if os_id == "alpine":
requirements[1] = "python-magic>=0.4.15"
return requirements
setuptools.setup(install_requires=get_requirements())
这允许使用 setup.cfg
的声明性语法,但如果安装目标是 Alpine 系统,则会调整 install_requires
值。
您可能想使用 platform module 来尝试识别系统详细信息。
最好的办法是尝试使用 platform.architecture()
、platform.platform()
和 platform.system()
的组合,并适当地处理错误并考虑所有可能的 return 信息。
示例:
我在 Win10 上 运行,这是这些函数的输出(还有一个):
>>> import platform
>>> print(platform.architecture())
('32bit', 'WindowsPE')
>>> print(platform.platform())
Windows-10-10.0.17134-SP0
>>> print(platform.processor())
Intel64 Family 6 Model 142 Stepping 10, GenuineIntel
>>> print(platform.system())
Windows
编辑
以上答案不一定return您想要的信息(我没有提及平台模块中任何已弃用的功能)。
深入挖掘,得到 this SO result,这说明用于收集发行版名称的内置平台功能已被弃用。
官方文档指向一个名为 distro 的 PyPi 包。 PyPi 上的发行版文档承认需要此类信息,并且在那里找到的示例用法如下所示:
>>> import distro
>>> distro.linux_distribution(full_distribution_name=False)
('centos', '7.1.1503', 'Core')
我正在编写一个 library that's dependent on file-magic, which works just fine for most platforms, but in Alpine Linux, file-magic won't work so I need to instead use the python-magic 库。
现在我知道如何编写自己的代码来处理不同的 Python 库 API,但我不知道如何编写我的 setup.cfg
或 setup.py
根据我们进行安装的系统有不同的要求。
我认为最好的选择是使用 PEP 508 规则,但我不知道如何说 "libmagic like Alpine" 或该语法中的其他内容,更不用说它是否适用于一个包的 setup.py。事实上,如果不安装 file-magic
并看着它死掉,我什至无法弄清楚如何分辨架构之间的区别:-(
当然,对于这种事情一定有最佳实践吗?
更新
在从下面的 Tim 那里获得了更广泛的理解之后,我拼凑了这个 hack 来让它工作:
def get_requirements():
"""
Alpine is problematic in how it doesn't play nice with file-magic -- a
module that appears to be the standard for most other Linux distros. As a
work-around for this, we swap out file-magic for python-magic in the Alpine
case.
"""
config = configparser.ConfigParser()
config.read("setup.cfg")
requirements = config["options"]["install_requires"].split()
os_id = None
try:
with open("/etc/os-release") as f:
os_id = [_ for _ in f.readlines() if _.startswith("ID=")][0] \
.strip() \
.replace("ID=", "")
except (FileNotFoundError, OSError, IndexError):
pass
if os_id == "alpine":
requirements[1] = "python-magic>=0.4.15"
return requirements
setuptools.setup(install_requires=get_requirements())
这允许使用 setup.cfg
的声明性语法,但如果安装目标是 Alpine 系统,则会调整 install_requires
值。
您可能想使用 platform module 来尝试识别系统详细信息。
最好的办法是尝试使用 platform.architecture()
、platform.platform()
和 platform.system()
的组合,并适当地处理错误并考虑所有可能的 return 信息。
示例:
我在 Win10 上 运行,这是这些函数的输出(还有一个):
>>> import platform
>>> print(platform.architecture())
('32bit', 'WindowsPE')
>>> print(platform.platform())
Windows-10-10.0.17134-SP0
>>> print(platform.processor())
Intel64 Family 6 Model 142 Stepping 10, GenuineIntel
>>> print(platform.system())
Windows
编辑
以上答案不一定return您想要的信息(我没有提及平台模块中任何已弃用的功能)。
深入挖掘,得到 this SO result,这说明用于收集发行版名称的内置平台功能已被弃用。
官方文档指向一个名为 distro 的 PyPi 包。 PyPi 上的发行版文档承认需要此类信息,并且在那里找到的示例用法如下所示:
>>> import distro
>>> distro.linux_distribution(full_distribution_name=False)
('centos', '7.1.1503', 'Core')