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

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

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

Теперь к фактической проблеме: для входного файла у меня есть «общая папка VM», которая содержит файл, созданный в системе Windows 7 с помощью системы управления доступом Roger (подробнее о 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-е поле содержит имя владельца карты, 5-е поле содержит фамилию владельца, 6-е поле содержит назначенную группу владельцев.

Проблема возникает из-за того, что любое из 3 вышеупомянутых полей может содержать символы, характерные для латышского языка, в файле примера слово «Jānis» содержит букву «ā», которая в юникоде равна 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 - если вы попробуете в любом случае, система вставит случайные символы для Характерные для латышского языка символы.

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

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


person Krisjanis Zvaigzne    schedule 19.03.2013    source источник
comment
Латышский символ ā вообще отсутствует в CP1252. Вы не можете создать файл с кодировкой CP1252, содержащий этот символ. (Вместо этого у вас есть файл, закодированный в CP1257?)   -  person Wooble    schedule 19.03.2013
comment
При выполнении sudo file /media/sf_attendance/PREvents.csv я получаю /media/sf_attendance/PREvents.csv: ISO-8859 text, with CRLF line terminators   -  person Krisjanis Zvaigzne    schedule 19.03.2013
comment
ISO-8859 — это семейство кодировок; CP1252 подобен (но не идентичен) ISO-8859-1, который поддерживает только западноевропейские языки; CP1257 поддерживает балтийские языки.   -  person Wooble    schedule 19.03.2013


Ответы (3)


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

>>> print(repr(b'J\xe2nis'.decode('cp1252')))
u'J\xe2nis'
>>> print(b'J\xe2nis'.decode('cp1252'))
Jânis
person phihag    schedule 19.03.2013
comment
Итак, изменение строки открытия файла на f = codecs.open(file, 'rb', 'cp1257'), а затем print firstname показывает правильный ā, но теперь при выполнении session.commit() я получаю UnicodeEncodeError: 'latin-1' codec can't encode character u'\u0101' in position 1: ordinal not in range(256) - person Krisjanis Zvaigzne; 19.03.2013
comment
Возможно, вам потребуется установить utf-8 в качестве кодировки по умолчанию для базы данных (сеанса)? - person djc; 19.03.2013
comment
Да, теперь я решил проблему - нужно было добавить convert_unicode=True при создании движка в engine = create_engine(connection, convert_unicode=True) - person Krisjanis Zvaigzne; 19.03.2013

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

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

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

person djc    schedule 19.03.2013
comment
Если я попробую firstname = firstname.decode('cp1252'), а затем вставлю это в базу данных, я все равно получу символ â - person Krisjanis Zvaigzne; 19.03.2013

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