3

大きな(しかし単純な)CSVを解析するPythonスクリプトを作成しています。

処理には時間がかかります。CSVの解析を中断して、後の段階で続行できるようにしたいと思います。

現在私はこれを持っています-そのうちのより大きなクラスに住んでいます:(未完成)

編集:

コードを変更しました。ただし、システムは300万行以上を解析します。

def parseData(self)
    reader = csv.reader(open(self.file))
    for id, title, disc in reader:
        print "%-5s %-50s %s" % (id, title, disc)
        l = LegacyData()
        l.old_id = int(id)
        l.name = title
        l.disc_number = disc
        l.parsed = False
        l.save()

これは古いコードです。

def parseData(self):
        #first line start
        fields = self.data.next()
        for row in self.data:
            items = zip(fields, row)
            item = {}
            for (name, value) in items:
                item[name] = value.strip()
            self.save(item)

みんなありがとう。

4

4 に答える 4

2

Linuxの場合は、Ctrl-Zを押して、実行中のプロセスを停止します。「fg」と入力して元に戻し、停止したところから開始します。

于 2011-01-05T00:26:20.243 に答える
1

signalイベントをキャッチするために使用できます。CTRL-Cこれは、ウィンドウでキャッチして解析を停止できるパーサーのモックアップです。

import signal, tme, sys

def onInterupt(signum, frame):
    raise Interupted()

try:
    #windows
    signal.signal(signal.CTRL_C_EVENT, onInterupt)
except:
    pass

class Interupted(Exception): pass
class InteruptableParser(object):

    def __init__(self, previous_parsed_lines=0):
        self.parsed_lines = previous_parsed_lines

    def _parse(self, line):
        # do stuff
        time.sleep(1) #mock up
        self.parsed_lines += 1
        print 'parsed %d' % self.parsed_lines

   def parse(self, filelike):
        for line in filelike:
            try:
                self._parse(line)
            except Interupted:
                print 'caught interupt'
                self.save()
                print 'exiting ...'
                sys.exit(0)

    def save(self):
        # do what you need to save state
        # like write the parse_lines to a file maybe
        pass

parser = InteruptableParser()
parser.parse([1,2,3])

現在Linuxを使用しているため、テストできません。

于 2011-01-05T01:33:41.907 に答える
1

私のやり方:

実際の処理コードをクラスに入れ、そのクラスにPickleプロトコル(http://docs.python.org/library/pickle.html)を実装します(基本的に、適切な関数を記述__getstate____setstate__ます)

このクラスは、ファイル名を受け入れ、開いているファイルを保持し、CSVリーダーインスタンスをインスタンスメンバーとして保持します。この__getstate__メソッドは現在のファイル位置を保存し、setstateはファイルを再度開き、適切な位置に転送して、新しいリーダーを作成します。

実際の作業は、__iter__各行が処理された後に外部関数に出力されるメソッドで実行します。

この外部関数は、割り込み(ソケット、キーボード、ファイルシステム上の特定のファイルの状態など)の入力を監視する「メインループ」を実行します。すべてが静かで、プロセッサの次の反復を呼び出すだけです。割り込みが発生すると、プロセッサの状態がディスク上の特定のファイルにピクルスされます。

プログラムを起動するときは、実行が保存されているかどうかを確認する必要があります。保存されている場合は、pickleを使用してエグゼキュータオブジェクトを取得し、メインループを再開します。

ここにいくつかの(テストされていない)コードがあります-ieaは十分に単純です:

from cPickle import load, dump
import csv
import os, sys

SAVEFILE = "running.pkl"
STOPNOWFILE = "stop.now"

class Processor(object):
    def __init__(self, filename):
        self.file = open(filename, "rt")
        self.reader = csv.reader(self.file)
    def __iter__(self):
        for line in self.reader():
            # do stuff
            yield None
    def __getstate__(self):
        return (self.file.name, self.file.tell())
    def __setstate__(self, state):
        self.file = open(state[0],"rt")
        self.file.seek(state[1])
        self.reader = csv.reader(self.File)

def check_for_interrupts():
    # Use your imagination here!  
    # One simple thing would e to check for the existence of an specific file
    # on disk.
    # But you go all the way up to instantiate a tcp server and listen to 
    # interruptions on the network
    if os.path.exists(STOPNOWFILE): 
        return True
    return False

def main():
    if os.path.exists(SAVEFILE):
        with open(SAVEFILE) as savefile:
            processor = load(savefile)
        os.unlink(savefile)
    else:
        #Assumes the name of the .csv file to be passed on the command line
        processor = Processor(sys.argv[1])
    for line in processor:
        if check_for_interrupts():
            with open(SAVEFILE, "wb") as savefile:
                dump(processor)
            break

if __name__ == "__main__":
    main()
于 2011-01-05T03:04:17.207 に答える
0

私の完全なコード

@jsbuenoのアドバイスに従い、フラグを付けましたが、別のファイルの代わりに、変数としてクラス内に保持しました。

私はクラスを作成します-それを呼び出すと、任意の入力を要求し、次に別のプロセスを開始して作業を行います。ループしているため、キーを押すとフラグが設定され、次の解析のためにループが呼び出されたときにのみチェックされます。したがって、私は現在のアクションを殺しません。呼び出しているデータから各オブジェクトのデータベースにフラグを追加するprocessと、いつでもこれを開始して、中断したところから再開できます。

class MultithreadParsing(object):
    
    process = None
    process_flag = True
    
    def f(self):
        print "\nMultithreadParsing has started\n"
        while self.process_flag:
            ''' get my object from database '''
            legacy = LegacyData.objects.filter(parsed=False)[0:1]
            
            if legacy:
                print "Processing: %s %s" % (legacy[0].name, legacy[0].disc_number)
                for l in legacy:
                    ''' ... Do what I want it to do ...'''
                sleep(1)
            else:
                self.process_flag = False
                print "Nothing to parse"
                
        
    
    def __init__(self):
        self.process = Process(target=self.f)
        self.process.start()
        print self.process
        a = raw_input("Press any key to stop \n")
        print "\nKILL FLAG HAS BEEN SENT\n"
        
        if a:
            print "\nKILL\n"
            self.process_flag = False

みんな(特に@jsbueno)を助けてくれてありがとう-もしあなたがいなかったら、私はこのクラスのアイデアを持っていなかっただろう。

于 2011-01-16T12:27:06.337 に答える