在单个 `setup.py` 中多次调用 `setup()` 是否安全?
Is it safe to call `setup()` multiple times in a single `setup.py`?
我正在开发一个包含 Cython 扩展的包。
根据 https://github.com/pypa/pip/issues/1958,我将使用 setup_requires
并推迟导入 Cython
。
我想到的最佳解决方案是在 setup.py
:
中调用 setup()
两次
... # initial imports
setup(setup_requires=['cython'])
from Cython.Build import cythonize
bar = Extension('foo.bar', sources = ['bar.pyx'])
setup(name = 'foo',
... # parameters
ext_modules = cythonize([bar]),
... # more parameters
)
不过我觉得 setup()
的名字暗示它应该只被调用一次。像我这样多次调用安全吗?
我不能只分发轮子,因为 Linux 用户也可以使用该软件包。
[编辑]
我还认为这个问题比处理编译器依赖性问题更笼统。人们可能想要导入一些包(例如 sphinx
或 pweave
)来预处理包的描述。
简单的答案是:否。调用安装程序后,它将解析命令行参数并开始执行其工作。
至于Cython
依赖,setup_requires
这里帮不上忙。它可能会在不安装的情况下尝试下载 Cython
。正如 SpotlightKid 评论的那样:
distutils doesn't try to be a compiler or install gcc as a dependency either
this argument (setup_requires) is needed if you are using distutils extensions,
因此,不适用于 Cython
.
这样的包
我认为用户有责任在调用 setup.py
之前安装 Cython
。如果您想提供更友好的错误信息,请尝试使用
try:
from Cython.Build import cythonize
except ImportError:
# Kindly ask the user to install Cython
以下帖子可能有所帮助:
- Install package which has setup_requires ...
- setup_requires for dev environments
我有一个不同的场景,我需要多次 运行 setup()
:在我的例子中,我从相同的来源构建了两个包。第一个包是基于 Fabric
的命令行工具,第二个包只是库(API、工具等)。对于这么小的项目,将项目拆分为两个存储库似乎太不切实际,因为 CLI 部分是实际上只是一个包装纸。 运行 setup()
多次使用不同的参数导致构建因各种错误(主要是丢失文件)而崩溃。我的解决方案是 运行 每个 setup()
都不同 Process
:
from setuptools import setup, find_packages
from multiprocessing import Process
if __name__ == '__main__':
setups = [
{
'name': 'cli-tool',
'description': 'Some description...',
'packages': find_packages(),
'entry_points': {
'console_scripts': [
'cli-tool = fabfile:main'
]
},
'...': 'etc. needed for setup() ...'
},
{
'name': 'cli-tool-lib',
'packages': find_packages(exclude=('fabfile',)),
'...': 'etc.'
}
]
for s in setups:
name = s['name']
print("Building '{}'.".format(name))
p = Process(target=setup, kwargs=s)
p.start()
p.join()
print("Building of '{}' done.\n".format(name))
我正在开发一个包含 Cython 扩展的包。
根据 https://github.com/pypa/pip/issues/1958,我将使用 setup_requires
并推迟导入 Cython
。
我想到的最佳解决方案是在 setup.py
:
setup()
两次
... # initial imports
setup(setup_requires=['cython'])
from Cython.Build import cythonize
bar = Extension('foo.bar', sources = ['bar.pyx'])
setup(name = 'foo',
... # parameters
ext_modules = cythonize([bar]),
... # more parameters
)
不过我觉得 setup()
的名字暗示它应该只被调用一次。像我这样多次调用安全吗?
我不能只分发轮子,因为 Linux 用户也可以使用该软件包。
[编辑]
我还认为这个问题比处理编译器依赖性问题更笼统。人们可能想要导入一些包(例如 sphinx
或 pweave
)来预处理包的描述。
简单的答案是:否。调用安装程序后,它将解析命令行参数并开始执行其工作。
至于Cython
依赖,setup_requires
这里帮不上忙。它可能会在不安装的情况下尝试下载 Cython
。正如 SpotlightKid 评论的那样:
distutils doesn't try to be a compiler or install gcc as a dependency either
this argument (setup_requires) is needed if you are using distutils extensions,
因此,不适用于 Cython
.
我认为用户有责任在调用 setup.py
之前安装 Cython
。如果您想提供更友好的错误信息,请尝试使用
try:
from Cython.Build import cythonize
except ImportError:
# Kindly ask the user to install Cython
以下帖子可能有所帮助:
- Install package which has setup_requires ...
- setup_requires for dev environments
我有一个不同的场景,我需要多次 运行 setup()
:在我的例子中,我从相同的来源构建了两个包。第一个包是基于 Fabric
的命令行工具,第二个包只是库(API、工具等)。对于这么小的项目,将项目拆分为两个存储库似乎太不切实际,因为 CLI 部分是实际上只是一个包装纸。 运行 setup()
多次使用不同的参数导致构建因各种错误(主要是丢失文件)而崩溃。我的解决方案是 运行 每个 setup()
都不同 Process
:
from setuptools import setup, find_packages
from multiprocessing import Process
if __name__ == '__main__':
setups = [
{
'name': 'cli-tool',
'description': 'Some description...',
'packages': find_packages(),
'entry_points': {
'console_scripts': [
'cli-tool = fabfile:main'
]
},
'...': 'etc. needed for setup() ...'
},
{
'name': 'cli-tool-lib',
'packages': find_packages(exclude=('fabfile',)),
'...': 'etc.'
}
]
for s in setups:
name = s['name']
print("Building '{}'.".format(name))
p = Process(target=setup, kwargs=s)
p.start()
p.join()
print("Building of '{}' done.\n".format(name))