2010-11-30 16 views
1

私は約7 +ギガのデータ合計のために約500,000 + txtファイルを持っています。私はそれらをsqliteデータベースに入れるためにpythonを使用しています。私は2つのテーブルを作成しています。1. pKとファイルへのハイパーリンクです。 他のテーブルについては、同僚がperlでdevlopedしたエンティティ抽出プログラムを使用しています。Pythonサブプロセス。 stdoutを読むことができません

これを達成するために、私はsubprocess.Popen()を使用しています。 Tこのメソッドの前に、私はループの繰り返しごとにperlをオープンしていましたが、単に役に立つだけでは高価でした。

私はperlを動的にする必要があります。私はそれからデータを4番目に送信する必要があり、それを行うまではプロセスは終了しません。 perlはファイルの完全な文字列をstdinとして受け入れるように修正され、\ nが得られたらstdoutを返します。しかし、私はデータの読み込みに問題があります...

私は、私のループ内の次の反復で、私のサブプロセスが終了したときに、I/Oエラーが発生します。 readline()またはread()を試してみると、ロックされます。私が経験している異なる行動のいくつかの例があります。

これは私のシステムをデッドロックし、私は強制的にpythonを閉じる必要があります。

numberExtractor = subprocess.Popen(["C:\\Perl\\bin\\perl5.10.0.exe","D:\\MyDataExtractor\\extractSerialNumbers.pl"], stdout=subprocess.PIPE, stdin= subprocess.PIPE) 
for infile in glob.glob(self.dirfilename + '\\*\\*.txt'): 
    f = open(infile) 
    reportString = f.read() 
    f.close() 

    reportString = reportString.replace('\n',' ') 
    reportString = reportString.replace('\r',' ') 
    reportString = reportString +'\n' 

    numberExtractor.stdin.write(reportString) 
    x = numberExtractor.stdout.read()  #I can not see the STDOUT, python freezes and does not run past here. 

    print x 

これはサブプロセスをキャンセルし、ループの次の繰り返しでI/Oエラーが発生します。

numberExtractor = subprocess.Popen(["C:\\Perl\\bin\\perl5.10.0.exe","D:\\MyDataExtractor\\extractSerialNumbers.pl"], stdout=subprocess.PIPE, stdin= subprocess.PIPE) 
for infile in glob.glob(self.dirfilename + '\\*\\*.txt'): 

    f = open(infile) 
    reportString = f.read() 
    f.close() 

    reportString = reportString.replace('\n',' ') 
    reportString = reportString.replace('\r',' ') 
    reportString = reportString +'\n' 
    numberExtractor.stdin.write(reportString) 
    x = numberExtractor.communicate() #Works good, I can see my STDOUT from perl but the process terminates and will not run on the next iteration 

    print x 

このように実行すると、すべてのコードが正常に実行されます。印刷行は '、0x015dbf08のモード' rb '>で、フォルダ内の各項目に適用されます。

numberExtractor = subprocess.Popen(["C:\\Perl\\bin\\perl5.10.0.exe","D:\\MyDataExtractor\\extractSerialNumbers.pl"], stdout=subprocess.PIPE, stdin= subprocess.PIPE) 
for infile in glob.glob(self.dirfilename + '\\*\\*.txt'): 
    f = open(infile) 
    reportString = f.read() 
    f.close() 

    reportString = reportString.replace('\n',' ') 
    reportString = reportString.replace('\r',' ') 
    reportString = reportString +'\n' 

    numberExtractor.stdin.write(reportString) 
    x = numberExtractor.stdout    #I can not get the value of the object, but it runs through all my files fine. 

    print x 

がうまくいけば、私は単純なミスを作っていますが、私はちょうど私のperll(標準入力)にファイルを送信することができますいくつかの方法があり、標準出力を取得し、その後、すべてのファイル内のための私のサブプロセスを再開することなく、繰り返し私のループ?

+0

PerlプログラムをPythonに簡単に変換できますか?このプログラムはPerlに簡単に翻訳できますか?ここでは複雑さが軽減されます。 – nmichaels

+0

これは本当にこの選択肢ではありません。私がこの道を始める前の私の最初の考えでした。 – dfarni

答えて

2

シェルの使用を検討してください。人生はより簡単です。

perl extractSerialNumbers.pl *.txt | python load_database.py 

Pythonの起動用perlとすべてのことを混乱させないでください。 perlから結果を読み、その結果をPythonで処理するだけです。

両方のプロセスが同時に実行されるため、これは非常に高速で、多くのCPUリソースをプログラミングすることなく使用する傾向があります。

Pythonプログラム(load_database.py)では、fileinputモジュールを使用して、stdinで提供されるファイル全体を読むことができます。

import fileinput 
for line in fileinput.input(): 
    load the row into the database 

これは、シェルをパイプライン設定の汚い作業にする場合、Pythonプログラムで必要なことだと思います。

+0

+1推奨シェルです。しかし、なぜこの単純な "for sys.stdin"の代わりにfileinputを使うのでしょうか? – tokland

+0

@tokland:(1)あまり単純ではありません。 (2)長期的には、 '<'リダイレクト対ファイル名のリストの処理は、 'fileinput'のときには簡単です。 –

+0

私はこれをWindowsマシンで実行しています – dfarni

関連する問題