web-dev-qa-db-ja.com

Psycopg2 "copy_from"コマンド、引用符で囲まれた区切り文字を無視できますか(エラーが発生します)?

Copy_fromコマンド(postgresでcopyコマンドを利用する関数)を使用して、データの行をcsvのような構造でpostgresにロードしようとしています。私のデータはコンマで区切られています(残念ながら、私はデータの所有者ではないため、区切り文字を変更することはできません)。カンマを含む引用符で囲まれた値を持つ行を読み込もうとすると、問題が発生します(つまり、そのコンマは区切り文字として扱われるべきではありません)。

たとえば、このデータ行は問題ありません。

",Madrid,SN,,SEN,,,SN,173,157"

このデータ行は適切ではありません。

","Dominican, Republic of",MC,,YUO,,,MC,65,162",

いくつかのコード:

    conn = get_psycopg_conn()
    cur = conn.cursor()

    _io_buffer.seek(0) #This buffer is holding the csv-like data
    cur.copy_from(_io_buffer, str(table_name), sep=',', null='', columns=column_names)
    conn.commit()
12
wouldbesmooth

copy_fromcsvモードまたはquoteオプションを公開していないようです基盤となるPostgreSQL COPY command 。したがって、それらを追加するにはpsycopg2にパッチを適用するか、 copy_expert を使用する必要があります。

私はそれを試していませんが、

curs.copy_expert("""COPY mytable FROM STDIN WITH (FORMAT CSV)""", _io_buffer)

十分かもしれません。

19
Craig Ringer

これと同じエラーが発生し、 craig-ringer でリストされた1行のコードに基づいて修正に近づくことができました。私が必要とした他の項目は、df.to_csv(index=False,header=False, quoting=csv.QUOTE_NONNUMERIC,sep=',')、具体的には, quoting=csv.QUOTE_NONNUMERICを使用して、最初のオブジェクトの引用符を含めることでした。

MySQLから1つのデータソースをプルしてPostgresに保存する完全な例を以下に示します。

#run in python 3.6
import MySQLdb
import psycopg2
import os
from io import StringIO
import pandas as pd
import csv

mysql_db = MySQLdb.connect(Host="Host_address",# your Host, usually localhost
                     user="user_name",         # your username
                     passwd="source_pw",  # your password
                     db="source_db")       # name of the data base

postgres_db = psycopg2.connect("Host=dest_address dbname=dest_db_name user=dest_user password=dest_pw")

my_list = ['1','2','3','4']

# you must create a Cursor object. It will let you execute all the queries you need
mysql_cur = mysql_db.cursor()
postgres_cur = postgres_db.cursor()

for item in my_list:
  # Pull cbi data for each state and write it to postgres
  print(item)
  mysql_sql = 'select * from my_table t \
       where t.important_feature = \'' + item + '\';'

  # Do something to create your dataframe here...
  df = pd.read_sql_query(mysql_sql, mysql_db)

  # Initialize a string buffer
  sio = StringIO()
  sio.write(df.to_csv(index=False,header=False, quoting=csv.QUOTE_NONNUMERIC,sep=','))  # Write the Pandas DataFrame as a csv to the buffer
  sio.seek(0)  # Be sure to reset the position to the start of the stream

  # Copy the string buffer to the database, as if it were an actual file
  with postgres_db.cursor() as c:
      print(c)
      c.copy_expert("""COPY schema:new_table FROM STDIN WITH (FORMAT CSV)""", sio)
      postgres_db.commit()

mysql_db.close()
postgres_db.close()
0
jhtravis