Sqlalchemy psycopg2.copy_from:从CSV导入时删除文本中的引号

Sqlalchemy psycopg2.copy_from:从CSV导入时删除文本中的引号,sqlalchemy,psycopg2,Sqlalchemy,Psycopg2,我有一个CSV文件,其中所有条目都被引用,即带有开始和结束引号。当我使用copy\u from导入数据库时,数据库表包含数据的引号,如果有空条目,我只会得到引号,即列中的“”条目,如下所示 [ 有没有一种方法可以告诉copy_from忽略引号,这样当我导入文件时,文本周围就没有引号,空条目将转换为Null,如下所示 这是我的密码: with open(source_file_path) as inf: cursor.copy_from(inf, table_name, columns=co

我有一个CSV文件,其中所有条目都被引用,即带有开始和结束引号。当我使用
copy\u from
导入数据库时,数据库表包含数据的引号,如果有空条目,我只会得到引号,即列中的“”条目,如下所示

[

有没有一种方法可以告诉copy_from忽略引号,这样当我导入文件时,文本周围就没有引号,空条目将转换为Null,如下所示

这是我的密码:

with open(source_file_path) as inf:
  cursor.copy_from(inf, table_name, columns=column_list, sep=',', null="None")
更新

我还没有找到解决上述问题的方法,但为了导入文件,我继续编写原始SQL代码,并在SQLAlchemy connection和Pyscopg2的游标中执行,如下所示,它们都删除了引号,并在有空条目的地方使用Null

sql = "COPY table_name (col1, col2, col3, col4) FROM '{}' DELIMITER ',' CSV HEADER".format(csv_file_path)
SQL炼金术:

Psycopg2:


虽然仍然希望
copy\u from
功能可以工作,但现在我想知道上面两个是否与
copy\u from
一样快,如果是,两个中的哪一个更快?

可能更好的方法是使用内置的CSV库读取CSV文件并将行传输到数据库。UNIX phi的推论“只做一件事,把它做好”的缺点是使用合适的工具(专门化的工具)。CSV库的好处是,您可以自定义如何读取CSV,如引用字符和跳过初始行(请参阅)

假设一个简单的CSV文件有两列:一个整数“ID”,一个带引号的字符串“Country Code”:

和声明性SQLAlchemy目标表:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base


engine = create_engine("postgresql+psycopg2://<REMAINDER_OF_YOUR_ENGINE_STRING>")
Base = declarative_base(bind=engine)

class CountryTable(Base):
    __tablename__ = 'countries'

    id = Column(Integer, primary_key=True)
    country = Column(String)
此解决方案比一行.copy_from方法长,但它提供了更好的控制,而无需深入研究代码/了解包装器或方便函数(如.copy_from)的文档。您可以指定要传输的选定列,并在行级别处理异常,因为数据是通过co逐行传输的mmit。行可以通过以下方式通过单个提交在批处理中传输:

with open("path_to_your.csv", "rb") as f:
    reader = csv.DictReader(f)
    session = Session()
    session.add_all([
        CountryTable(id=row["ID"], country=row["Country Code"]) for row in reader
        ])
    session.commit()
    session.close()    
要比较解决问题的不同方法的执行时间,请使用Python附带的模块(或者更确切地说是命令行命令)。但是,请注意:


编辑:


我试图找出.copy_from的编码位置,因为我以前没有使用过它。它原来是。它不100%支持读取CSV文件,只支持类似文件的对象。唯一适用于CSV的自定义参数是分隔符。它不理解引用字符。

可能更好的方法是使用内置In CSV库读取CSV文件并将行传输到数据库。UNIX“做一件事,做好一件事”理念的必然结果是使用适当的工具(专用工具)CSV库的好处在于,您可以自定义如何读取CSV,例如引用字符和跳过初始行(请参阅)

假设一个简单的CSV文件有两列:一个整数“ID”,一个带引号的字符串“Country Code”:

和声明性SQLAlchemy目标表:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base


engine = create_engine("postgresql+psycopg2://<REMAINDER_OF_YOUR_ENGINE_STRING>")
Base = declarative_base(bind=engine)

class CountryTable(Base):
    __tablename__ = 'countries'

    id = Column(Integer, primary_key=True)
    country = Column(String)
此解决方案比一行.copy_from方法长,但它提供了更好的控制,而无需深入研究代码/了解包装器或方便函数(如.copy_from)的文档。您可以指定要传输的选定列,并在行级别处理异常,因为数据是通过co逐行传输的mmit。行可以通过以下方式通过单个提交在批处理中传输:

with open("path_to_your.csv", "rb") as f:
    reader = csv.DictReader(f)
    session = Session()
    session.add_all([
        CountryTable(id=row["ID"], country=row["Country Code"]) for row in reader
        ])
    session.commit()
    session.close()    
要比较解决问题的不同方法的执行时间,请使用Python附带的模块(或者更确切地说是命令行命令)。但是,请注意:


编辑:


我试图找出.copy_from的编码位置,因为我以前没有使用过它。它原来是。它不100%支持读取CSV文件,只支持类似文件的对象。唯一适用于CSV的自定义参数是分隔符。它不理解引用字符。

谢谢。我广泛使用CSV库,但我当我需要控制每列和每行(单元格)时使用它尤其是在验证数据时。然而,在这种情况下,数据符合所有要求,并且包含在多个14GB文件中,因此感觉逐行读取将是“浪费时间”,因为从中进行简单的
复制需要几分钟时间才能将这些类型的文件吞噬掉。我刚刚遇到了这个问题。这是一个多么愚蠢的函数。他们应该扔掉它谢谢。我广泛使用CSV库,但当我需要控制每一列和每一行(单元格)时,我会使用它尤其是在验证数据时。然而,在这种情况下,数据符合所有要求,并且包含在多个14GB文件中,因此感觉逐行读取将是“浪费时间”,因为从
中进行简单的
复制需要几分钟时间才能将这些类型的文件吞噬掉。我刚刚遇到了这个问题。这是一个多么愚蠢的函数。他们应该扔掉它出来
import csv

from sqlalchemy.orm import sessionmaker

from your_model_module import engine, CountryTable


Session = sessionmaker(bind=engine)
with open("path_to_your.csv", "rb") as f:
    reader = csv.DictReader(f)
    session = Session()
    for row in reader:
        country_record = CountryTable(id=row["ID"], country=row["Country Code"])
        session.add(country_record)
        session.commit()
    session.close()
with open("path_to_your.csv", "rb") as f:
    reader = csv.DictReader(f)
    session = Session()
    session.add_all([
        CountryTable(id=row["ID"], country=row["Country Code"]) for row in reader
        ])
    session.commit()
    session.close()