我需要打开一些XML文件,然后进行处理以生成大量行,然后将这些行插入远程postgress数据库中的多个表中。
要提取XML数据,我使用xml.etree.ElementTree
来解析XML树并根据需要提取元素。虽然我正在做很多事情,但基本的操作是采用一个特定的元素,无论是字符串还是整数,并放在一些字典中。
经过一些处理之后,我需要将一些字典插入到我的数据库中。对于任何单个xml文件,我可以在3个表中生成最多8-10,000行(或查询)。
在测试时,我输出到sql文件,然后手动运行查询。如果我有很多xml文件,那显然不会起作用..
因此我尝试使用psycopg2
来自动完成此过程。据我了解,从堆栈溢出和其他地方运行单个execute
函数是非常缓慢的。基于This stackoverflow question,我试图编写如下代码:
QueryData = ','.join(cur.mogrify('(%s,%s,%s)', row) for row in myData)
cur.execute('INSERT INTO DBTABLE' + QueryData)
cur.commit()
其中myData
是元组[(a,b,c),(a,b,c),(a,b,c)...]
的列表,其内容是xml.etree.ElementTree
提取的数据和我自己计算的值的组合。
当我尝试实际执行上面的代码时,我收到以下错误:
TypeError: sequence item 0: expected str instance, bytes found
好的......如果我然后尝试将我的数据(每个元组元素)转换为str()
但是我得到了:
TypeError: encoding without a string argument
我是否只是完全错了?我该怎么做我需要的东西?我正在使用Python3。
其他
我被要求展示数据的一个例子。
这是最简单的,它是3个整数值放入表中。它的格式为:(document_id,item_index,item_code)
一个典型的例子是:(937, 138, 681)
我转换的一般尝试是尝试:
(str(document_id),str(item_index),str(item_code))
我也尝试过另一种方式:
(bytes(document_id,'utf-8'),bytes(item_index,'utf-8'),bytes(item_code,'utf-8'))
后者也会引发错误:TypeError: encoding without a string argument
答案 0 :(得分:2)
psycopg documentation表示对于cur.mogrify:
返回的字符串始终是字节字符串。
所以要使用这个hack,你只需要将mogrify的结果解码回字符串,例如:
QueryData = ','.join(cur.mogrify('(%s,%s,%s)', row).decode('utf-8') for row in myData)
cur.execute('INSERT INTO DBTABLE' + QueryData)
但是,如this StackOverflow question中所述,复制大量数据的最有效方法是使用COPY。您可以使用任何“类似python文件的对象”来完成此操作。以下是psycopg文档中的一个示例:
>>> f = StringIO("42\tfoo\n74\tbar\n")
>>> cur.copy_from(f, 'test', columns=('num', 'data'))
>>> cur.execute("select * from test where id > 5;")
>>> cur.fetchall()
[(6, 42, 'foo'), (7, 74, 'bar')]
答案 1 :(得分:0)
你在表名后丢失了VALUES,其他一切似乎都是正确的:
cursorPG.execute(“插入测试 VALUES ”+','。join(cursorPG.mogrify('(%s,%s)',x)for m in mydata))< / p>
答案 2 :(得分:0)
好的,所以我让它工作......但是我很困惑为什么我的解决方案有效。我发布它作为答案,但如果有人可以向我解释发生了什么将是伟大的:
基本上是这样的:QueryData = ','.join(cur.mogrify('(%s,%s,%s)', row) for row in myData)
cur.execute('INSERT INTO DBTABLE' + QueryData)
必须改为:
QueryData = b','.join(cur.mogrify(b'(%s,%s,%s)', row) for row in myData)
cur.execute(b'INSERT INTO DBTABLE' + QueryData)
这让我觉得非常不优雅。