Zrobiłem sporo spostrzeżenia na temat tego błędu i sprowadziłem to do faktu, że bazy danych, z którymi pracuję, są w różnych kodowaniach.psycopg2.DataError: niepoprawna sekwencja bajtów dla kodowania "UTF8": 0xa0
Serwer AIX Pracuję z działa
psql 8.2.4
server_encoding | LATIN1 | | Client Connection Defaults/Locale and Formatting | Sets the server (database) character set encoding.
okien 2008 R2 serwera Pracuję z działa
psql (9.3.4)
CREATE DATABASE postgres
WITH OWNER = postgres
ENCODING = 'UTF8'
TABLESPACE = pg_default
LC_COLLATE = 'English_Australia.1252'
LC_CTYPE = 'English_Australia.1252'
CONNECTION LIMIT = -1;
COMMENT ON DATABASE postgres
IS 'default administrative connection database';
Teraz kiedy próbuję wykonać mój skrypt poniżej Pythona Otrzymuję ten błąd
Traceback (most recent call last):
File "datamain.py", line 39, in <module>
sys.exit(main())
File "datamain.py", line 33, in main
write_file_to_table("cms_jobdef.txt", "cms_jobdef", con_S104838)
File "datamain.py", line 21, in write_file_to_table
cur.copy_from(f, table, ",")
psycopg2.DataError: invalid byte sequence for encoding "UTF8": 0xa0
CONTEXT: COPY cms_jobdef, line 15209
Oto mój skrypt
import psycopg2
import StringIO
import sys
import pdb
def connect_db(db, usr, pw, hst, prt):
conn = psycopg2.connect(database=db, user=usr,
password=pw, host=hst, port=prt)
return conn
def write_table_to_file(file, table, connection):
f = open(file, "w")
cur = connection.cursor()
cur.copy_to(f, table, ",")
f.close()
cur.close()
def write_file_to_table(file, table, connection):
f = open(file,"r")
cur = connection.cursor()
cur.copy_from(f, table, ",")
f.close()
cur.close()
def main():
login = open('login.txt','r')
con_tctmsv64 = connect_db("x", "y",
login.readline().strip(),
"d.domain", "c")
con_S104838 = connect_db("x", "y", "z", "a", "b")
try:
write_table_to_file("cms_jobdef.txt", "cms_jobdef", con_tctmsv64)
write_file_to_table("cms_jobdef.txt", "cms_jobdef", con_S104838)
finally:
con_tctmsv64.close()
con_S104838.close()
if __name__ == "__main__":
sys.exit(main())
zostały usunięte niektóre dane wrażliwe.
Więc nie jestem pewien, jak mogę kontynuować. O ile mogę powiedzieć, że metoda copy_expert może pomóc, eksportując jako kodowanie UTF8. Ale ponieważ serwer, z którego pobieram dane, działa 8.2.4 Nie sądzę, że obsługuje format kodowania COPY.
Myślę, że moim najlepszym strzałem jest próba ponownej instalacji bazy danych postgre z kodowaniem LATIN1 na serwerze Windows. Kiedy próbuję to zrobić, otrzymuję poniższy błąd.
Więc im zupełnie zatrzymany, każda pomoc będzie bardzo mile widziane!
Aktualizacja Zainstalowałem postgre db w oknach jako kodowanie LATIN1, zmieniając domyślny lokalny na "C". Ten jednak dał mi poniższy błąd i nie robi wydaje się prawdopodobne udanej/prawidłowego podejścia
Próbowałem również kodowania plików w formacie binarnym za pomocą psql COPY funkcję
def write_table_to_file(file, table, connection):
f = open(file, "w")
cur = connection.cursor()
#cur.copy_to(f, table, ",")
cur.copy_expert("COPY cms_jobdef TO STDOUT WITH BINARY", f)
f.close()
cur.close()
def write_file_to_table(file, table, connection):
f = open(file,"r")
cur = connection.cursor()
#cur.copy_from(f, table)
cur.copy_expert("COPY cms_jobdef FROM STDOUT WITH BINARY", f)
f.close()
cur.close()
nadal nie ma szczęścia Pojawia się ten sam błąd:
DataError: invalid byte sequence for encoding "UTF8": 0xa0
CONTEXT: COPY cms_jobdef, line 15209, column descript
W odniesieniu do odpowiedzi Phils próbowałem tego podejścia z wciąż nie ma su ccess.
import psycopg2
import StringIO
import sys
import pdb
import codecs
def connect_db(db, usr, pw, hst, prt):
conn = psycopg2.connect(database=db, user=usr,
password=pw, host=hst, port=prt)
return conn
def write_table_to_file(file, table, connection):
f = open(file, "w")
#fx = codecs.EncodedFile(f,"LATIN1", "UTF8")
cur = connection.cursor()
cur.execute("SHOW client_encoding;")
print cur.fetchone()
cur.copy_to(f, table)
#cur.copy_expert("COPY cms_jobdef TO STDOUT WITH BINARY", f)
f.close()
cur.close()
def write_file_to_table(file, table, connection):
f = open(file,"r")
cur = connection.cursor()
cur.execute("SET CLIENT_ENCODING TO 'LATIN1';")
cur.execute("SHOW client_encoding;")
print cur.fetchone()
cur.copy_from(f, table)
#cur.copy_expert("COPY cms_jobdef FROM STDOUT WITH BINARY", f)
f.close()
cur.close()
def main():
login = open('login.txt','r')
con_tctmsv64 = connect_db("x", "y",
login.readline().strip(),
"ctmtest1.int.corp.sun", "5436")
con_S104838 = connect_db("x", "y", "z", "t", "5432")
try:
write_table_to_file("cms_jobdef.txt", "cms_jobdef", con_tctmsv64)
write_file_to_table("cms_jobdef.txt", "cms_jobdef", con_S104838)
finally:
con_tctmsv64.close()
con_S104838.close()
if __name__ == "__main__":
sys.exit(main())
wyjście
In [4]: %run datamain.py
('sql_ascii',)
('LATIN1',)
In [5]:
ta zakończy się pomyślnie, ale kiedy uruchomić
select * from cms_jobdef;
Nic nie jest w nowej bazie danych
Próbowałem nawet konwertować format pliku z LATIN1 na UTF8.Nadal nie ma szczęścia
Dziwne jest to, że robię to ręcznie, używając tylko funkcji postgre COPY, która działa. Nie mam pojęcia dlaczego. Po raz kolejny wszelka pomoc byłaby bardzo doceniana.
Cześć Phil, dziękuję za odpowiedź. Próbowałem również i nie odniosłem sukcesu. Kod zostanie pomyślnie wykonany, ale po uruchomieniu tabela pozostanie pusta. Zaktualizowałem moje oryginalne pytanie, aby odzwierciedlić to –
Nienawidzę pytać o to ... Czy zgadzasz się na transakcję? http://initd.org/psycopg/docs/connection.html mówi: "Domyślnie Psycopg otwiera transakcję przed wykonaniem pierwszego polecenia: jeśli funkcja commit() nie zostanie wywołana, efekt jakiejkolwiek manipulacji danymi zostanie utracony." –
Dzięki za opinie Phil, byłeś ogromną pomocą! –