0
import curses, threading, sys

def thread():
    a = curses.initscr()
    curses.noecho()
    curses.cbreak()
    a.keypad(True)
    while True:
        char = a.getch()
        if char == curses.KEY_RESIZE: 
            print("key_resize", file=sys.stderr)
        else:
            print("other", file=sys.stderr)

threading.Thread(target=thread).start()

この関数を単独で実行すると、すべて問題なく動作します - KEY_RESIZE が送信され、すべて問題ありません。スレッド内から getch() を呼び出すと問題が発生します。キー イベントは正常に動作しているように見えますが (徹底的にまたは広範囲にテストしていません)、KEY_RESIZE が送信されることはありません。

私は何か間違ったことをしていますか、またはスレッドに関係なく KEY_RESIZE が送信されるようにこれを修正する方法はありますか?

Python 3.4.3 の 2 つの異なる端末エミュレーター (gnome-terminal と konsole) で、スレッドの内側と外側の両方で画面を初期化して試しました。

curses は画面出力を台無しにする傾向があるため、print は stderr (別の端末にリダイレクトされます) に送信されます。このコードでは端末の修正も扱っていないため、通常の状態に戻すには端末をリセットする必要があります。

4

1 に答える 1

0

原則として、curses はスレッドセーフではありません。すべての作業を 1 つのスレッドで行うと、curses アプリケーションを機能させることができます。そうしないと、予期しない動作が発生します...

初歩的なサポートを提供する ncurses のコンパイル時の構成 (つまり、より良い出発点) がありますが、数年前に導入されたものの、事前にパッケージ化された形式でそれを目にすることはほとんどありません (FAQ公式リリースを参照)。

参考文献:

初期化中に、ncurses はSIGWINCHおよびその他のシグナル ハンドラを追加します。を使用すると、python が をキャプチャして無視しているstraceことがわかります。SIGWINCH

2722  <... futex resumed> )             = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722  --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
2722  rt_sigreturn({mask=[]})           = -1 EINTR (Interrupted system call)
2722  futex(0x7f94d4000c10, FUTEX_WAIT_PRIVATE, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722  --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
2722  rt_sigreturn({mask=[]})           = -1 EINTR (Interrupted system call)
2722  futex(0x7f94d4000c10, FUTEX_WAIT_PRIVATE, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722  --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
2722  rt_sigreturn({mask=[]})           = -1 EINTR (Interrupted system call)
2722  write(2, "Exception ignored in: <module 'threading' from '/usr/lib/python3.4/threading.py'>\n", 82) = 82
2722  write(2, "Traceback (most recent call last):\n", 35) = 35
2722  write(2, "  File \"/usr/lib/python3.4/threading.py\", line 1285, in _shutdown\n", 66) = 66
2722  open("/usr/lib/python3.4/threading.py", O_RDONLY|O_CLOEXEC) = 4 

Pythonがシグナル ハンドラーを確立したため、 ncursesは を認識できなくSIGWINCHなり、配信しませんKEY_RESIZE。おそらくこれは、スレッド化された構成でのシグナルの問題を軽減するために Python で行われます。

おそらく関連情報:

于 2015-11-25T00:08:14.970 に答える