2016-12-20 21 views
3

したがって、Python 3.5のpsycopg2ドライバを使用してPandas 19.xに次のコードを実行しています。psycopg2 Postgresメモリバッファを使用したPandas read_csvのCOPY EXPERTがValueErrorで失敗する

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 

Uh..wotパス? bufはメモリ内にあります。私はここで何が欠けていますか?

参考までに、コピー先が予期したとおりに動作しているようです。以下の回答には、以下の

おかげ

ソリューションコードは、私のクエリの速度が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') 

速度は、ポストグレースからデータをコピーして30秒未満でパンダのデータフレームにロードするのに約4分です。 copyコマンドはpsycopg2ドライバの機能であり、他のドライバでは動作しないことに注意してください。

+1

(おそらく空のデータフレームを得るでしょう、それなしで試してください))'だからちょうど 'df = pd.read_csv(buf、engine = 'c')'確かではない、ちょうど推測する – piRSquared

+1

@piRSquared:そうです。あなたはファイルハンドルを渡さなければなりません。そして、 'getvalue()'を渡すと、あなたはファイル名を渡しているとpandasが信じさせます。 –

+0

しかしそれ以上のことがあります:バッファオブジェクトを "巻き戻す"必要があります。そうしないと動作しません。 –

答えて

2

ファイルハンドルまたはファイル名をpandas.read_csv()に渡す必要があります。

バッファであるbuf.getvalue()は、オブジェクトがreadメソッドを持っていないので、あなたが「ファイル名」ことを除いて、ファイル名を渡していると信じてread_csvパンダを行い渡すと、それは、(ファイル名の255文字にウィンドウの制限を)など、あまりにも長い間見ています

あなたはほとんどそれを持っています。 bufは既にファイルのようなオブジェクトなので、そのままそのまま渡してください。小さなディテール:前cursor.copy_expert(sql_query, buf)呼び出しはおそらくwritebuf位置が末尾にある使用するので、あなたがそれを巻き戻す必要があり( `以降.getvalueを削除してみてください

buf.seek(0) # rewind because you're at the end of the buffer 
df = pd.read_csv(buf,engine='c') 
関連する問題