

python初心者です．whileループ内でコンソールからの入力の取得をinput()もしくはraw_input()で取得したいのですが，何も入力がない場合はスルーして次のコマンドを実行するようなコードを書きたいと思っています．（コンソールのバッファに何も溜まっていなかったら，`input()`は呼ばない，という実装にしたいのです）  
イメージとしては

[code]

    while True:
        tmp = '0'
        if (console.readable()):
            tmp = input()
            print tmp
    
        hogehoge
    
[/code]

という感じです．（このコードはあくまでイメージなので実際には動きません）  
この`console.readable()`の部分は以前Cで似たようなことをした時に実装した方法なのですが，この部分をpythonで実装するにはどうすればよいか，という質問です．  
なかなか調べても良いページが見当たらず，だれか知恵をお貸しいただけないでしょうか．

よろしくお願い致します


CC BY-SA 3.0
2018-05-01T11:28:15.797
43700
2019-01-05T14:32:09.340
2018-05-01T12:00:59.033
28378
28378
question
python
pythonでのraw_input()の使い方


`input()`を非ブロック動作にするためにコンソールのモードを変更したりOS依存モジュールの機能を用いたりするとできるかも知れませんが、アプローチを変えて「`input()`をデーモンスレッドで行わせ結果をキューを通じて主スレッドが取り出したら・・・」と考え以下のような実装を考えてみました。`Input.input()`はデフォルトでブロックモードで動作しますが、`block=True`にするとその時点で入力があった場合は`str`インスタンスを、なかった場合は`None`を返すようにしています。

[code]

    import threading
    import queue
    import time
    
    
    class Input(threading.Thread):
        def __init__(self):
            super().__init__(daemon=True)
            self.queue = queue.Queue()
            self.start()
    
        def run(self):
            while True:
                t = input()
                self.queue.put(t)
    
        def input(self, block=True, timeout=None):
            try:
                return self.queue.get(block, timeout=timeout)
            except queue.Empty:
                return None
    
    
    def main():
        cin = Input()
        for i in range(10):
            time.sleep(1)  # 何かの仕事のつもり
            t = cin.input(block=False)
            print('{}: t={}'.format(i, t))
    
    
    if __name__ == '__main__':
        main()
    
[/code]

(Windows10 cygwin 64bit Python 3.6.4, Ubuntu 16.04LTS Python 3.5.2で試しました)

しかし、cygwin上で動かすと例外発生時のスタックトレースの表示が途中で止まる現象が起きます。何度かENTERを押せば最後まで表示されシェルへ戻りはするのですが。WSLやUbuntuではそういうことは起きませんでした。この実装はコンソールの振る舞いに影響される点があるのだと思います。

少々中途半端な実装のままで恐縮ですが、一つのアイデアとしてコメントしてみました。


CC BY-SA 4.0
2018-05-02T16:29:47.967
43747
2018-05-02T16:29:47.967
4417
43700
answer


この質問は、Pythonの`input()`では、入力データを待つ仕様になっているが、C言語の`getchar()`と同じ仕様のものが実現できないかという質問だと思います。回答としては、Pythonの標準ライブラリだけだとこの機能を実現するのは無理だということになります。

ウィンドウアプリにすれば、容易に実装できます。ウィンドウアプリでは、例えば、ゲームであれば、矢印キーでキャラクターを動かすのは普通にすると思います。ウィンドウアプリでのキーイベントの取得については、下記等を参考にしてください。

<http://www.geocities.jp/penguinitis2002/computer/programming/Python/PyGTK/03-key.html>

コンソールアプリで、どうしてもやりたければ、キー入力と違って少し手間になりますが、ファイルを使うことで実現できます。console.readable()のかわりに、

[code]

    os.path.isfile('a.txt')
    
[/code]

としておいて、以下のようにターミナルからファイルに書き込んでやればできます。

[code]

    echo 'a' > a.txt
    
[/code]


CC BY-SA 4.0
2018-05-03T01:51:58.893
43753
2018-05-07T01:37:18.177
2018-05-07T01:37:18.177
15171
15171
43700
answer


質問者はもうここを訪れていないようですが、ノウハウの例として。  
コンソールでやるなら curses というライブラリがあります。

[curses ---
文字セル表示を扱うための端末操作](https://docs.python.org/ja/3/library/curses.html)  
[Python で Curses プログラミング](https://docs.python.org/ja/3/howto/curses.html)  
[windows-curses 1.0](https://pypi.org/project/windows-curses/)  
[PythonにおけるCursesプログラミング](http://d.hatena.ne.jp/SumiTomohiko/20070507/1178541054)

> ユーザからの入力  
>
> cursesライブラリ自身は、非常に簡単な入力機構しか提供しません。Pythonでは、この欠点を補うための文字列を入力するウィジェットを追加しています。
>
>
> ウィンドウへの入力を得るもっともよく使われる方法は、ウィンドウのgetch()メソッドを使うことです。これは一時停止し、ユーザのキー入力を待ち、もしecho()が前に呼び出されていたらそれを表示します。あなたは、一時停止する前にカーソルを移動させる座標を追加で指定することもできます。
>
>
> nodelay()メソッドで、この挙動を変更することができます。nodelay(1)のあと、ウィンドウに対してgetch()すると、ノンブロッキングになり、入力がないときはERR
> (-1) を返します。halfdelay()関数というのもあり、（結果的に）それぞれのgetch()に時間制限を設定することができます;
> もしhalfdelay()の引数で指定したミリ秒だけ経過しても入力が得られない場合は、cursesは例外を生成します。
>
> getch()メソッドは整数を返します;
> もし戻り値が0から255までの間ならば、それは押されたきーのASCIIコードを表します。255より大きい値は、Page UpやHome,
> カーソルキーといった特殊キーを表します。あなたは戻り値を、curses.KEY_PPAGEやcurses.KEY_HOME,
> curses.KEY_LEFTといった定数と比較することができます。通常、あなたのメインループは以下のようになります:
[code]

    while 1:
        c = stdscr.getch()
        if c == ord('p'): PrintDocument()
        elif c == ord('q'): break  # Exit the while()
        elif c == curses.KEY_HOME: x = y = 0
    
[/code]

> curses.asciiモジュールは、ASCIIクラスのクラス関数を提供し、この関数は整数か1文字の文字列を引数に取ります;
> これはあなたのコマンドインタプリタの読みやすいテストを書くのに便利です。このクラスはまた、整数か1文字の文字列を引数に取り、相互に変換する関数も提供します。例えば、curses.ascii.ctrl()は引数に対応した制御文字を返します。


CC BY-SA 4.0
2019-01-05T14:32:09.340
51737
2019-01-05T14:32:09.340
26370
43700
answer