4

一部のソース データ ソースから Postgres データベースにデータをロードする必要があります。このタスクを実行するには、まずデータを一時 CSV ファイルに書き込み、次に COPY FROM クエリを使用して CSV ファイルから Postgres データベースにデータを読み込みます。これはすべて Python で行います。

コードは次のようになります。

table_name = 'products'
temp_file = "'C:\\Users\\username\\tempfile.csv'"
db_conn = psycopg2.connect(host, port, user, password, database)
cursor = db_conn.cursor()
query = """COPY """ + table_name + """ FROM """ + temp_file + " WITH NULL AS ''; """
cursor.execute(query)

中間ファイルへの書き込みのステップを避けたい。代わりに、Python オブジェクトに書き込み、COPY FROM ファイル メソッドを使用してデータを postgres データベースにロードしたいと考えています。

StringIO オブジェクトから postgres データベースにデータをコピーする psycopg2 の copy_from メソッドを使用するこの手法を認識しています。ただし、ある理由で psycopg2 を使用できないため、COPY FROM タスクをライブラリに依存させたくありません。他のpostgresドライバーでも実行できるPostgresクエリにしたい。

中間ファイルに書き込まずにこれを行うより良い方法を教えてください。

4

2 に答える 2

7

psycopg2/COPYを使用できるように、ワイヤプロトコルのサポートが統合されています。COPY ... FROM STDINCOPY ... TO STDOUT

ドキュメントの使用COPY TOCOPY FROMを参照してください。psycopg2

あなたはpsycopg2を使用できないと言っているので、運が悪いです。COPY TO STDOUTドライバーは、それらを使用するために/を理解する必要があります。または、ドライバーのネットワークソケットを乗っ取ってプロトコルを自分COPY FROM STDINで実装できるように、生データをソケットに書き込む方法を提供する必要があります。COPYこれにはドライバー固有のコードが絶対に必要です。単純に DB-API を使用することはできません。

したがって、カンプソンの提案は、通常は非常に悪い考えですが、あなたの唯一の選択肢のようです.

(これを投稿しているのは、主に、この回答を見つけた他の人が、使用に制限がないpsycopg2ことを確認するためです。)

を使用する必要がある場合は、次のようpsqlにしてください。

  • subprocessPopenコンストラクターでモジュール使用する
  • -qAtX-v ON_ERROR_STOP=1を渡してpsql、バッチ処理の正常な動作を取得します。
  • ['psql', '-v', 'ON_ERROR_STOP=1', '-qAtX', '-c', '\copy mytable from stdin']シェルを使用するのではなく、配列形式のコマンドを使用してください。
  • の stdin に書き込みpsql、それを閉じて、psql終了するまで待ちます。
  • コマンドの失敗時にスローされた例外をトラップすることを忘れないでください。stderrsubprocessをキャプチャして、例外オブジェクトにラップします。

os.popen2古いスタイルなどよりも安全で、クリーンで、正しくするのが簡単です.

于 2014-11-04T03:50:32.000 に答える
7

スクリプトからpsqlコマンドライン ツールを呼び出して(つまり を使用subprocess.call)、そのコマンドを活用して\copy、あるインスタンスの出力を別のインスタンスの入力にパイプし、一時ファイルを回避することができます。すなわち

psql -X -h from_host -U user -c "\copy from_table to stdout" | psql -X -h to_host -U user -c "\copy to_table from stdin"

これは、テーブルが宛先データベースに存在することを前提としています。そうでない場合は、別のコマンドで最初に作成する必要があります。

また、このメソッドの 1 つの注意点は、最初のpsql呼び出しからのエラーがパイピング プロセスによって飲み込まれる可能性があることです。

于 2014-11-03T21:26:42.387 に答える