我是python中setuptools的半新手。我最近为我的项目添加了一个依赖项,并遇到了依赖项的问题。这是问题所在:
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
from mypackage import VERSION
setup(
name='mypackage',
...
version=VERSION,
packages=['mypackage'],
install_requires=['six'])
问题是mypackage
导入six
,因此from mypackage import VERSION
行导致全新安装(其中六个尚未安装)的setup.py失败。我通过黑客入侵虚拟模块导入解决了这个问题(见下文),但我真的希望有一种更好的方法,不需要我在两个位置或单独的文件中维护版本号。
try:
import six
except ImportError:
# HACK so we can import the VERSION without needing six first
import sys
class HackObj(object):
def __call__(*args):
return HackObj()
def __getattr__(*args):
return HackObj()
sys.modules['six'] = HackObj()
sys.modules['six.moves'] = HackObj()
答案 0 :(得分:2)
作为一般规则,请勿从setup.py
导入您的软件包,因为(如您所知),如果您尚未安装所有依赖项,则无法安装软件包。
相反,按照建议in this answer,创建一个单独的模块version.py
(或类似的),没有任何外部依赖定义VERSION
。在setup.py
执行execfile('mypackage/version.py')
,您可以访问VERSION
,而不会遇到任何令人讨厌或不安全的黑客攻击。
正如medmunds指出的那样{3}中没有execfile
,所以改为使用:
with open('mypackage/version.py') as f:
exec(f.read())
答案 1 :(得分:1)
我在问这个问题几个月后发布了我一直在使用的解决方案。感谢kynan间接促使我提供这个问题的答案。虽然kynan发布的解决方案很棒,但我个人不喜欢只为版本号添加单个文件,因为这意味着版本号将保存在package.version.version下的程序中。 PEP 396表示版本号应位于名称__version__
下的包或模块名称空间的顶层。
我现在使用的解决方案使用一个简单的正则表达式来解析定义__version__
的python程序中的行的版本号。它看起来像:
import os
import re
PACKAGE_NAME = 'thepackage'
HERE = os.path.abspath(os.path.dirname(__file__))
INIT = open(os.path.join(HERE, PACKAGE_NAME, '__init__.py')).read()
README = open(os.path.join(HERE, 'README.md')).read()
VERSION = re.search("__version__ = '([^']+)'", INIT).group(1)
模块的过程类似,替换
INIT = open(os.path.join(HERE, PACKAGE_NAME, '__init__.py')).read()
与
INIT = open(os.path.join(HERE, '{0}.py'.format(PACKAGE_NAME))).read()
答案 2 :(得分:0)
难道你不能这样做吗?
from pkg_resources import require
version = require("module_name")[0].version
否则你可以尝试在 init .py中编写版本,但我不知道这是不是一个好习惯,老实说。
答案 3 :(得分:0)
虽然其他人已经恰当地指出从setup.py导入你自己的软件包并不是一种非常好的做法,但是有些情况会以不同的方式出现这种情况 - 实际的安装过程需要一些软件包在完成所有依赖项的安装之前,它将无法使用。
在这些情况下,setuptools提供了一个解决方案:
from setuptools import setup
setup(
name='mypackage',
...
version=VERSION,
packages=['mypackage'],
setup_requires=['six'],
install_requires=['six'])
这将实际下载在安装过程运行时可用的六个本地副本。它还将在您当前的环境中正确安装六个,以便在安装过程完成后可以使用它。