2010-12-13 5 views
10

ザPythonのドキュメントfile.read()状態An empty string is returned when EOF is encountered immediately.そのドキュメントさらに状態に関する:この方法は、C関数のfread()より の根底 を呼び出すことがパイソンEOF()

注できるだけサイズのバイトに近い として取得するために1回以上。また、 が指定されていない場合でも、ノンブロッキングモードでは、 よりも少ないデータが返される可能性があります。 が返されることに注意してください。

私はGuidoがf.eof()を追加しないと考えていると信じています。PERFECTLY CLEARだから、Pythonの方法を使う必要があります!

しかし、私には分かりませんが、読んでから要求されたバイト数よりも少ないバイト数を受け取ったにもかかわらず、それを受け取った場合、EOFに達しているという確定テストです。

すなわち:あなたはfile.read(size)の呼び出しで要求バイト未満を受信した場合

with open(filename,'rb') as f: 
    while True: 
     s=f.read(size) 
     l=len(s) 
     if l==0: 
      break  # it is clear that this is EOF... 
     if l<size: 
      break  # ? Is receiving less than the request EOF??? 

はそれがbreakへの潜在的なエラーですか?ここで

答えて

21

あなたは上... Pythonのあなたのヘビ皮を考えていないが、まず、審査

C.

ではありません。

  • ST = f.read()EOFに読み込む場合、または開きますバイナリとして、最後のバイトに;
  • st = f.read(n)試行は、nバイトを読み取り、場合によってはnバイトを超えます。
  • st = f.readline()は一度に1行を読み込み、行は '\ n'またはEOFで終わります。
  • st = f.readlines()は、readline()を使用してファイル内のすべての行を読み込み、行のリストを返します。

ファイルの読み取り方法がEOFの場合は、''を返します。同じタイプのEOFテストは、StringIO、socket.makefileなどの他の「ファイルのような」メソッドでも使用されています。nバイト未満の戻り値は、f.read(n)から確かにEOFの賢明なテストではありません! 。時間の99%は、それは見つけるのは非常にイライラするだろうが動作しない時間です。さらに、悪いPythonフォームです。この場合のnの唯一の用途は、リターンのサイズに上限を設けることです。

Pythonのファイルライクなメソッドがを返す理由は、より小さく、nバイトですか?

  1. EOFは確かに一般的な理由です。
  2. ネットワークソケットが読み取り時にタイムアウトする可能性があります。
  3. 正確にnバイトは、論理マルチバイト文字(テキストモードの場合は\r\nなど)、またはマルチバイト文字(Unicode)などの間にブレークを引き起こす場合があります。
  4. ファイルは非ブロックモードであり、別のプロセスがファイルにアクセスし始めます。
  5. 一時的にファイルにアクセスできません。
  6. ファイル、ディスク、ネットワークなどの潜在的な一時的なエラー状態
  7. プログラムは信号を受信しましたが、シグナルハンドラはそれを無視しました。

私は、このようにあなたのコードを書き換えるでしょう:

with open(filename,'rb') as f: 
    while True: 
     s=f.read(max_size) 
     if not s: break 

     # process the data in s... 

または、generatorを書く:

def blocks(infile, bufsize=1024): 
    while True: 
     try: 
      data=infile.read(bufsize) 
      if data: 
       yield data 
      else: 
       break 
     except IOError as (errno, strerror): 
      print "I/O error({0}): {1}".format(errno, strerror) 
      break 

f=open('somefile','rb') 

for block in blocks(f,2**16): 
    # process a block that COULD be up to 65,536 bytes long 
+1

"バイナリモードでは\ r \ n" < - これは "バイナリモード"ではなく "テキストモード"であるべきですか?バイナリモードでは、それはちょうど他のようなバイトのペアだろうか? –

1

は私のCコンパイラのマニュアルがfread()機能のために言っていることだ:エラーが発生した場合未満 数かもしれ実際に読み込ま フルアイテムの数を返します

size_t fread( 
    void *buffer, 
    size_t size, 
    size_t count, 
    FILE *stream 
); 

のfread、またはファイルの末尾に がある場合は、 に達するまでカウントされます。行うには正しいものとなり、ループの外にするのでbreak -

は、だから未満size手段エラーのいずれかが発生したか、EOFに達したときのように見えます。

+0

これは正しくない、信号が少ないバイトを引き起こし、短い読み取りの原因になります返される...これはまさにEOFではない。 – Lekensteyn

+0

@Lekensteyn:私は、プログラムが信号を受け取ったために短い読み込みが発生したが、シグナルハンドラがそれを無視した場合、シグナルは一般的に致命的なエラーを示すか、またはユーザーがプロセスを中断したいと考えているので、 - それが正確にEOFであるかどうかに関わらず、ループから脱出するのは正しいことです。 – martineau

+0

シグナルハンドラが短いリードを起こすのは賢明だと私は同意しますが、エラー状態であるとは私は同意しません。私のスクリプトの1つは、EOFまでstdinからデータを処理し続けます。 'SIGUSR1'はすぐにデータをフラッシュするように設定されています。これは、期待される短い読み込みと、エラーではない*を引き起こします。 – Lekensteyn