【问题标题】:How to ignore a csv delimiter on specific scenarios in python?如何在 python 的特定场景中忽略 csv 分隔符?
【发布时间】:2021-07-17 09:17:13
【问题描述】:

我正在尝试使用 CSV 文件在 DB 中插入数据。

import psycopg2 #import the postgres library
#connect to the database
conn = psycopg2.connect(host='1.11.11.111',
                   dbname='postgres',
                   user='postgres',
                   password='myPassword',
                   port='1234')  
#create a cursor object 
#cursor object is used to interact with the database
cur = conn.cursor()
#open the csv file using python standard file I/O
#copy file into the table just created 
with open("C:/Users/Harshal/Desktop/tar.csv", 'r') as f:
next(f) 
cur.copy_from(f, 'geotargets_india',sep=',')
conn.commit()
conn.close()
f.close()

我的表如下:

create table public.geotargets_india(
Criteria_ID integer not null,
Name character varying(50) COLLATE pg_catalog."default" NOT NULL,
Canonical_Name character varying(100) COLLATE pg_catalog."default" NOT NULL,
Parent_ID NUMERIC(10,2),
Country_Code character varying(10) COLLATE pg_catalog."default" NOT NULL,
Target_Type character varying(50) COLLATE pg_catalog."default" NOT NULL,
Status character varying(50) COLLATE pg_catalog."default" NOT NULL
)

我的 CSV 看起来像:

我得到的错误是: 例如,如果仔细查看我的 csv 行:1007740,Hyderabad,"Hyderabad,Telangana,India",9061642.0,IN,City,Active 。在这里,Canonical_Name 有“,”分隔的字符串,这会导致错误,并假设 CSV 中的列比表中的多。如何解决这个问题? 注意:我假设错误只是由于这个原因。 CSV Link

【问题讨论】:

标签: python postgresql csv psycopg2


【解决方案1】:

foo.csv:

It is header which will be ignored------------------------------------
1007740,Hyderabad,"Hyderabad,Telangana,India",9061642.0,IN,City,Active

Python:

import psycopg2
conn = psycopg2.connect('')
cur = conn.cursor()
f = open('foo.csv', 'r')
cur.copy_expert("""copy geotargets_india from stdin with (format csv, header, delimiter ',', quote '"')""", f)
conn.commit()

psql:

table geotargets_india;
┌─────────────┬───────────┬───────────────────────────┬────────────┬──────────────┬─────────────┬────────┐
│ criteria_id │   name    │      canonical_name       │ parent_id  │ country_code │ target_type │ status │
├─────────────┼───────────┼───────────────────────────┼────────────┼──────────────┼─────────────┼────────┤
│     1007740 │ Hyderabad │ Hyderabad,Telangana,India │ 9061642.00 │ IN           │ City        │ Active │
└─────────────┴───────────┴───────────────────────────┴────────────┴──────────────┴─────────────┴────────┘

【讨论】:

  • 我有一个后续问题:我们如何使用数据框而不是选择保存的文件,而不是将 CSV 作为文件读取?我正在使用 pandas 操作原始 CSV。
  • @eras'q 抱歉,我不是 Python/Pandas 专家,只是从这里和那里获得了一些知识。
【解决方案2】:

Canonical_Name 中的问题是正确的。我成功地将行1007740,Hyderabad,"Hyderabad",9061642.0,IN,City,Active 导入到您的结构表中。

很遗憾,copy_from 方法不支持 csv 分隔符参数。这是文档https://www.psycopg.org/docs/cursor.html#cursor.copy_from

因此您可以使用制表符分隔符重新格式化 csv 文件,然后使用 copy_from

import csv
import psycopg2 #import the postgres library
#connect to the database
conn = psycopg2.connect(host='1.11.11.111',
                   dbname='postgres',
                   user='postgres',
                   password='myPassword',
                   port='1234')
#create a cursor object
#cursor object is used to interact with the database
cur = conn.cursor()
#open the csv file using python standard file I/O
#copy file into the table just created

with open("C:/Users/Harshal/Desktop/tar.csv", 'r') as f:
    reader = csv.reader(f, delimiter=",")
    with open("C:/Users/Harshal/Desktop/tar.tsv", 'w') as tsv:
        writer = csv.writer(tsv, delimiter='\t')
        writer.writerows(reader)

with open("C:/Users/Harshal/Desktop/tar.tsv", 'r') as f:
    next(f)
    cur.copy_from(f, 'geotargets_india',sep='\t')
    conn.commit()
    conn.close()
    f.close()

【讨论】:

  • 在 `cur.copy_from(f, 'geotargets_india',sep='\t') 行出现错误 InvalidTextRepresentation: invalid input syntax for type integer: "" CONTEXT: COPY geotargets_india, line 1, column criteria_id: "" `
【解决方案3】:

您应该自己在 Python 中读取和解析 CSV 文件,然后使用 INSERT 语句将数据加载到数据库中。

import csv
import psycopg2

conn = psycopg2.connect(
    host='1.11.11.111',
    dbname='postgres',
    user='postgres',
    password='myPassword',
    port='1234'
)  
cur = conn.cursor()

with open("tar.csv") as fd:
    rdr = csv.DictReader(fd)
    cur.executemany("""
        INSERT INTO geotargets_india
        VALUES (%(Criteria_ID)s, %(Name)s, %(Canonical_Name)s, %(Parent_ID)s, %(Country_Code)s, %(Target_Type)s, %(Status)s);
        """,
        rdr
    )

cur.close()
conn.close()

上面有几个cmets。 csv.DictReader 类将返回您的 CSV 字典。返回的 DictReader 对象 rdr 是可迭代的,因此可以直接在 psycopg2 的 cursor.executemany 函数中使用,这可能比自己遍历 csv DictReader 对象效率更高。

【讨论】:

  • 我必须在导入之前安装 CSV 对吗?我试过 pip install csv 并得到错误ERROR: Could not find a version that satisfies the requirement csv (from versions: none) ERROR: No matching distribution found for csv
  • 不,csv 是 Python 标准库的一部分,因此您不必安装它。查看它的documentation
  • 谢谢,但仍然收到来自---> 22 cur.executemany(""" 行的错误InvalidTextRepresentation: invalid input syntax for type numeric: "" LINE 3: VALUES ('2356', 'India', 'India', '', 'IN', 'Country...
  • 看起来该行中的 Parent_ID(第四个值)为空白或缺失。对于 psycopg2,空白字符串 ('') 与数字类型不兼容。如果在这种情况下您期望 NULL 值,那么您需要将空白字符串转换为 None
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-20
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 2014-08-14
相关资源
最近更新 更多