【问题标题】:COPY-FROM within python connection.execute: csv into postgres - no error but also no datapython connection.execute中的COPY-FROM:csv到postgres - 没有错误但也没有数据
【发布时间】:2018-03-28 19:39:24
【问题描述】:

我正在尝试将数据从 csv 加载到我的 postgres 数据库。我正在使用 sqlalchemy(以及连接/原始 sql 数据方法而不是 ORM 方法)。但是,我成功地创建了具有相应字段的表。使用 copy-from 时没有任何反应:我没有收到错误,但我的表也是空的。

conn = eng.connect()
trans = conn.begin()

try: 
    conn.execute("""CREATE TABLE IF NOT EXISTS table_name(var1 numeric, date date, time time, datetime timestamp primary key,....);""")
    trans.commit()
except:
    trans.rollback()
    raise

try: 
    # File 1 bid
    conn.execute("""COPY table_name FROM '/home/user/csvfile.csv' 
    WITH CSV HEADER DELIMITER as ','""")
    trans.commit()
except:
    trans.rollback()
    raise

Jupyter 笔记本没有报告错误消息。

我做错了什么?

另外,我不太明白:

file = "/home/user/csvfile.csv"
  conn.execute("""COPY table_name FROM file 
        WITH CSV HEADER DELIMITER as ','""")

在“文件”中产生错误。

【问题讨论】:

  • 数据库和应用程序是否在同一个服务器,这样数据库也可以访问/home/user/csvfile.csv?
  • 你好 Jim,是的,他们都在同一个服务器上;我正在使用 AWS。

标签: python postgresql csv sqlalchemy connection


【解决方案1】:

事务不可重用:

>>> trans = conn.begin()
2018-03-29 09:14:33,001 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
>>> trans.commit()
2018-03-29 09:14:35,449 INFO sqlalchemy.engine.base.Engine COMMIT
>>> trans.commit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/u/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1642, in commit
    raise exc.InvalidRequestError("This transaction is inactive")
sqlalchemy.exc.InvalidRequestError: This transaction is inactive
>>> trans.rollback()
>>> 

您必须在第一个事务之后开始一个新事务,或者在同一个事务中执行所有操作。

另一方面,这并不能解释您的 COPY 失败的原因。在上一个显式事务结束后,连接回退到autocommit。换句话说,如果没有事务正在进行,则引擎或连接将提交。但这里有个问题:自动提交是基于检测数据更改操作,这是由matching the given statement 针对

AUTOCOMMIT_REGEXP = re.compile(
    r'\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER|GRANT|REVOKE|'
    'IMPORT FOREIGN SCHEMA|REFRESH MATERIALIZED VIEW|TRUNCATE)',
    re.I | re.UNICODE)

您可能会注意到,COPY 不是该正则表达式的一部分。如前所述,您最好的选择是启动另一个显式事务,或者在同一个事务中执行这两个操作。但是,如果您希望在未来某个时间通过 COPY 使用自动提交,请指示 SQLAlchemy 它应该自动提交:

conn.execute(text("COPY ...").execution_options(autocommit=True))

对于后一个错误,FROM file 没有神奇地访问 Python 变量,是一个语法错误。将文件名作为参数传递给查询:

copy_stmt = text("COPY table_name FROM :file WITH CSV HEADER")
copy_stmt = copy_stmt.execution_options(autocommit=True)
conn.execute(copy_stmt, {"file": file})

请注意,COPY from a file 需要您可能不应该拥有的权限:

COPY 命名文件或命令只允许数据库超级用户使用,因为它允许读取或写入服务器有权访问的任何文件。

解决方案是使用COPY ... FROM STDIN,但要使用you have to use a raw DB-API connection

file = "/home/user/csvfile.csv"
stmt = "COPY table_name FROM STDIN CSV HEADER"

raw_conn = eng.raw_connection()

# Uses the actual psycopg2 connection as a context manager
# for transaction handling.
with open(file) as f, \
        raw_conn.connection, \
        raw_conn.cursor() as cur:
    cur.copy_expert(stmt, f)

raw_conn.close()

【讨论】:

  • 谢谢你,Ijla。就是这样。谈到后两种方法,自动提交和使用原始连接。展望未来,是否有推荐的方式,还是取决于具体情况?
【解决方案2】:

尝试添加“;”到您的复制命令。 ... 分隔符 ',' CSV ;" :-)

【讨论】:

  • 感谢 Slumdog,我补充说,但它不起作用:Ilja 的答案是解决方案 :)
猜你喜欢
  • 2016-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2019-03-16
  • 2014-01-25
相关资源
最近更新 更多