[PYTHON] Mit psycopg2 aus pd.DataFrame einfügen

Ich habe versucht, unter Bezugnahme auf den Artikel hier einzufügen, bin aber gestolpert und werde ihn aufschreiben. Es ist fast das gleiche, aber es gab zwei Probleme beim Einfügen von Zeichenketten. Codierungsfehler beim Einfügen einer japanischen Zeichenfolge und Codierungsfehler einer Zeichenfolge mit einem Backslash.

Implementierung

from io import StringIO
from typing import List

import pandas as pd
import psycopg2

class Client:
    def __init__(self, dsn: str) -> None:
        """
        Arguments:
            dsn(str): 'postgresql://{username}:{password}@{hostname}:{port}/{dbname}'
        """
        self._cur = None
        self._conn = psycopg2.connect(dsn)
        self._conn.set_client_encoding('UTF8')
        self._cur = self._conn.cursor()

    def __del__(self) -> None:
        if self._cur is not None:
            self._cur.close()

        self._conn.close()

    def insert(self, table: str, values: pd.DataFrame) -> None:
        buf = StringIO()
        df.to_csv(buf, sep='\t', na_rep='\\N', index=False, header=False)
        buf.seek(0)
        columns = df.columns.values.tolist()
        self._cur.copy_from(buf, table, columns=columns)
        self._conn.commit()

Diesmal ist es nicht passiert, aber es scheint, dass es auch beim Umgang mit "NULLABLE" Integer-Typen in "pd.DataFrame" einen Fehler verursachen kann. Siehe auch: https://qiita.com/hoto17296/items/b6c90db4b9bcdb7b6d78

Japanisches Codierungsproblem

Gelöst mit set_client_encoding ('UTF8') Referenz: https://www.psycopg.org/docs/connection.html#connection.set_client_encoding

Backslash-Problem

Ich habe dies von außen implementiert, aber ich habe es vermieden, indem ich Folgendes getan habe. Nehmen wir an, dass die Spalte "a" eine Zeichenfolge ist

import os


df = get_dataframe()  #Holen Sie sich den Datenrahmen in irgendeiner Weise
df.a = df.a.str.replace('\\', '\\\\')

client = Client(os.environ.get('POSTGRES_DSN')
client.insert(table, df)

Andere Implementierungen

Oben haben wir "copy_from" verwendet, aber wenn wir "copy_expert" verwenden, können wir wie folgt schreiben.

cur.copy_expert(
    f"""
        COPY {table}(
            {','.join(columns)}
        )
        FROM STDIN
        WITH
            DELIMITER AS ' '
            NULL AS '\\N'
        ENCODING 'utf8'
    """,
    buf,
)

Wir brauchen keine set_client_encoding ('UTF8'), da wir die Codierung in der Abfrage angeben.

Referenz: https://www.psycopg.org/docs/cursor.html#cursor.copy_expert

Recommended Posts

Mit psycopg2 aus pd.DataFrame einfügen
Bulk Insert Pandas DataFrame mit psycopg2
Generieren Sie mit Python eine Einfügeanweisung aus CSV.
Mit Skype benachrichtigen Sie mit Skype von Python!
Rufen Sie C von Python mit DragonFFI auf
Installieren Sie Python von der Quelle mit Ansible
Holen Sie sich mit DataFrame eine Spalte aus DataFrame
Informationen zu Transaktionen beim Betrieb von PostgreSQL mit Psycopg2
Frei von der harten Codierung von Funktionen mit SymPy
Führen Sie Aprili von Python auf Orange aus
Betreiben Sie Maya mit OSC von vvvv
Rufen Sie Python von Nim mit Nimpy auf
Verwenden Sie PostgreSQL mit Lambda (Python + psycopg2)
Laden Sie fbx aus Python mitinema4d