Python setuptools依赖项和导入问题
我对python中的setuptools还不太熟悉。我最近在我的项目中添加了一个依赖项,并且遇到了一个依赖项问题。问题是:Python setuptools依赖项和导入问题,python,setuptools,Python,Setuptools,我对python中的setuptools还不太熟悉。我最近在我的项目中添加了一个依赖项,并且遇到了一个依赖项问题。问题是: try: from setuptools import setup except ImportError: from distutils.core import setup from mypackage import VERSION setup( name='mypackage', ... version=VERSION,
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
,因此setup.py在新安装时失败(six尚未安装),原因是来自mypackage导入版本的行。我通过入侵一个虚拟模块导入(见下文)解决了这个问题,但我真的希望有一个更好的方法,不需要我在两个位置或一个单独的文件中维护版本号
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()
你不能这样做吗
from pkg_resources import require
version = require("module_name")[0].version
否则,您可以尝试在init.py中编写版本,但老实说,我不知道这是否是一种好的做法。您不能这样做吗
from pkg_resources import require
version = require("module_name")[0].version
否则,您可以尝试在init.py中编写版本,但老实说,我不知道这是否是一种好的做法。作为一般规则,不要从setup.py
导入包,因为(正如您所意识到的)如果您尚未安装所有依赖项,则无法安装包
相反,按照建议,创建一个单独的模块version.py
(或类似模块),而不需要定义version
。在您的setup.py
doexecfile('mypackage/version.py')
中,您可以访问version
,而无需任何恶意或不安全的黑客攻击
正如medmunds指出的那样,execfile
在Python 3中不可用,因此请改用:
with open('mypackage/version.py') as f:
exec(f.read())
一般来说,不要从setup.py
导入软件包,因为(正如您所意识到的那样)如果您尚未安装所有依赖项,则无法安装软件包
相反,按照建议,创建一个单独的模块version.py
(或类似模块),而不需要定义version
。在您的setup.py
doexecfile('mypackage/version.py')
中,您可以访问version
,而无需任何恶意或不安全的黑客攻击
正如medmunds指出的那样,execfile
在Python 3中不可用,因此请改用:
with open('mypackage/version.py') as f:
exec(f.read())
在提出这个问题后,我发布了几个月以来一直在使用的解决方案。感谢kynan间接地提醒我回答这个问题。虽然kynan发布的解决方案很棒,但我个人不喜欢只为版本号添加一个文件,因为这意味着版本号将保存在package.version.version下的程序中。指示版本号应位于包或模块名称空间的顶级,位于名称\uuuuu version\uuuuu
下
我现在使用的解决方案使用一个简单的正则表达式来解析python程序中定义\uuuuu version\uuuu
的行中的版本号。它看起来像:
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()
与
在提出这个问题后,我发布了几个月以来一直在使用的解决方案。感谢kynan间接地提醒我回答这个问题。虽然kynan发布的解决方案很棒,但我个人不喜欢只为版本号添加一个文件,因为这意味着版本号将保存在package.version.version下的程序中。指示版本号应位于包或模块名称空间的顶级,位于名称\uuuuu version\uuuuu
下
我现在使用的解决方案使用一个简单的正则表达式来解析python程序中定义\uuuuu version\uuuu
的行中的版本号。它看起来像:
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()
与
虽然其他人恰当地指出,从setup.py导入您自己的包不是一个很好的做法,但在某些情况下,这种情况会以不同的方式出现——实际的安装过程需要一些包,这些包在所有依赖项安装完成后才可用
在这些情况下,setuptools提供了一个解决方案:
from setuptools import setup
setup(
name='mypackage',
...
version=VERSION,
packages=['mypackage'],
setup_requires=['six'],
install_requires=['six'])
这实际上会在安装过程运行时下载六的本地副本。它还将正确地将six安装到您当前的环境中,以便在安装过程完成后可以使用。而其他人则适当地指出,从setup.py导入您自己的软件包不是一个很好的做法,在某些情况下,这种情况会以不同的方式出现——实际的安装过程需要一些软件包,这些软件包在安装完所有依赖项之后才可用
在这些情况下,setuptools提供了一个解决方案:
from setuptools import setup
setup(
name='mypackage',
...
version=VERSION,
packages=['mypackage'],
setup_requires=['six'],
install_requires=['six'])
这实际上会在安装过程运行时下载六的本地副本。它还将正确地将six安装到您当前的环境中,以便在安装过程完成后可以使用。此方法遇到相同的问题:pkg\u resources.DistributionNotFound:six
。事实上,您不应该需要six,而应该需要“mypackage”!是的,我在那里就是这么做的。mypackage.\uuuu init\uuuuuuuuuy.py包含行import six
,因此该错误和原始问题。此方法遇到相同的问题:pkg\u resources.DistributionNotFound:six
。事实上,您不应该需要六行,而是需要“mypackage”!是的,我在那里就是这么做的。mypackage.\uuuuu init\uuuuuuuuuy.py包含行import six
,因此出现了错误和原始问题。我忘了我发布了这个问题。另一个线程有一些很好的建议,其中一个类似于我现在的做法。很快添加我的解决方案。我对execfile
解决方案非常满意,但它在Python 3上不起作用。好的,对于Python 2和3,使用和open('mypackage/version.py')作为f:exec(f.read())
代替execfile('mypackage/version.py')
。我忘了我贴了这封信