导出数据框时如何修复“发电机”对象没有属性“ to_csv”

时间:2019-07-14 07:16:35

标签: python oracle pandas sqlalchemy export-to-csv

我正在使用Python将数据从Oracle表导出到Pandas DataFrame,然后再导出到CSV文件。

但是我收到此错误:

AttributeError: 'generator' object has no attribute 'to_csv'

我找不到我的代码存在的问题:

import cx_Oracle
import csv
import pandas as pd
import sqlalchemy
from sqlalchemy import create_engine

DATABASE = "MY database"
SCHEMA   = "MY USER"
PASSWORD = "MY PASS"
connstr  = "oracle://{}:{}@{}".format(SCHEMA, PASSWORD, DATABASE)
conn     = sqlalchemy.create_engine(connstr)
result=pd.read_sql('My QUERY' , con=conn, chunksize=10000)
result.to_csv("test",sep=',',chunksize=10000)

1 个答案:

答案 0 :(得分:3)

为您提供了数据帧的 iterator ,而不是单个数据帧(生成器是迭代器的一种),因为您指定了chunksize值。参见pandas.read_sql() documentation

  

块大小 int,默认为无

     

如果指定,则返回一个迭代器,其中 chunksize 是每个块中要包括的行数。

您需要遍历该迭代器;最简单的方法是使用for循环。然后,当您写出CSV文件时,您不想再次使用分块。您应该改为在 append 模式下打开输出文件,以便将每个块作为新行添加到文件中:

chunks = pd.read_sql('My QUERY', con=conn, chunksize=10000)
for chunk in chunks:  # each chunk is a dataframe
    # append the data from each chunk to the same output file
    chunk.to_csv("test.csv", sep=",", mode="a")

但这不是从表中生成CSV文件的有效方法!如果您使用Oracle SQL * Plus命令行工具,则可以更有效地获取CSV文件,请参阅Oracle自己的博客文章Fast Generation of CSV and JSON from Oracle Database

即使只是将SQLAlchemy查询直接流式传输到csv.writer()对象,也会更好:

import cx_Oracle
import csv
from sqlalchemy import create_engine

DATABASE  = "MY database"
SCHEMA    = "MY USER"
PASSWORD  = "MY PASS"
BATCHSIZE = 10000
connstr   = "oracle://{}:{}@{}".format(SCHEMA, PASSWORD, DATABASE)
engine   = sqlalchemy.create_engine(connstr, arraysize=BATCHSIZE)
conn     = engine.connect()
with open("test.csv", "w") as outputfile:
    writer = csv.writer(outputfile)
    results = conn.execute('My QUERY')
    writer.writerows(results)

然后,cx_Oracle库为您分批将结果从数据库流传输到Python,然后writer.writerows()将这些结果写入CSV文件。批处理大小由arraysize参数控制,该参数指示cx_Oracle库每次在服务器和客户端之间的往返中加载多少行。如果您必须使用DataFrame,您可能也想在熊猫代码中进行设置。

您实际上也不需要SQLAlchemy;您可以直接在此处直接使用cx_Oracle,并设置cursor.arraysize parameter

import cx_Oracle
import csv

DATABASE  = "MY database"
SCHEMA    = "MY USER"
PASSWORD  = "MY PASS"
BATCHSIZE = 10000

conn      = cx_Oracle.connect(user=SCHEMA, password=PASSWORD, dsn=DATABASE)
cursor    = connection.cursor()
cursor.arraysize = BATCHSIZE

with open("test.csv", "w") as outputfile:
    writer = csv.writer(outputfile)
    results = cursor.execute('My QUERY')
    writer.writerows(results)