6

ターミナルでpythonでプログレスバーを作ろうと思っています。まず、端末ウィンドウの幅 (列) を取得する必要があります。Python 2.7 では、Windows でこれを実行できる標準ライブラリはありません。Windows コンソール API を手動で呼び出す必要があるかもしれません。

MSDN と Python のドキュメントによると、次のコードを書きました。

import ctypes
import ctypes.wintypes

class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
    _fields_ = [
        ('dwSize', ctypes.wintypes._COORD),
        ('dwCursorPosition', ctypes.wintypes._COORD),
        ('wAttributes', ctypes.c_ushort),
        ('srWindow', ctypes.wintypes._SMALL_RECT),
        ('dwMaximumWindowSize', ctypes.wintypes._COORD)
    ]
hstd = ctypes.windll.kernel32.GetStdHandle(ctypes.c_ulong(-11)) # STD_OUTPUT_HANDLE = -11
print hstd
csbi = CONSOLE_SCREEN_BUFFER_INFO()
print ctypes.sizeof(csbi) # <---------------
ret = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(ctypes.c_ulong(hstd), csbi)
print ret
print csbi.dwSize.X

それは正常に動作します。printコード内のいくつかを削除することにしました。しかし、その後、それはうまくいきません!GetLastError6 (無効なハンドル) を返します。print 'hello'何度か試してみると、 、 、import sysなどのコードのポイントされた位置に何かがあるに違いないことがわかりましたsys.stdout.flush()。最初は、何かをするのに時間がかかるのではないかと思います。それでその位置に入れようとしましtime.sleep(2)たが、それでもうまくいきません。

でも、struct代わりに を使えばctypes.Structureそんな問題はありません。

import ctypes
import struct

hstd = ctypes.windll.kernel32.GetStdHandle(-11) # STD_OUTPUT_HANDLE = -11
csbi = ctypes.create_string_buffer(22)
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(hstd, csbi)
width, height, curx, cury, wattr, left, top, right, bottom, maxx, maxy = struct.unpack("hhhhHhhhhhh", csbi.raw)
print bufx

無関係なコードがこのような違いを生んだ理由を教えてくれる人はいますか?

4

1 に答える 1

2

参照によって構造体を渡す必要があります。

ret = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(
    ctypes.c_ulong(hstd), 
    ctypes.byref(csbi)
)

restypeforを宣言することもお勧めしますGetStdHandle。これは、コードを 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 では、コードはより有用なエラーを報告します。私はこれを見る:

トレースバック (最新の呼び出しが最後):
  ファイル「test.py」の 16 行目
    ret = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(ctypes.c_ulong(hstd), csbi)
ValueError: プロシージャが呼び出された引数が多すぎる可能性があります (20 バイトで
過剰)

これは、Python コードとネイティブ コードの間のインターフェイスでバイナリの不一致があることを明確にするのに十分です。

より新しいバージョンの Python を入手すれば、このスタックの不均衡チェックも役立つと思います。

于 2013-08-01T15:29:46.777 に答える