問題:pyodbcによるPythonマルチプロセッシングとデータベースアクセスは "安全ではありません"?
私は、次のトレースバックを取得していますし、それが何を意味するのか理解していないか、それを修正する方法:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python26\lib\multiprocessing\forking.py", line 342, in main
self = load(from_parent)
File "C:\Python26\lib\pickle.py", line 1370, in load
return Unpickler(file).load()
File "C:\Python26\lib\pickle.py", line 858, in load
dispatch[key](self)
File "C:\Python26\lib\pickle.py", line 1083, in load_newobj
obj = cls.__new__(cls, *args)
TypeError: object.__new__(pyodbc.Cursor) is not safe, use pyodbc.Cursor.__new__()
状況:私はしました
処理されるデータでいっぱいのSQL Serverデータベースを取得しました。マルチプロセッシングモジュールを使用して作業を並列化し、コンピュータ上の複数のコアを利用しようとしています。次のように私の一般的なクラス構造は次のとおりです。
- MyManagerClass
- これは、メインクラス、プログラムが開始されます。
- それらが終了するため、それはまた、他のプロセスを作成し、起動する2つのmultiprocessing.Queueオブジェクト一つ
work_queue
一write_queue
- を作成し、その後、待機します。
- 注:これはない multiprocessing.managers.BaseManagerの拡張子(ある)
- MyReaderClass
- このクラスは、SQL Serverデータベースからデータを読み込みます。
work_queue
に項目を入れます。
- MyWorkerClass
- 業務処理が起こる場所です。
work_queue
からアイテムを取得し、完了したアイテムをwrite_queue
に配置します。
- MyWriterClass
- このクラスは、バックSQL Serverデータベースに処理されたデータの書き込みが担当しています。
write_queue
からアイテムを取得します。
アイデアは1人のマネージャー、ある読者、1人のライター、そして多くの労働者があるだろうということです。
その他の詳細:
私は標準エラー出力に二回トレースバックを取得するので、私はそれは作家のために一度、読者のために一度起こるとすることを考えています。私のワーカープロセスはうまく作成されますが、work_queue
に何もないので、KeyboardInterruptを送信するまでそこに座ってください。
リーダーとライターの両方が、データベースとの独自の接続を持ち、初期化時に作成されます。
ソリューション:このソリューションにつながっその答えと質問のためのマークとフェルディナント・バイエルに
感謝。彼らは正当にCursorオブジェクトが "pickle-able"ではないことを指摘しました。これは、マルチプロセスがプロセス間で情報を渡すために使用する方法です。
私のコードの問題は、__init__()
の方法でMyReaderClass(multiprocessing.Process)
とMyWriterClass(multiprocessing.Process)
の両方がデータベースに接続されていたことです。 MyManagerClass
にこれらのオブジェクト(つまりinitメソッドと呼ばれる)を作成した後、start()
というオブジェクトを作成しました。
したがって、接続オブジェクトとカーソルオブジェクトが作成され、次にpickle経由で子プロセスに送信されます。私の解決策は、接続とカーソルオブジェクトのインスタンス化を子プロセスが完全に作成されるまで呼び出されないrun()メソッドに移すことでした。
ちょうどいいこと:優秀な質問。 – mavnn