Правильное чтение текста из файла Windows-1252 (cp1252) в python - программирование
Подтвердить что ты не робот

Правильное чтение текста из файла Windows-1252 (cp1252) в python

так хорошо, поскольку заголовок подсказывает, что проблема заключается в правильном чтении ввода из файла с кодировкой Windows-1252 в python и вставке указанного ввода в таблицу SQLAlchemy-MySql.

Текущая настройка системы:
Windows 7 VM с "Roger Access Control System", которая выводит файл;
Ubuntu 12.04 LTS VM с общей папкой для системы Windows, поэтому я могу получить доступ к файлу с помощью "Python 2.7.3".

Теперь, к фактической проблеме, для входного файла у меня есть "общая папка VM", которая содержит файл, который genereate в системе Windows 7 через Roger Access Control System (roger.pl для более подробной информации), этот файл называется "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-е поле содержит имя владельца карты, а пятое содержит имя владельца, 6-е место содержит группу, назначенную владельцам.

Проблема возникает из-за того, что любое из трех вышеупомянутых полей может содержать символы, характерные для латышского языка, в файле примера слово "Янис" содержит букву "ā", которая в юникоде - 257.

Как я привык, я открываю файл как таковой:

try:
    f = codecs.open(file, 'rb', 'cp1252')
except IOError:
    f = codecs.open(file, 'wb', 'cp1252')

До сих пор все работает - он открывает файл и поэтому я перехожу к итерации по каждой строке файла (это непрерывный запуск script, так что простите за цикл):

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 - если вы пытаетесь в любом случае, система вставляет случайные символы для символов, характерных для Латвии.

Пожалуйста, позвольте мне сейчас, если вам нужна какая-либо другая информация, я с радостью предоставит ее:)

Любая помощь будет высоко оценена.

4b9b3361

Ответ 1

CP1252 не может представлять ā; ваш вход содержит аналогичный символ â. repr просто отображает ASCII-представление строки юникода в Python 2.x:

>>> print(repr(b'J\xe2nis'.decode('cp1252')))
u'J\xe2nis'
>>> print(b'J\xe2nis'.decode('cp1252'))
Jânis

Ответ 2

Я думаю, что u'J\xe2nis' правильный, см.:

>>> print u'J\xe2nis'.encode('utf-8')
Jânis

Получаете ли вы фактические ошибки из SQLAlchemy или в выводе вашего приложения?

Ответ 3

У меня была та же проблема с некоторыми файлами 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()