【问题标题】:copy command with psycopg2 library使用 psycopg2 库复制命令
【发布时间】:2013-07-09 22:20:14
【问题描述】:

是否可以通过 psycopg2 运行下面的命令?如果是这样,我该怎么做?

COPY table_name(col1,col2) FROM 'path/to/file.csv' WITH HEADER DELIMITER ',' CSV;

【问题讨论】:

    标签: python postgresql psycopg2


    【解决方案1】:

    copy_from 命令对于基本用例很有用:

    with open('path/to/file.csv') as f:
        cursor.copy_from(f, 'table_name', columns=('col1', 'col2'), sep=',')
    

    请注意,当按照您的问题所述复制 CSV 数据时,各种问题会阻止您使用 copy_from - 标题行、引用值、包含逗号的值。可以使用 copy_expert 命令通过简单的手动组合 COPY 查询导入 CSV:

    with open('path/to/file.csv') as f:
        cursor.copy_expert('COPY table_name(col1, col2) FROM STDIN WITH HEADER CSV', f)
    

    【讨论】:

      【解决方案2】:

      是的!

      您可以使用copy_from method:

      import psycopg2
      dbname=...
      user=...
      password=...
      host=...
      port=...
      con = psycopg2.connect(database=dbname,user=user,password=password,host=host,port=port)
      cur = con.cursor()    
      f = open('path/to/file.csv')
      cur.copy_from(f, 'test', columns=('col1', 'col2'), sep=",")
      con.commit()
      con.close()
      

      【讨论】:

      • 我们能否提及 copy_from 方法的引号。我在 csv 文件中的字符串列周围有双引号?
      • @shrinathM psycopg2 的 copy_from 当前不支持引用值,当您有一个重要的 CSV 文件时,请改用 copy_expert。
      【解决方案3】:

      Google 搜索 psycopg2 copy 发现 the psycopg manual 作为我的第一个搜索结果,其中包括有关使用客户端 COPY 的说明。

      如果您想要服务器端 COPY,您只需像运行任何其他 SQL 一样运行该语句。

      如上所述,该命令没有任何意义。我猜你打算写一个COPY ... TOCOPY ... FROM 命令并在隐藏真实文件名等的同时破坏它。

      【讨论】:

      • 你是对的,我的命令中有错字。我忘了运行 cur.commit()。感谢您的帮助!
      【解决方案4】:

      有一个使用copy_from 的交易破坏者:它不识别引用的字段,例如如果你有一个值with, a comma 并使用 csv.writer 那么它写为,"with, a comma"。 psycopg2 无法识别这一点(请参阅 @shrinathM 的引号注释)。

      这就是为什么在大多数情况下您需要回退到更基本的copy_expert

      也就是说,我在使用 COPY 时发现的另一件困难的事情是要了解 CSV 必须如何构造,以便 postgres 正确使用它。这里使用StringIO而不是文件的基本代码。

      以下解决方案向您展示了如何使用 python 编写 CSV 以及如何使用 copy_expert。如果您已经有 CSV,那么您只需要最后一行。

      import io
      import csv
      import datetime 
      
      f = io.StringIO()
      w = csv.writer(f)
      data = [
        ['Hans', [1,2,3], True],
        ['Kurt', [4], False],
      ]
      columns = ['name', 'ids', 'has_foo']
      print('convert to csv format')
      for l_in in data:
        l_out = []
        for v in l_in:
          if v == None:
            l_out.append('')
          elif type(v) in [str, int, datetime.date]:
            l_out.append(str(v))
          elif type(v) in [list, set, tuple]:
            l_out.append('{' + ','.join(str(i) for i in v) + '}')
          elif type(v) == bool:
            if v:
              l_out.append('t')
            else:
              l_out.append('f')
          else:
            print(f'unsupported type {type(v)}, writing str()')
            l_out.append(str(v))
        w.writerow(l_out)
      print('actual copy')
      f.seek(0)
      cursor = conn.cursor()
      cursor.copy_expert(f"""COPY my_table ({','.join(columns)}) FROM STDIN WITH (FORMAT CSV)""", f)
      conn.commit()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-20
        • 2012-07-10
        • 1970-01-01
        • 2019-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多