在Python中正确读取Windows-1252(cp1252)文件的文本
好吧,正如标题所说,我遇到的问题是如何正确读取一个用windows-1252编码的文件,并把这些内容插入到SQLAlchemy-MySql的表中。
当前的系统设置:
我有一个Windows 7的虚拟机,里面运行着“Roger Access Control System”,这个系统会输出文件;
还有一个Ubuntu 12.04 LTS的虚拟机,和Windows系统共享一个文件夹,这样我就可以访问文件,使用的是“Python 2.7.3”。
现在说说具体的问题,我有一个“虚拟机共享文件夹”,里面有一个文件是通过Windows 7系统的Roger Access Control System生成的,文件名叫“PREvents.csv”,从名字上看,它是一个用“;”分隔的数据列表。
数据的示例格式:
2013-03-19;15:58:30;100;Jānis;Dumburs;1;Uznemums1;0;Ieeja;
2013-03-19;15:58:40;100;Jānis;Dumburs;1;Uznemums1;2;Izeja;
第4个字段是卡片持有者的名字,第5个是姓氏,第6个是持有者的分配组。
问题在于,上面提到的三个字段中的任何一个都可能包含拉脱维亚语特有的字符,比如在示例文件中,“Jānis”这个词就包含了字母“ā”,在unicode中是257。
我习惯这样打开文件:
try:
f = codecs.open(file, 'rb', 'cp1252')
except IOError:
f = codecs.open(file, 'wb', 'cp1252')
到目前为止,一切正常——文件可以打开,然后我开始遍历文件的每一行(这是一个持续运行的脚本,请原谅这个循环):
while True:
line = f.readline()
if not line:
# Pause loop for 1 second
time.sleep(1)
else:
# Split the line into list
date, timed, userid, firstname, lastname, groupid, groupname, typed, pointname, empty = line.split(';')
问题就出现在这里,如果我用print repr(firstname)
打印出来,它显示u'J\xe2nis'
,根据我的理解,这并不正确——`\xe2\并不能代表拉脱维亚字符“ā”。
在循环的后面,根据事件类型,我把变量分配给SQLAlchemy对象并进行插入/更新:
if typed == '0': # Entry type
event = Events(
period,
fullname,
userid,
groupname,
timestamp,
0,
0
)
session.add(event)
else: # Exit type
event = session.query(Events).filter(
Events.period == period,
Events.exit == 0,
Events.userid == userid
).first()
if event is not None:
event.exit = timestamp
event.spent = timestamp - event.entry
# Commit changes to database
session.commit()
在寻找答案的过程中,我发现了如何定义默认编码:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
但这对我没有任何帮助。
基本上,这一切导致我无法正确插入持有者的名字和姓氏,以及持有者的分配组名,如果它们包含任何拉脱维亚特有的字符,比如:
Instead of the character "ā" it inserts "â"
我还想补充一点,我无法更改“PREvents.csv”文件的编码,而“RACS”系统也不支持插入UTF-8或Unicode文件——如果你尝试这样做,系统会插入一些随机符号来替代拉脱维亚特有的字符。
如果需要其他信息,请告诉我,我很乐意提供 :)
任何帮助都将非常感激。
3 个回答
我觉得 u'J\xe2nis'
是对的,看看这个:
>>> print u'J\xe2nis'.encode('utf-8')
Jânis
你是在SQLAlchemy里遇到真正的错误,还是在你应用程序的输出中看到问题?
我之前也遇到过类似的问题,针对一些XML文件,我是通过用ANSI编码(Windows-1252)读取文件,然后再用UTF-8编码写入文件来解决的。
import os
import sys
path = os.path.dirname(__file__)
file_name = 'my_input_file.xml'
if __name__ == "__main__":
with open(os.path.join(path, './' + file_name), 'r', encoding='cp1252') as f1:
lines = f1.read()
f2 = open(os.path.join(path, './' + 'my_output_file.xml'), 'w', encoding='utf-8')
f2.write(lines)
f2.close()
CP1252这种编码方式无法表示字符ā;你的输入中包含了一个类似的字符â。repr
这个函数在Python 2.x中只是显示了一个unicode字符串的ASCII表示形式:
>>> print(repr(b'J\xe2nis'.decode('cp1252')))
u'J\xe2nis'
>>> print(b'J\xe2nis'.decode('cp1252'))
Jânis