如何使Python的请求包中的响应成为类似文件的对象"

时间:2014-07-17 08:38:45

标签: python python-requests psycopg2 amazon-redshift

我正在使用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中的类文件对象。谁知道我错过了什么?

1 个答案:

答案 0 :(得分:4)

您可以使用response.raw file object,但考虑到除非您将decode_content标记设置为True,否则任何内容编码(例如GZIP或Deflate压缩)仍然存在在调用.read()时,psycopg2不会。

您可以在raw文件对象上设置标志,将默认设置更改为解压缩时:

response.raw.decode_content = True

然后使用response.raw文件对象csv.DictReader()