我正在使用Python的requests
库进行Web服务,并且端点正在返回一个(非常大的)CSV文件,然后我想将其流式传输到数据库中。代码如下所示:
response = requests.get(url, auth=auth, stream=True)
if response.status_code == 200:
stream_csv_into_database(response)
现在,当数据库是MongoDB数据库时,使用DictReader
完美加载:
def stream_csv_into_database(response):
.
.
.
for record in csv.DictReader(response.iter_lines(), delimiter='\t'):
product_count += 1
product = {k:v for (k,v) in record.iteritems() if v}
product['_id'] = product_count
collection.insert(product)
但是,我正在从MongoDB切换到Amazon RedShift,我已经可以使用psycopg2
访问它了。我可以打开连接并进行简单的查询,但我想要做的是使用来自webservice的流式响应并使用psycopg2的copy_expert
来加载RedShift表。这是我到目前为止所尝试的:
def stream_csv_into_database(response, campaign, config):
print 'Loading product feed for {0}'.format(campaign)
conn = new_redshift_connection(config) # My own helper, works fine.
table = 'products.' + campaign
cur = conn.cursor()
reader = response.iter_lines()
# Error on following line:
cur.copy_expert("COPY {0} FROM STDIN WITH CSV HEADER DELIMITER '\t'".format(table), reader)
conn.commit()
cur.close()
conn.close()
我得到的错误是:
文件必须是COPY FROM的可读文件对象; COPY TO的可写文件对象。
我明白错误在说什么;事实上,我可以从psycopg2 documentation看到copy_expert
来电copy_from
,其中:{/ p>
从类似文件的对象读取数据,将它们附加到数据库表(COPY表FROM文件语法)。源文件必须同时具有read()和readline()方法。
我的问题是我无法找到使response
对象成为类文件对象的方法!我尝试.data
和.iter_lines
都没有成功。我当然不想从webservice下载整个multi-gigabyte文件,然后将其上传到RedShift。必须有一种方法可以将流式响应用作psycopg2可以复制到RedShift中的类文件对象。谁知道我错过了什么?
答案 0 :(得分:4)
您可以使用response.raw
file object,但考虑到除非您将decode_content
标记设置为True
,否则任何内容编码(例如GZIP或Deflate压缩)仍然存在在调用.read()
时,psycopg2不会。
您可以在raw
文件对象上设置标志,将默认设置更改为解压缩时:
response.raw.decode_content = True
然后使用response.raw
文件对象csv.DictReader()
。