私は以下のジレンマを持っています。理論的に無効なレコードを含むことができる巨大なCSVファイルを解析しています(python
)。問題をすばやく修正できるように、エラーメッセージの行番号を確認したいと思います。しかし、私は多くのファイルを解析しているため、エラーは非常にまれですが、私はメインパイプラインにオーバーヘッドを追加するエラー処理をしたくありません。だから私はenumerate
または同様のアプローチを使用したくないのです。一言で言えばPythonでオーバーヘッドのない意味のあるIOエラーメッセージ
、私はこのように動作するget_line_number
機能を探しています:
with open('file.csv', 'r') as f:
for line in f:
try:
process(line)
except:
line_no = get_line_number(f)
raise RuntimeError('Error while processing the line ' + line_no)
しかし、これはこのループでf.tell()
will not workとして、複雑しているようです。
EDIT:
オーバーヘッドが非常に重要であるように思えます。私の実際の世界のケースでは(ファイルが非常に短いレコードのリストであるため、単一の浮動小数点数、浮動小数点数の組または文字列と整数の組であるため、file.csv
は約800MBで約80M行です)、それは約2.5です1ファイルあたりの秒数はenumerate
です。何らかの理由により、fileinput
はと非常にです。
import timeit
s = """
with open('file.csv', 'r') as f:
for line in f:
pass
"""
print(timeit.repeat(s, number = 10, repeat = 3))
s = """
with open('file.csv', 'r') as f:
for idx, line in enumerate(f):
pass
"""
print(timeit.repeat(s, number = 10, repeat = 3))
s = """
count = 0
with open('file.csv', 'r') as f:
for line in f:
count += 1
"""
print(timeit.repeat(s, number = 10, repeat = 3))
setup = """
import fileinput
"""
s = """
for line in fileinput.input('file.csv'):
pass
"""
print(timeit.repeat(s, setup = setup, number = 10, repeat = 3))
出力
[45.790788270998746, 44.88589363079518, 44.93949336092919]
[70.25306860171258, 70.28569177398458, 70.2074502906762]
[75.43606997421011, 74.39759518811479, 75.02027251804247]
[325.1898657102138, 321.0400970801711, 326.23809849238023]
EDIT 2:
実際のシナリオに近づい。 try-except
句は、オーバーヘッドを減らすためにループの外にあります。
import timeit
setup = """
def process(line):
if float(line) < 0.5:
outliers += 1
"""
s = """
outliers = 0
with open('file.csv', 'r') as f:
for line in f:
process(line)
"""
print(timeit.repeat(s, setup = setup, number = 10, repeat = 3))
s = """
outliers = 0
with open('file.csv', 'r') as f:
try:
for idx, line in enumerate(f):
process(line)
except ValueError:
raise RuntimeError('Invalid value in line' + (idx + 1)) from None
"""
print(timeit.repeat(s, setup = setup, number = 10, repeat = 3))
出力
[244.9097429071553, 242.84596176538616, 242.74369075801224
[293.32093235617504, 274.17732743313536, 274.00854821596295]
だから、私の場合には、enumerate
からのオーバーヘッドは10%程度です。
だから、あなたの例があまりにも遅く動くか、あまりにもゆっくりと動くかもしれないと思うのが問題ですか? perfに実際にどれだけの影響がありますか?エラーがないことが分かっているファイルの違いを測定しましたか? –
うわー、2倍の減速は期待できませんでした。 'try/catch'の' process(line) '呼び出しをラップするとどれだけの影響がありますか? –
私はどちらかというと、実際にデータと何をしようとしていても「合格」を置き換えることは、公平な比較ではありません。また、csvファイルの1行あたり10バイトしかないのはかなり珍しいことです。 – nigel222