Skip to main content
 首页 » 编程设计

python之从源代码(或 Heroku)中找出 Python 版本

2025年05月04日15oomusou

我们运行一个名为 inteokej.nu 的站点,我需要找出它运行的 Python 版本。我已将所有文件拉到我的计算机上,但我不知道是否以及如何从中找出版本号?该站点托管在 Heroku 上,也许有一种方法可以通过某种 Heroku 命令找出版本?

至于现在我没有任何可能更改任何代码(例如添加代码片段以获取版本)。

提前致谢!

请您参考如下方法:

取决于您的需要。 (a) 您正在运行的版本或 (b) .pyc 文件下的版本已编译?

a. 如果您需要知道您正在运行的 python 版本,请执行以下操作:

>>> import sys 
>>> sys.version_info 
sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0) 
>>> print sys.version_info.major 
2 
>>> print sys.version_info.minor 
7 
>>> print sys.version_info.micro 
3 
>>> print '%s.%s.%s' % (sys.version_info.major, sys.version_info.minor, sys.version_info.micro) 
2.7.3 

b.如果想知道某个.pyc文件下的python版本被编译,请执行以下操作:

>>> f = open('somefile.pyc') 
>>> magic = f.read(4) 
>>> magic 
'\x03\xf3\r\n' 
>>> magic.encode('hex') 
'03f30d0a' 
>>> import struct 
>>> struct.unpack("<HH", magic) 
(62211, 2573) 
>>> struct.unpack("<HH", magic)[0] 
62211 

已知值列在 python 源文件 Python/import.c 中。这里是 Python 2.7.10rc1 的已知值:

   Python 1.5:   20121 
   Python 1.5.1: 20121 
   Python 1.5.2: 20121 
   Python 1.6:   50428 
   Python 2.0:   50823 
   Python 2.0.1: 50823 
   Python 2.1:   60202 
   Python 2.1.1: 60202 
   Python 2.1.2: 60202 
   Python 2.2:   60717 
   Python 2.3a0: 62011 
   Python 2.3a0: 62021 
   Python 2.3a0: 62011 (!) 
   Python 2.4a0: 62041 
   Python 2.4a3: 62051 
   Python 2.4b1: 62061 
   Python 2.5a0: 62071 
   Python 2.5a0: 62081 (ast-branch) 
   Python 2.5a0: 62091 (with) 
   Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) 
   Python 2.5b3: 62101 (fix wrong code: for x, in ...) 
   Python 2.5b3: 62111 (fix wrong code: x += yield) 
   Python 2.5c1: 62121 (fix wrong lnotab with for loops and 
                        storing constants that should have been removed) 
   Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) 
   Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode) 
   Python 2.6a1: 62161 (WITH_CLEANUP optimization) 
   Python 2.7a0: 62171 (optimize list comprehensions/change LIST_APPEND) 
   Python 2.7a0: 62181 (optimize conditional branches: 
            introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) 
   Python 2.7a0  62191 (introduce SETUP_WITH) 
   Python 2.7a0  62201 (introduce BUILD_SET) 
   Python 2.7a0  62211 (introduce MAP_ADD and SET_ADD) 

要解决您的问题,您可以递归地遍历目录并从每个 .pyc 文件中提取值,并使用每个值/版本的文件列表填充字典。请参阅以下示例:

import os, struct 
 
your_path = '/your/path' # <- enter your path here 
values = {} 
 
for root, dirs, files in os.walk(your_path): 
    for file in files: 
        if file.endswith('.pyc'): 
            full_path = os.path.join(root, file) 
            value = struct.unpack("<HH", open(full_path).read(4))[0] # <- evtl. enclose this in a try block 
            if not values.has_key(value): 
                values[value] = [] 
            values[value].append(full_path) 
            print '%s %s' % (value, full_path) 
 
for value, files in values.items(): 
    print 'Following files have value %s' % (value) 
    for file in files: 
        print '    %s' % (file) 

如果您在 Linux 下,您可以使用以下一行命令解决您的问题(感谢 Neftas 的建议!):

dir=/your/path; find ${dir} -name "*.pyc" | while read file; do head -c 2 ${file} | od -d | head -n 1 | awk -v z=${file} -F ' ' '{print $2 "\t" z}'; done 

这会输出一个包含值和文件名的列表,如下所示:

62211   /usr/lib/pymodules/python2.7/reportbug/ui/urwid_ui.pyc 
62211   /usr/lib/pymodules/python2.7/reportbug/debbugs.pyc 
62211   /usr/lib/pymodules/python2.7/reportbug/checkbuildd.pyc 
... 
62161   /usr/lib/pymodules/python2.6/debianbts.pyc 
62161   /usr/lib/pymodules/python2.6/fpconst.pyc 
62161   /usr/lib/pymodules/python2.6/SOAPpy/Server.pyc 
...