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

我想在终端中用python制作一个进度条。首先,我必须得到终端窗口的宽度(列)。在Python2.7中,没有标准库可以在Windows上实现这一点。我知道也许我必须手动调用Windows控制台API

根据MSDN和Python文档,我编写了以下代码:

导入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”类型,为和。