2016-10-31 40 views
1

我有一系列的.csv文件有一些數據,我希望有一個Python腳本打開他們,做一些預處理,並將處理後的數據上傳到我的Postgres數據庫。許多記錄上傳到Postgres的

我有它大部分完成,但我的上傳步驟不起作用。我確定這很簡單,我錯過了,但我無法找到它。我會很感激你能提供的任何幫助。

下面的代碼:

import psycopg2 
import sys 
from os import listdir 
from os.path import isfile, join 
import csv 
import re 
import io 

try: 
    con = db_connect("dbname = '[redacted]' user = '[redacted]' password = '[redacted]' host = '[redacted]'") 
except: 
    print("Can't connect to database.") 
    sys.exit(1) 
cur = con.cursor() 

upload_file = io.StringIO() 

file_list = [f for f in listdir(mypath) if isfile(join(mypath, f))] 
for file in file_list: 
    id_match = re.search(r'.*-(\d+)\.csv', file) 
    if id_match: 
     id = id_match.group(1) 
     file_name = format(id_match.group()) 
     with open(mypath+file_name) as fh: 
      id_reader = csv.reader(fh) 
      next(id_reader, None) # Skip the header row 
      for row in id_reader: 
       [stuff goes here to get desired values from file] 
       if upload_file.getvalue() != '': upload_file.write('\n') 
      upload_file.write('{0}\t{1}\t{2}'.format(id, [val1], [val2])) 

print(upload_file.getvalue()) # prints output that looks like I expect it to 
      # with thousands of rows that seem to have the right values in the right fields 

cur.copy_from(upload_file, '[my_table]', sep='\t', columns=('id', 'col_1', 'col_2')) 
con.commit() 

if con: 
    con.close() 

這將運行沒有錯誤,但在PSQL選擇查詢仍然顯示在表中沒有記錄。我錯過了什麼?

編輯:我結束了放棄並將其寫入到一個臨時文件,然後上傳文件。這工作沒有任何麻煩......我顯然寧願沒有臨時文件,所以我很高興有人看到這個問題的建議。

+0

代碼似乎沒問題。你說你的'print'行輸出了成千上萬行,但是你通過''t''作爲'copy_from'的分隔符。也許這就是問題所在? – lucasnadalutti

+0

我正在閱讀幾十個文件,每個文件有幾百條記錄,因此總共有幾千行。代碼的這條線,使他們出現在打印語句不同的行: 如果upload_file.getvalue()=「!」:upload_file.write(「\ n」) –

+0

是啊,這可能是問題呢。嘗試在'copy_from'參數中將'sep ='\ t''更改爲'sep ='\ n''並查看數據庫中是否有任何更改。 – lucasnadalutti

回答

1

當你寫一個io.StringIO(或任何其他文件)的對象,文件指針保持在寫入的最後一個字符的位置。所以,當你做

f = io.StringIO() 
f.write('1\t2\t3\n') 
s = f.readline() 

文件指針停留在文件的結尾和s包含一個空字符串。


閱讀(未getvalue)中的內容,您必須將文件指針重新定位開始,例如使用seek(0)

upload_file.seek(0) 
cur.copy_from(upload_file, '[my_table]', columns = ('id', 'col_1', 'col_2')) 

這使得copy_from從一開始就閱讀並導入所有的線在你upload_file


不要忘了,你看,並保持在你的記憶中的所有文件,這可能會爲一個小的進口工作,但在做平行進口大片或多個進口時,可能會成爲一個問題。

+0

真棒,謝謝! –

+0

'不要忘記,你閱讀並保存了所有文件在你的記憶中,這可能適用於一個小的輸入,但是當並行輸入大量輸入或多個輸入時可能會成爲問題。我這樣做的全部原因是我認爲這是一次上傳數千條記錄的最快方式。我會仔細研究一下,看看我能否在檔案中找到更好的建議。 –

+0

如果記憶是一個問題,我不會說它是壞的,只是要記住。如果只有幾千條記錄,我不會太擔心。如果內存是一個問題,您可以嘗試將修改的CSV寫入管道,然後通過'copy_from'讀取(如果可能的話)。 –