Python 最佳实践:如何在 setup.py 中列出所需的依赖项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15422527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best practices: how do you list required dependencies in your setup.py?
提问by CppLearner
This is how I do it currently:
这就是我目前的做法:
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
requires = [
'pyramid',
'pyramid_debugtoolbar',
'waitress',
'requests',
'mock',
'gunicorn',
'mongoengine',
]
setup(name='repoapi',
version='0.0',
description='repoapi',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=requires,
tests_require=requires,
test_suite="repoapi",
entry_points="""\
[paste.app_factory]
main = repoapi:main
""",
)
Is this an okay way? I have some troubles. For example, for pyramid, I cannot use the system-wide nosetests plugin to run tests. I need to install pyramidin the global python site-packages!
这是一个好的方法吗?我有一些麻烦。例如,对于pyramid,我不能使用系统范围的nosetests 插件来运行测试。我需要安装pyramid在全局python站点包中!
But I don't want that. So I must install nose in the virtualenv of this project. But I don't want it to be a dependency. I don't feel like it should belong to requires. It isn't. Yet, I also don't want to install by hand all the time. Yeah I know I have a lot of I don't want to do this and that...
但我不想那样。所以我必须在这个项目的 virtualenv 中安装nose。但我不希望它成为一种依赖。我觉得它不应该属于requires. 不是。然而,我也不想一直手动安装。是的,我知道我有很多我不想做这个和那个...
But how would you solve that? I don't want to tamper the global python site-packages, but I want to install nose as part of the virtualenv.
但是你会怎么解决呢?我不想篡改全局 python 站点包,但我想将鼻子安装为 virtualenv 的一部分。
Also, pip install requirement files. It's slightly more accurate because I don't need to specify the version manually and I don't need to be afraid of updating setup.py manually. Just throw pip freeze > file.txtand done.
此外,pip 安装要求文件。它稍微准确一些,因为我不需要手动指定版本,也不需要害怕手动更新 setup.py。只需扔就pip freeze > file.txt完成了。
However, pip can return garbage because we throw garbage packages into virtualenv.
但是,pip 可以返回垃圾,因为我们将垃圾包扔到 virtualenv 中。
So many blades. What's the best practice? How do you deal with these issues?
这么多刀片。最佳做法是什么?你如何处理这些问题?
Maybe I missed it, but https://github.com/django/django/blob/master/setup.py, how did Django do it?
也许我错过了,但是https://github.com/django/django/blob/master/setup.py,Django 是怎么做到的?
采纳答案by Tom Offermann
You can split up your requirements into "install" dependencies and "test" dependencies like this:
您可以将您的需求拆分为“安装”依赖项和“测试”依赖项,如下所示:
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
install_requires = [
'pyramid',
'pyramid_debugtoolbar',
'waitress',
'requests',
'gunicorn',
'mongoengine',
]
tests_require = [
'mock',
'nose',
]
setup(name='repoapi',
...
install_requires=install_requires,
tests_require=tests_require,
test_suite="nose.collector",
...
)
This way, when someone installs the package, only the "install" dependencies are installed. So, if someone only wants to use the package (and they aren't interested in running the tests), then they don't have to install the test dependencies.
这样,当有人安装软件包时,只会安装“安装”依赖项。因此,如果有人只想使用该包(并且他们对运行测试不感兴趣),那么他们就不必安装测试依赖项。
When you do want to run the tests, you can use this:
当您确实想运行测试时,可以使用以下命令:
$ python setup.py test
Per the docs:
根据文档:
Note that these required projects will not be installed on the system where the tests are run, but only downloaded to the project's setup directory if they're not already installed locally.
请注意,这些必需的项目不会安装在运行测试的系统上,如果它们尚未在本地安装,则只会下载到项目的安装目录。
Once the "test" dependencies are in place, then it will run the "test_suite" command. Since you mentioned nose as your preferred test runner, I showed how you use "nose.collector"to configure that.
一旦“测试”依赖项就位,它将运行“test_suite”命令。由于您提到鼻子是您首选的测试运行器,我展示了您如何使用“nose.collector”来配置它。
Incidentally, the Django setup.py is not the cleanest example for understanding the basics of setuptools. I think the Sentry setup.pyis a better example to learn from.
顺便说一句,Django setup.py 并不是理解 setuptools 基础知识的最干净的例子。我认为Sentry setup.py是一个更好的学习例子。
回答by Peter K
If you are using requirement files, then an alternative would be to read their content instead of duplicating it:
如果您正在使用需求文件,那么另一种方法是读取它们的内容而不是复制它:
import pathlib
from setuptools import setup, find_packages
HERE = pathlib.Path(__file__).parent
INSTALL_REQUIRES = (HERE / "requirements.txt").read_text().splitlines()
TESTS_REQUIRE = (HERE / "test-requirements.txt").read_text().splitlines()[1:]
setup(...,
install_requires=INSTALL_REQUIRES,
tests_require=TESTS_REQUIRE,
...
)
I find this approach much more stable and less prone to errors, since requirements change sometimes and one often forgets to update two places.
我发现这种方法更稳定,更不容易出错,因为有时需求会发生变化,人们经常忘记更新两个地方。
Note: notice the TESTS_REQUIREstart from the second line, this is due to the fact that the first line of test-requirements.txtis often -r requirements.txt. Feel free to change it if your case is different.
注意:注意TESTS_REQUIRE从第二行开始,这是因为第一行test-requirements.txt通常是-r requirements.txt。如果您的情况不同,请随意更改它。

