ファイルに書き込んだ後、os.path.getsizeがまだ前のサイズを返すのはなぜですか?
質問
大きなxmlファイルを小さなチャンクに分割しようとしています。出力ファイルに書き込み、サイズをチェックしてしきい値を超えたかどうかを確認しますが、getsize()メソッドが期待どおりに機能しているとは思いません。
サイズが変化しているファイルのファイルサイズを取得する良い方法は何でしょうか。
このようなことをしました...
import string
import os
f1 = open('VSERVICE.xml', 'r')
f2 = open('split.xml', 'w')
for line in f1:
if str(line) == '</Service>\n':
break
else:
f2.write(line)
size = os.path.getsize('split.xml')
print('size = ' + str(size))
これを実行すると、ファイルサイズとして0が約80回、次に4176回出力されます。Pythonは、実際に出力する前に出力をバッファーに保存しますか?
解決
はい、Pythonは出力をバッファリングしています。次のようなサイズを自分で追跡した方が良いでしょう:
size = 0
for line in f1:
if str(line) == '</Service>\n':
break
else:
f2.write(line)
size += len(line)
print('size = ' + str(size))
(これは100%正確ではないかもしれません。たとえば、Windowsでは \ r \ n
行セパレーターのために各行が1バイトずつ増えますが、単純なチャンクには十分なはずです。)
他のヒント
ファイルサイズはファイルの位置と異なります。たとえば、
os.path.getsize('sample.txt')
ファイルサイズをバイト単位で正確に返します。
しかし
f = open('sample.txt')
print f.readline()
f.tell()
ここで、f.tell()は、ファイルハンドラーの現在の位置、つまり次の書き込みでデータを配置する場所を返します。バッファリングを認識しているため、出力ファイルに単純に追加している限り、正確である必要があります。
次のように、os.path.getsizeをos.tellに置き換えようとしましたか:
f2.write(line)
size = f2.tell()
サイズを自分で追跡することは、あなたの場合には問題ありません。別の方法は、サイズをチェックする直前にファイルバッファをフラッシュすることです。
f2.write(line)
f2.flush() # <-- buffers are written to disk
size = os.path.getsize('split.xml')
それをあまりにも頻繁に行うと、ファイルI / Oが遅くなります。
ファイルの終わりまでのオフセットを見つけるには:
file.seek(0,2)
print file.tell()
実世界の例-ファイルの更新を読み取り、発生時に印刷します。
file = open('log.txt', 'r')
#find inital End Of File offset
file.seek(0,2)
eof = file.tell()
while True:
#set the file size agian
file.seek(0,2)
neweof = file.tell()
#if the file is larger...
if neweof > eof:
#go back to last position...
file.seek(eof)
# print from last postion to current one
print file.read(neweof-eof),
eof = neweof