2016-10-31 2 views
1

데이터가있는 일련의 .csv 파일이 있습니다. 파이썬 스크립트로 모든 파일을 열고 전처리 한 다음 처리 된 데이터를 내 포스트그레스 데이터베이스에 업로드하고 싶습니다.많은 레코드가 포스트그레스에 업로드

거의 완료되었지만 업로드 단계가 작동하지 않습니다. 나는 그것이 내가 누락 된 단순한 무언가이다라고 확신한다. 그러나 나는 단지 그것을 발견 할 수 없다. 네가 제공 할 수있는 도움을 주시면 감사하겠습니다.

여기에 코드입니다 :

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

각 레코드가 두어 개나되는 몇 개의 파일을 읽고 있습니다. 따라서 수천 개의 레코드가 있습니다. 다음 코드 행은 print 문에서 별개의 행으로 표시되도록합니다. 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)의 내용을 읽고, 당신은 시작, 예를 들어, 파일 포인터의 위치를 ​​변경해야한다 이것은 처음부터 읽고 upload_file의 모든 라인을 가져 copy_from 수 있습니다 seek(0)

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

사용합니다.


당신이 읽고 하나의 작은 수입을 위해 일 수있는 메모리에있는 모든 파일을 유지하지만, 병렬로 큰 수입 또는 여러 수입을 할 때 문제가 될 수 있다는 것을 잊지 마십시오.

+0

굉장합니다, 고마워요! –

+0

'메모리에있는 모든 파일을 읽고 작은 단일 가져 오기로 작동 할 수도 있지만 대량 가져 오기 나 여러 파일을 동시에 처리 할 때 문제가 될 수 있음을 잊지 마십시오. '이렇게하면 슬프다. 이런 식으로하는 이유는 수천 개의 레코드를 한꺼번에 업로드하는 것이 가장 빠른 방법이라고 생각했기 때문입니다.아카이브에서 더 좋은 제안을 찾을 수 있는지 찾아 보겠습니다. –

+0

메모리가 걱정된다면, 나쁘다고 말하면 안됩니다. 몇 천장 밖에 안되면 걱정하지 않으셔도됩니다. 만약 메모리가 문제가된다면 수정 된 CSV를 파이프에 쓰는 것이 좋을지 모르나'copy_from '에 의해 읽혀질 것입니다. –

관련 문제