我正在开发一个程序,我希望将从csv文件读取的地址与postgres数据库进行比较。 (它是QGis的插件) 只要我在没有自己的参数的情况下发送查询,我就可以成功建立连接并从数据库中读取数据。
所以我做的是: 我读了一个csv文件并将其存储在一个列表中。 然后我选择一个输出文件。 接下来,我单击一个按钮,单击该按钮,应将csv文件中的条目与数据库中的条目进行比较。 如果来自csv文件的条目(邮政编码,城镇,地址)在数据库中具有完全相同的属性,我将其写入“成功匹配”列表,如果一个不匹配,我将其写入列表“错误列表”
当我用自己的参数执行语句时,我的问题就出现了。 我收到的Sql错误消息说:
编码UTF8的字节序列无效:0xdf 0x65
我认为,错误发生在我从csv文件填充的第一个列表中。我的地址有特殊字符,如öäüß......
以下是使用的代码:
This Method writes the succesfully matched addresses to a file, the failed ones to a lineEdit
def write_output_file(self):
compare_input_with_database()
try:
with open(self.outputfile, 'wb') as csvfile:
writer = csv.writer(csvfile, delimiter=';', quoting=csv.QUOTE_MINIMAL)
for row in geocoded_list:
writer.writerow(row)
if len(error_list) > 0:
self.writefailedaddresses()
raiseInformation("Es konnten nicht alle Adressen geocodiert werden!")
else:
raiseInformation("Adressen erfolgreich geocodiert!")
except csv.Error:
raiseException("Fehler beim schreiben der Datei")
This method, compares a row entry from the list/csvfile to the database.
def compare_input_with_database():
dbcursor = database_connection.open_connection()
for row in addressList:
entry = str(row[0])
addresssplit = entry.split(';')
try:
resultset = database_connection.select_specific_address(dbcursor, int(addresssplit[0]), addresssplit[1], addresssplit[2])
geocoded_list.append(resultset)
except psycopg2.DatabaseError, e:
raiseException(e)
error_list.append(addresssplit)
database_connection.close_connection()
def select_specific_address(cursor, plz, town, address):
cursor.execute("SELECT plz,ort,strasse,breitengrad,laengengrad from addresses where plz=%s AND ort=%s AND strasse=%s", (plz, town, address))
resultset = cursor.fetchone()
return resultset
This Method reads a csv file and populates it in a list
def loadFileToList(addressfile, dlg):
del addressList[:]
if os.path.exists(addressfile):
if file_is_empty(addressfile):
raiseException("Ungueltige Quelldatei! Quelldatei ist leer!")
return -1
else:
with open(addressfile, 'rb') as csvfile:
filereader = csv.reader(csvfile, delimiter=';')
for row in filereader:
addressList.append(row)
return addressList
else:
raiseException("Pfad der Quelldatei nicht gefunden!")
return -1
谢谢!
编辑: 当我显示包含特殊字符的地址时,它显示为“Hauptstra \ xdfe”而不是“Hauptstraße” 抱歉,我很难接受编码,这是unicode吗? 这是否意味着,它会像这样发送到数据库,并且我需要以不同的方式对其进行编码?
编辑2: 我看了一眼orkaround并试图实现它:
def loadFileToList(addressfile, dlg):
del addressList[:]
if os.path.exists(addressfile):
if file_is_empty(addressfile):
raiseException("Ungueltige Quelldatei! Quelldatei ist leer!")
return -1
else:
#with open(addressfile, 'rb') as csvfile:
#filereader = csv.reader(csvfile, delimiter=';')
reader = unicode_csv_reader(open(addressfile))
for row in reader:
addressList.append(row)
return addressList
else:
raiseException("Pfad der Quelldatei nicht gefunden!")
return -1
def unicode_csv_reader(utf8_data, dialect=csv.excel, **kwargs):
csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs)
for row in csv_reader:
yield [unicode(cell, 'utf-8') for cell in row]
但现在我在执行代码时收到以下错误消息: 读者中的行:
文件“C:/Users/Constantin/.qgis2/python/plugins \ Geocoder \ logic.py”, 第46行,在unicode_csv_reader中 yield [行中单元格的unicode(cell,'utf-8')] UnicodeDecodeError:'utf8'编解码器无法解码位置19的字节0xdf:无效 继续字节
我只是不明白为什么它只是无法解码它-.-
更新:
我的csv文件中的一些行:
1190;Wien;Weinberggasse
1190;Wien;Hauptstraße
1190;Wien;Kärnterstraße
答案 0 :(得分:1)
except
的语法暗示您正在使用Python 2.但由于您在字符串中使用非ASCII(Unicode)字符,因此Python 3是一个明显更好的选择。你似乎在用德语工作,所以至少有一些ü和ß会潜入。
在Python 3中,阅读只是:
rows = []
with open('test.csv', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile, delimiter=';', quoting=csv.QUOTE_MINIMAL)
for row in reader:
rows.append(row)
写作:
with open('testout.csv', mode="w", encoding='utf-8') as csvfile:
writer = csv.writer(csvfile, delimiter=';', quoting=csv.QUOTE_MINIMAL)
for row in rows:
writer.writerow(row)
请注意,读/写不是二进制,并且编码是理所当然的。结果正是您所期望的。类似的东西:
Artikelname;Menge
Äpfel;3
Bäume;12
正确编码所有字符。在磁盘上,数据是UTF-8编码的。在内存中,完整的Unicode。
如果你不能使用Python 3,那么你必须非常谨慎地对Unicode字符进行正确编码和解码,特别是在I / O边界 - 例如。读取和写入数据,或与PostgreSQL等外部系统通信时。现有代码至少有几种方法可以不用处理。例如,使用str()
来转换不一定是ASCII字符的内容,以及缺少UTF-8编码。
不幸的是,Python 2中没有简单的修复.Python 2的CSV模块是 schrecklich kaput 。来自the docs:“csv模块不直接支持读写Unicode。” 2016年?!但是,有一些解决方法。其中一个食谱就在文档中。 This Stack Overflow answer重申它,并提供其他几种选择。
所以,如果可以,请使用Python 3。它将简化此问题和许多其他非ASCII I / O问题。否则,在其他SO答案中部署其中一个CSV解决方法。
<强>更新强>
如果您在使用变通方法时遇到问题,我也不喜欢标准答案。这是一个适合我的非规范读者解决方案:
import csv
rows = []
with open('test.csv', mode='rb') as csvfile:
reader = csv.reader(csvfile, delimiter=';', quoting=csv.QUOTE_MINIMAL)
for row in reader:
urow = [unicode(cell, 'utf-8') for cell in row]
rows.append(urow)
print rows
这对Python 3来说绝对是不可移植的,但它可以工作,不需要导入任何其他模块。请注意,如果您使用的是IPython / Jupyter或交互式Python控制台(“REPL”),您将看到较低级别的字符串,例如:
[ [u'Artikelname', u'Menge'],
[u'\xc4pfel', u'3'],
[u'B\xe4ume', u'12]
]
因此,字符串有\xc4
,而不是一个漂亮,整洁的Ä。这很烦人,但没错。输入u'\u00c4pfel'
可以为您提供相同的功能。并且很容易确认c4
是the correct Unicode code point。 Python 2在处理非ASCII字符方面做得很差。只有4,094个理由才能使用Python 3。
输出的手册等价物,顺便说一下:
with open('testout.csv', mode='wb') as csvfile:
writer = csv.writer(csvfile, delimiter=';', quoting=csv.QUOTE_MINIMAL)
for row in rows:
urow = [cell.encode('utf-8') for cell in row]
writer.writerow(urow)
所有这些完全取决于您的输入文件真正采用UTF-8编码。如果它们处于其他任何地方,那就会打开另一个可怕的腐烂水壶。