デフォルトでは、標準入力はバッファリングされ、正規モードを使用します。これにより、入力を編集できます。 Enter キーを押すと、Python で入力を読み取ることができます。
入力への下位レベルのアクセスが必要な場合は、 tty.setraw()
を使用できます 標準入力ファイル記述子で。これにより、sys.stdin.read(1)
を使用して一度に 1 文字を読み取ることができます。 .この場合、Python スクリプトが特殊文字の処理を担当し、文字のエコーや削除などの機能の一部が失われることに注意してください。詳細については、termios(3) を参照してください。
ウィキペディアで上下キーに使用されるエスケープ シーケンスについて読むことができます。
すべてを 1 つのプロセスで処理すれば、標準のシェルの動作を再現できるはずです。
サブプロセスを使用することもできます (モジュールを参照するのではなく、 fork()
を使用できます)。 または popen()
)。メインプロセスでバッファリングされていない入力を解析し、サブプロセスの stdin (バッファリング可能) に送信します。メイン プロセスと履歴を共有するには、プロセス間通信が必要になる場合があります。
この方法で入力をキャプチャするために必要なコードの例を次に示します。いくつかの基本的な処理を行っているだけであり、ユースケースに適合させるにはさらに作業が必要であることに注意してください。
import sys
import tty
import termios
def getchar():
fd = sys.stdin.fileno()
attr = termios.tcgetattr(fd)
try:
tty.setraw(fd)
return sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSANOW, attr)
EOT = '\x04' # CTRL+D
ESC = '\x1b'
CSI = '['
line = ''
while True:
c = getchar()
if c == EOT:
print('exit')
break
elif c == ESC:
if getchar() == CSI:
x = getchar()
if x == 'A':
print('UP')
elif x == 'B':
print('DOWN')
elif c == '\r':
print([line])
line = ''
else:
line += c
Python には、多くの機能を備えたキーボード モジュールがあります。おそらく次のコマンドでインストールします:
pip install keyboard
次に、次のようなコードで使用します:
import keyboard
keyboard.add_hotkey('up', lambda: keyboard.write('write command retrieved from the history of your shell here'))
keyboard.wait('esc')
または、関数 on_press_keyUsing 関数 on_press_key を使用できます:
keyboard.on_press_key("p", lambda _:print("You pressed p"))
コールバック関数が必要です。 _ を使用したのは、キーボード関数がキーボード イベントをその関数に返すためです。
実行されると、キーが押されたときに関数が実行されます。次の行を実行すると、すべてのフックを停止できます:
keyboard.unhook_all()
詳細については、stackoverflow の同様の投稿を参照してください。これが Python でのキー押下の検出に役立つことを願っていますか?
補足: 上記の fork() メソッドについて言及しましたが、python では
を使用できますサブプロセス ここに組み込みモジュールがあるので、subprocess をインポートして準備完了です。ここでは、特に run 関数を使用して、サブシェルでコマンドを実行します。 C から来た人にとっては、これにより、フォークして子プロセスを作成し、子プロセスの実行が完了するのを待つ必要がなくなります。今回は Python に任せてください。
ユーザーが入力したコマンドを実行するためのサンプル コード
def execute_commands(command):
try:
subprocess.run(command.split())
except Exception:
print("psh: command not found: {}".format(command))