所以我使用Python 3.5中的psycopg2驱动程序运行以下代码到Pandas 19.x.
buf = io.StringIO()
cursor = conn.cursor()
sql_query = 'COPY ('+ base_sql + ' limit 100) TO STDOUT WITH CSV HEADER'
cursor.copy_expert(sql_query, buf)
df = pd.read_csv(buf.getvalue(),engine='c')
buf.close()
从内存缓冲区读取时, read_csv 会破坏块:
pandas\parser.pyx in pandas.parser.TextReader.__cinit__ (pandas\parser.c:4175)()
pandas\parser.pyx in pandas.parser.TextReader._setup_parser_source (pandas\parser.c:8333)()
C:\Users\....\AppData\Local\Continuum\Anaconda3\lib\genericpath.py in exists(path)
17 """Test whether a path exists. Returns False for broken symbolic links"""
18 try:
---> 19 os.stat(path)
20 except OSError:
21 return False
ValueError: stat: path too long for Windows
呃......路径? buf在记忆中。我在这里错过了什么?
仅供参考,Copy to似乎按预期工作。
以下解决方案代码
感谢下面的答案,我的查询速度使用此方法加倍,我的内存使用率下降了500%。这是我的最终测试代码,以帮助其他人解决他们的性能问题。我很想看到任何可以改善这一点的代码!请务必在问题中链接回这个问题。
# COPY TO CSV quick and dirty performance test
import io
import sys
start = time.time()
conn_str_copy= r'postgresql+psycopg2://' + user_id + r":" + pswd + r"@xxx.xxx.xxx.xxx:ppppp/my_database"
result = urlparse(conn_str_copy)
username = result.username
password = result.password
database = result.path[1:]
hostname = result.hostname
size = 2**30
buf = io.BytesIO()
# buf = io.StringIO()
engine = create_engine(conn_str_copy)
conn_copy= psycopg2.connect(
database=database, user=username, password=password, host=hostname)
cursor_copy = conn_copy.cursor()
sql_query = 'COPY ('+ my_sql_query + ' ) TO STDOUT WITH CSV HEADER'
cursor_copy.copy_expert(sql_query, buf, size)
print('time:', (time.time() - start)/60, 'minutes or ', time.time() - start, 'seconds')
tmp = buf.seek(0)
df = pd.read_csv(buf,engine='c', low_memory=False )
buf.close()
print('time:', (time.time() - start)/60, 'minutes or ', time.time() - start, 'seconds')
从postgres复制数据的速度约为4分钟,而将其加载到pandas数据帧的时间不到30秒。请注意,复制命令是psycopg2驱动程序的一项功能,可能无法在其他驱动程序中使用。
答案 0 :(得分:2)
您必须将文件句柄或文件名传递给pandas.read_csv()
。
传递buf.getvalue()
会让大熊猫read_csv
相信您传递了文件名,因为对象没有read
方法,除了"文件名&# 34;是缓冲区,它看起来太长(窗口限制为文件名255个字符)
你几乎得到了它。由于buf
已经是类文件对象,因此只需按原样传递即可。小细节:您必须回放它,因为之前的cursor.copy_expert(sql_query, buf)
调用可能使用了write
并且buf
位置在最后(尝试没有它,您可能会得到一个空的数据帧)
buf.seek(0) # rewind because you're at the end of the buffer
df = pd.read_csv(buf,engine='c')