Python 为什么不相关的代码会产生影响?
我想在终端中用python制作一个进度条。首先,我必须得到终端窗口的宽度(列)。在Python2.7中,没有标准库可以在Windows上实现这一点。我知道也许我必须手动调用Windows控制台API 根据MSDN和Python文档,我编写了以下代码:Python 为什么不相关的代码会产生影响?,python,windows,winapi,ctypes,Python,Windows,Winapi,Ctypes,我想在终端中用python制作一个进度条。首先,我必须得到终端窗口的宽度(列)。在Python2.7中,没有标准库可以在Windows上实现这一点。我知道也许我必须手动调用Windows控制台API 根据MSDN和Python文档,我编写了以下代码: 导入ctypes 导入ctypes.wintypes 类控制台\屏幕\缓冲区\信息(ctypes.Structure): _字段=[ ('dwSize',ctypes.wintypes._COORD), ('dwCursorPosition',ct
导入ctypes
导入ctypes.wintypes
类控制台\屏幕\缓冲区\信息(ctypes.Structure):
_字段=[
('dwSize',ctypes.wintypes._COORD),
('dwCursorPosition',ctypes.wintypes._COORD),
('wAttributes',ctypes.c_ushort),
('srWindow',ctypes.wintypes.\u SMALL\u RECT),
('dwMaximumWindowsSize',ctypes.wintypes.\u COORD)
]
hstd=ctypes.windell.kernel32.GetStdHandle(ctypes.c_-ulong(-11))#STD_-OUTPUT_-HANDLE=-11
打印hstd
csbi=控制台\屏幕\缓冲区\信息()
打印ctypes.sizeof(csbi)#您需要通过引用传递结构:
ret = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(
ctypes.c_ulong(hstd),
ctypes.byref(csbi)
)
我还建议您为GetStdHandle
声明restype
。这意味着您的代码可以在64位进程下运行。我会这样写:
ctypes.windll.kernel32.GetStdHandle.restype = ctypes.wintypes.HANDLE
hstd = ctypes.windll.kernel32.GetStdHandle(-11) # STD_OUTPUT_HANDLE = -11
csbi = CONSOLE_SCREEN_BUFFER_INFO()
ret = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(
hstd,
ctypes.byref(csbi)
)
实际上,在我的Python版本中,您的代码报告了一个更有用的错误。我看到:
Traceback (most recent call last):
File "test.py", line 16, in
ret = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(ctypes.c_ulong(hstd), csbi)
ValueError: Procedure probably called with too many arguments (20 bytes in
excess)
回溯(最近一次呼叫最后一次):
文件“test.py”,第16行,在
ret=ctypes.windell.kernel32.GetConsoleScreenBufferInfo(ctypes.c_-ulong(hstd),csbi)
ValueError:调用过程时可能使用了太多参数(20字节)
(超额)
这足以说明Python代码和本机代码之间的接口存在二进制不匹配
我猜想,如果你得到一个更新版本的Python,你也会从这个堆栈不平衡检查中受益。要从Python可靠地使用GetLastError
,请使用kernel32=ctypes.windell('kernel32',use_last_error=True)
,然后调用ctypes.get_last_error
。我已经知道了。但是如果我使用ctypes.byref
(就像我最初所做的那样),我就无法得到正确的值,不管我是否保留了那条指向的线。@eryksun我不确定我是否遵循了你的第二条评论。如果我将HANDLE
分配给GetStdHandle.restype
,则hstd
将属于HANDLE
类型。然后,当我将hstd
传递给GetConsoleScreenBufferInfo
时,这不意味着ctypes将使用hstd
的类型来正确封送指针大小的对象,即使没有显式的argtypes
规范。@eryksun因此,返回值不可能有64到32位的截断,这只意味着你不会得到指针类型。然后,在将句柄作为参数传递时,可以截断。这是否意味着在我上面的代码中需要argtypes,以确保传递64位值?@eryksun非常感谢。最近我真的从你那里学到了很多关于ctypes的知识,我真的很感激!2.7.5链接:对于“P”类型,为和。