29

バックグラウンド:

私はCのselect()関数に精通しています。私はこの機能を多くの目的で使用してきました。それらのほとんどは、パイプやファイルなどの読み書き用です。エラー リストを使用したことはないと言わざるを得ませんが、これは重要な問題には関係ありません。

質問:

Python は次のselect()ように動作しますか?

C への単純なselect()インターフェイスにもかかわらず、 Python では異なる方法で動作することがわかりました。ファイルの読み取り準備が整ったときに初めて返されるようです。読み取るバイトを残してファイルを読み取ると、呼び出しがブロックされます。ただし、これら 2 つの呼び出しの間に読み取り呼び出しがなく、前の呼び出しが返された後に再度呼び出すと、期待どおりに返されます。例えば:select()select()select()select()select()select()

import select
# Open the file (yes, playing around with joysticks)
file = open('/dev/input/js0', 'r') 
# Hold on the select() function waiting
select.select([file], [], [])
# Say 16 bytes are sent to the file, select() will return.
([<open file '/dev/input/js0', mode 'r' at 0x7ff2949c96f0>], [], [])
# Call select() again, and select() will indeed return.
select.select([file], [], [])
([<open file '/dev/input/js0', mode 'r' at 0x7ff2949c96f0>], [], [])
# read 8 bytes. There are 8 bytes left for sure. Calling again file.read(8) will empty the queue and would be pointless for this example
file.read(8)
'<\t\x06\x01\x00\x00\x81\x01'
# call select() again, and select() will block
select.select([file], [], [])
# Should it block? there are 8 bytes on the file to be read.

これがselect()Python の動作である場合は、それで問題ありません。処理できます。期待していたほどではありませんが、まあまあです。私はそれで何ができるかを知っています。

しかし、これが私の行動でない場合は、select()誰かが私が間違っていることを教えてくれれば幸いです. 私が読んだselect()のは、Python ドキュメントの内容です。嘘じゃないから大丈夫。多分質問は次のとおりです。

  • Pythonでファイルを読み取る準備ができていると見なされるのはいつですか?
  • 一度も読み込まれていないファイルということですか?
  • 読み取るバイトを含むファイルを意味しますか?
4

2 に答える 2

20

Pythonは予想どおりシステム コールとしてselect()渡さselect()れますが、ブロックに関する問題は別の問題であり、おそらくバッファリングに関連しています。正しいことをしている自分を満足させるselect()ために、ジョイスティックなどの特別なデバイスを使用するのではなく、ファイル システムでファイルの読み取り/書き込みを試してください。

open()おそらく、通話を変更したいと思うでしょう。Pythonsopen呼び出しはデフォルトでバッファリングされた読み取りを使用するため、実行してもread(8)、入力ファイルからより多くのデータを読み取り、結果をバッファリングする可能性があります。ジョイスティック デバイスがバッファなしで開かれるように、bufferingオプションをに設定する必要があります。open

あなたが試すための提案:

  • Python のデフォルトでは、ファイルはテキスト モードで開かれます。ジョイスティックなどの特殊なデバイスを扱うときは、おそらく openmodeを使用する必要があります。rb
  • ファイルを非バッファ モードで開きます。
  • selectベースの呼び出しを行う場合は、デバイスを非ブロック モードに設定します。フラグで使用os.open()してみてください。os.O_RDONLY|os.O_NONBLOCK
于 2012-07-21T10:44:18.090 に答える
0

ばかげた質問をしてもいいですか?本当に8バイト残っていますか?

デバイスノードは、必ずしも通常のファイルのように動作するとは限りません。1回のread()システムコールでstructinput_event全体を読み取る必要がある場合があります。(そして、あなたが十分に読んでいない場合、残りは捨てられます)。データグラムソケットのrecvmsg()に少し似ています。

于 2012-07-21T10:52:25.003 に答える