如何在Python中以编程方式获取已安装模块的版本?
对于这些模块:
required_modules = ['nose', 'coverage', 'webunit', 'MySQLdb', 'pgdb', 'memcache']
以及程序:
required_programs = ['psql', 'mysql', 'gpsd', 'sox', 'memcached']
大概是这样的:
# Report on the versions of programs installed
for module in required_modules:
try:
print module.__version__
except:
exit
2 个回答
-1
我发现使用各种工具来获取版本信息并不太可靠(包括moraes的回答中提到的最好用的pkg_resources
),因为大多数工具并不能覆盖所有情况。
在Python中,版本号可能会出现在不同的地方,具体取决于情况:
对于模块和包,版本号通常在可选的
__version__
属性中,这是PEP396推荐的。如果子包和子模块没有这个属性,默认情况下应该继承父包的版本号。对于分发的模块和包,版本号在
Version
元数据字段中,这个字段的位置由PEP345规定:- 对于构建的轮子分发(PEP427),版本号在
dist-info
目录中,同时也在dist-info文件夹的名称中。 - 对于构建的蛋分发(setuptools的旧格式),版本号在
egg-info
目录中,同样也在egg-info文件夹的名称中。
- 对于构建的轮子分发(PEP427),版本号在
最后,对于内置模块和包,默认版本应该继承自Python系统的版本,除非被覆盖。
此外,在运行时(也就是你需要这个版本号的时候),包和模块可能会:
- 已经被导入,或者没有被导入
- 已经构建并通过pip安装(无论是否在调试模式下),或者仅仅是添加到PYTHON PATH(sys.path)中
- 没有构建并添加到PYTHON PATH(sys.path)中
这种多样的设置使得现有的解决方案很难处理这个问题的所有方面。pkg_resources
可能是目前获取版本信息的最佳方式,但例如当一个包是解压的轮子并添加到PYTHON PATH时,它就无法工作。此外,它也不支持内置模块。
因为我们需要一个可靠的方法来获取任何包、模块或子模块的版本,我最终写了getversion。它实现了一系列策略,直到找到有效的方法。
使用起来非常简单:
from getversion import get_module_version
# Get the version of an imported module
from xml import dom
version, details = get_module_version(dom)
特别是details
提供了关于如何获取版本标志的有用提示:
> print(details)
Version '3.7.3.final.0' found for module 'xml.dom' by strategy 'get_builtin_module_version', after the following failed attempts:
- Attempts for module 'xml.dom':
- <get_module_version_attr>: module 'xml.dom' has no attribute '__version__'
- Attempts for module 'xml':
- <get_module_version_attr>: module 'xml' has no attribute '__version__'
- <get_version_using_pkgresources>: Invalid version number: None
- <get_builtin_module_version>: SUCCESS: 3.7.3.final.0
3
很遗憾,并不是所有的模块都有module.__version__
这个属性。
一个解决办法是使用包管理工具。当你通过easy_install或pip安装一个库时,它会记录下你安装的版本。然后你可以这样做:
import pkg_resources
version = pkg_resources.get_distribution("nose").version