【发布时间】:2009-08-28 08:05:38
【问题描述】:
我试图找出给定的可执行文件(或库)是否从 Python 编译为 32 位或 64 位。我正在运行 64 位的 Vista,想确定目录中的某个应用程序是针对 32 位还是 64 位编译的。
有没有一种简单的方法可以仅使用标准 Python 库(目前使用 2.5.4)来做到这一点?
【问题讨论】:
标签: python windows dll 64-bit executable
我试图找出给定的可执行文件(或库)是否从 Python 编译为 32 位或 64 位。我正在运行 64 位的 Vista,想确定目录中的某个应用程序是针对 32 位还是 64 位编译的。
有没有一种简单的方法可以仅使用标准 Python 库(目前使用 2.5.4)来做到这一点?
【问题讨论】:
标签: python windows dll 64-bit executable
用于此的 Windows API 是 GetBinaryType。您可以使用 pywin32 从 Python 调用它:
import win32file
type=GetBinaryType("myfile.exe")
if type==win32file.SCS_32BIT_BINARY:
print "32 bit"
# And so on
如果您想在没有 pywin32 的情况下执行此操作,则必须自己阅读 PE header。这是 C# 中的 an example,这是 Python 的快速移植:
import struct
IMAGE_FILE_MACHINE_I386=332
IMAGE_FILE_MACHINE_IA64=512
IMAGE_FILE_MACHINE_AMD64=34404
f=open("c:\windows\explorer.exe", "rb")
s=f.read(2)
if s!="MZ":
print "Not an EXE file"
else:
f.seek(60)
s=f.read(4)
header_offset=struct.unpack("<L", s)[0]
f.seek(header_offset+4)
s=f.read(2)
machine=struct.unpack("<H", s)[0]
if machine==IMAGE_FILE_MACHINE_I386:
print "IA-32 (32-bit x86)"
elif machine==IMAGE_FILE_MACHINE_IA64:
print "IA-64 (Itanium)"
elif machine==IMAGE_FILE_MACHINE_AMD64:
print "AMD64 (64-bit x86)"
else:
print "Unknown architecture"
f.close()
【讨论】:
如果您在 Windows 上运行 Python 2.5 或更高版本,您还可以使用 ctypes 来使用不带 pywin32 的 Windows API。
from ctypes import windll, POINTER
from ctypes.wintypes import LPWSTR, DWORD, BOOL
SCS_32BIT_BINARY = 0 # A 32-bit Windows-based application
SCS_64BIT_BINARY = 6 # A 64-bit Windows-based application
SCS_DOS_BINARY = 1 # An MS-DOS-based application
SCS_OS216_BINARY = 5 # A 16-bit OS/2-based application
SCS_PIF_BINARY = 3 # A PIF file that executes an MS-DOS-based application
SCS_POSIX_BINARY = 4 # A POSIX-based application
SCS_WOW_BINARY = 2 # A 16-bit Windows-based application
_GetBinaryType = windll.kernel32.GetBinaryTypeW
_GetBinaryType.argtypes = (LPWSTR, POINTER(DWORD))
_GetBinaryType.restype = BOOL
def GetBinaryType(filepath):
res = DWORD()
handle_nonzero_success(_GetBinaryType(filepath, res))
return res
然后像使用 win32file.GetBinaryType 一样使用 GetBinaryType。
注意,你必须实现handle_nonzero_success,如果返回值为0,它基本上会抛出异常。
【讨论】:
我已编辑 Martin B's 答案以使用 Python 3,添加了 with 语句和 ARM/ARM64 支持:
import struct
IMAGE_FILE_MACHINE_I386 = 332
IMAGE_FILE_MACHINE_IA64 = 512
IMAGE_FILE_MACHINE_AMD64 = 34404
IMAGE_FILE_MACHINE_ARM = 452
IMAGE_FILE_MACHINE_AARCH64 = 43620
with open('foo.exe', 'rb') as f:
s = f.read(2)
if s != b'MZ':
print('Not an EXE file')
else:
f.seek(60)
s = f.read(4)
header_offset = struct.unpack('<L', s)[0]
f.seek(header_offset + 4)
s = f.read(2)
machine = struct.unpack('<H', s)[0]
if machine == IMAGE_FILE_MACHINE_I386:
print('IA-32 (32-bit x86)')
elif machine == IMAGE_FILE_MACHINE_IA64:
print('IA-64 (Itanium)')
elif machine == IMAGE_FILE_MACHINE_AMD64:
print('AMD64 (64-bit x86)')
elif machine == IMAGE_FILE_MACHINE_ARM:
print('ARM eabi (32-bit)')
elif machine == IMAGE_FILE_MACHINE_AARCH64:
print('AArch64 (ARM-64, 64-bit)')
else:
print(f'Unknown architecture {machine}')
【讨论】:
进行此调整后,我能够在 Python 3.5 程序中成功使用 Martin B 的答案:
s=f.read(2).decode(encoding="utf-8", errors="strict")
最初它在我的 Python 2.7 程序中运行良好,但在进行了其他必要的更改后,我发现我得到了 b'MZ',并且解码它似乎可以解决这个问题。
【讨论】:
win32file.GetBinaryType。在 .pyd 文件上运行它也不起作用,即使它被重命名为 .dll。看下一篇:
import shutil
import win32file
from pathlib import Path
myDir = Path("C:\\Users\\rdboylan\\AppData\\Roaming\\Python\\Python37\\site-packages\\pythonwin")
for fn in ("Pythonwin.exe", "win32ui.pyd"):
print(fn, end=": ")
myf = myDir / fn
if myf.suffix == ".pyd":
mytemp = myf.with_suffix(".dll")
if mytemp.exists():
raise "Can not create temporary dll since {} exists".format(mytemp)
shutil.copyfile(myf, mytemp)
type = win32file.GetBinaryType(str(mytemp))
mytemp.unlink()
else:
type=win32file.GetBinaryType(str(myf))
if type==win32file.SCS_32BIT_BINARY:
print("32 bit")
else:
print("Something else")
# And so on
结果
Pythonwin.exe: 32 bit
win32ui.pyd: Traceback (most recent call last):
File "C:/Users/rdboylan/Documents/Wk devel/bitness.py", line 14, in <module>
type = win32file.GetBinaryType(str(mytemp))
pywintypes.error: (193, 'GetBinaryType', '%1 is not a valid Win32 application.')
【讨论】: