Python, UnicodeDecodeError

Используя Java, с помощью Apache палата общин Строка Utils:

public boolean isPalindrome(String phrase) {
  phrase = phrase.toLowerCase().replaceAll("[^a-z]", "");
  return StringUtils.reverse(phrase).equals(phrase);
}

7
задан Mu Mind 25 September 2012 в 04:00
поделиться

7 ответов

Старый вопрос, но интересное обсуждение. Концепции ISAM важны, дополнительные функции, которые мы предоставляем в сегодняшних СУБД (как обсуждалось, например, резервное копирование, согласованность, безопасность, метаданные), предлагают нам значительные преимущества.

С увлечением NoSQL (да, да) Я сказал это ... безумие) это не означает, что мы не можем моделировать доступ, подобный ISAM, внутри СУБД. Вы будете уверены, что я перенесу в БД столько логики, сколько смогу, но бывают случаи, такие как "традиционная" сетка данных / многомерная интерполяция данных, когда я просматриваю все необходимые записи с помощью моей собственной логической схемы. index.

f)

Это действительно то, что вы хотели? Предложение: постройте путь ОДИН РАЗ, используя лучший метод (см. Пункт (2) ниже).

(1) Как правило, используйте repr (foo) или "% r"% foo для диагностики. Таким образом, ваш диагностический код с гораздо меньшей вероятностью вызовет исключение (как здесь происходит) И вы избежите двусмысленности. Вставьте оператор print repr (folder), repr (f) , прежде чем пытаться получить размер, выполнить повторный запуск и отправить отчет.

(2) Не прокладывайте пути по u " % s /% s "% (папка, имя файла) ... используйте os.path.join (папка, имя файла)

(3) Не используйте простые исключения, проверьте известные проблемы. Чтобы неизвестные проблемы не остались неизвестными, сделайте что-нибудь вроде этого:

try:
    some_code()
except ReasonForBaleOutError:
    continue
except: 
    # something's gone wrong, so get diagnostic info
    print repr(interesting_datum_1), repr(interesting_datum_2)
    # ... and get traceback and error message
    raise

Более сложный способ будет включать в себя ведение журнала вместо печати, но вышеизложенное намного лучше, чем не знать, что происходит.

Дальнейшие правки после rtm ("os.walk"), запоминание старых легенд и повторное чтение вашего кода:

(4) os. walk () обходит все дерево; вам не нужно вызывать его рекурсивно.

(5) Если вы передаете строку unicode в os.walk (), результаты (пути, имена файлов) сообщаются как unicode. Тебе не нужна вся эта чепуха. Затем вам просто нужно выбрать способ отображения результатов Unicode.

(6) Удаление путей с «$» в них: вы должны изменить список на месте, но ваш метод опасен. Попробуйте что-то вроде этого:

for i in xrange(len(folders), -1, -1):
    if '$' in folders[i]:
        del folders[i]

(7) Вы можете ссылаться на файлы, объединив имя папки и имя файла. Вы используете ОРИГИНАЛЬНОЕ имя папки; когда вы вырываете рекурсию, это не сработает; ты' Вам нужно будет использовать текущее отброшенное значение content [0] , сообщенное os.walk.

(8) Вы должны использовать что-то очень простое, например:

for folder, subfolders, filenames in os.walk(unicoded_top_folder):

Нет необходимости в ] генератор = os.walk (...); попробуйте: content = generator.next () и т. д. и, кстати, если вам когда-нибудь понадобится выполнить generator.next () в будущем, используйте except StopIteration вместо простого .

(9) Если вызывающий объект предоставляет несуществующую папку, исключение не возникает, он просто ничего не делает. Если предоставленная папка существует, но пуста, то же самое. Если вам нужно различать эти два сценария, вам необходимо провести дополнительное тестирование.

Ответ на этот комментарий от OP: "" "Спасибо, пожалуйста, прочтите информацию, которую repr () показал в первый пост. я не Не знаю, почему напечатано так много разных элементов, но похоже, что у всех есть проблемы. И общее между ними - это файлы .ink. Может в этом проблема? Кроме того, в последних файлах firefox он печатает (Modalitrovvisoria), в то время как настоящее имя файла из Explorer содержит (Modalità provvisoria) "" "

(10) Ммм, это не" .INK ".lower (), это ".LNK" .lower () ... возможно, вам нужно изменить шрифт в том, с чем вы это читаете.

(11) Тот факт, что все имена "проблемных" файлов заканчиваются на ".lnk" / может / быть связано с тем, что os.walk () и / или Windows делают что-то особенное с именами этих файлов.

(12) Я повторяю здесь оператор Python, который вы использовали для создания этого вывода, с добавлением некоторых пробелов :

print repr(
    "Error reading file %s" \
    % u"%s/%s" % (
        folder.decode('utf-8','ignore'),
        f.decode('utf-8','ignore')
        )
    )

Похоже, вы не прочитали, не поняли или просто проигнорировали совет, который я дал вам в комментарии к другому ответу (и ответу этого ответчика): UTF-8 НЕ имеет отношения к контексту имена файлов в файловой системе Windows.

Нас интересует, к какой именно папке и f относятся. Вы растоптали все свидетельства, пытаясь расшифровать их с помощью UTF-8. Вы усугубили обфускацию, используя опцию «игнорировать». Если бы вы использовали опцию «заменить», вы бы увидели «(Modalit \ ufffdrovvisoria)». Опция "игнорировать" не имеет места в отладке.

В любом случае подозрительным является тот факт, что в некоторых именах файлов была какая-то ошибка, но они НЕ теряли символы с опцией "игнорировать" (или не искажались).

Какая часть " "" как и ожидалось

>>> 'Ha\x9aek'.decode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\python26\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x9a in position 2: unexpected code byte

ЛЮБАЯ случайная строка байтов может быть декодирована без ошибок с помощью latin1

>>> 'Ha\x9aek'.decode('latin1')
u'Ha\x9aek'

НО U + 009A - это управляющий символ (SINGLE CHARACTER INTRODUCER), то есть бессмысленная тарабарщина; абсолютно ничего общего с правильным ответом

>>> unicodedata.name(u'\u0161')
'LATIN SMALL LETTER S WITH CARON'
>>>

(16) Этот пример показывает, что происходит, когда символ представляется в наборе символов по умолчанию; что будет, если это не так? Вот пример (на этот раз с использованием IDLE) имени файла, содержащего идеограммы CJK, которые определенно не могут быть представлены в моем наборе символов по умолчанию:

IDLE 2.6.4      
>>> import os
>>> from pprint import pprint as pp

repr (результаты Unicode) выглядит нормально

>>> pp(list(os.walk(ur"c:\junk\terabytest\chinese")))
[(u'c:\\junk\\terabytest\\chinese', [], [u'nihao\u4f60\u597d.txt'])]

, а Unicode отлично отображается в IDLE :

>>> print list(os.walk(ur"c:\junk\terabytest\chinese"))[0][2][0]
nihao你好.txt

Результат str, очевидно, получается с использованием .encode (что угодно, "заменить") - не очень полезно, например, вы не можете открыть файл, передав его в качестве имени файла.

>>> pp(list(os.walk(r"c:\junk\terabytest\chinese")))
[('c:\\junk\\terabytest\\chinese', [], ['nihao??.txt'])]

Итак, вывод таков: для лучших результатов,

15
ответ дан 6 December 2019 в 07:06
поделиться

Вы запускаете эту программу в Windows cmd.exe? Если это так, попробуйте запустить его в IDLE и посмотрите, возникнут ли те же ошибки. Коробка Cmd.exe не поддерживает Unicode, только ascii.

1
ответ дан 6 December 2019 в 07:06
поделиться

Вы пытаетесь выполнить какое-либо действие (например, печать) над строкой Unicode, содержащей символы, отличные от ASCII. , и по умолчанию строка преобразуется в ascii. Для правильного представления строки потребуется указать кодировку.
Если вы разместите образец кода того, что вы пытаетесь сделать, это значительно поможет.

Самый простой способ сделать это:
s = u'ma \ xf1ana ';
print s.encode ('latin-1');

Отредактировано после добавления деталей к вопросу:

В вашем случае вам необходимо декодировать строку, которую вы прочитали первой:
f.decode (); ,
поэтому попробуйте изменить
u "% s /% s"% (folder, f)
на
os.path.join (folder, f.decode ())

Обратите внимание, что 'latin- 1 'может потребоваться изменить на то, что ваш файл назван

PS: Джон Мачин упомянул очень полезные способы улучшения и очистки кода. +1

2
ответ дан 6 December 2019 в 07:06
поделиться

Некоторые элементы Unicode:

  • размещение # encoding: utf-8 в верхней части файла иногда помогает (если ваш редактор использует UTF-8 для сохранения файла ...)
  • s = "я строка"
  • u = u "я юникод, по крайней мере, в python <۳"
  • Если вы работаете с файлами, попробуйте заглянуть в кодеков модуль.

Дополнительные материалы для чтения:

1
ответ дан 6 December 2019 в 07:06
поделиться
u"%s" % f

В разных местах вы делаете что-то похожее на приведенный выше код. Это совершенно неправильный способ преобразования объекта str в объект Unicode, поскольку преобразование выполняется с помощью sys.getdefaultencoding () (ascii), что почти гарантированно неверно.

Вы должны использовать методы кодирования / декодирования для преобразования в / из объекта Unicode. Это требует знания кодировки вашего ввода (строк, возвращаемых os.walk). Например, если имена файлов закодированы в UTF-8,

uf = f.decode('utf-8')

интерпретирует f как последовательность байтов в кодировке UTF-8 и вернет правильный объект Unicode. Точно так же, когда вам нужно вывести объект Unicode, вы должны затем преобразовать его обратно в str, указав действительную кодировку, в которой вы хотите вывести его как.

print uf.encode('utf-8')
1
ответ дан 6 December 2019 в 07:06
поделиться

вместо выполнения:

print "Error reading file %s"%u"%s/%s"%(folder, f)

Попробуйте следующее:

print "Error reading file %s"%u"%s/%s"%(folder.encode('ascii','ignore'), f.encode('ascii','ignore'))

Поскольку консоль не может печатать символы Unicode, вы можете увидеть правильное имя. 'ignore' указывает кодеку пропустить эти символы. вы также можете использовать 'replace' (печатает '?'), 'xmlcharrefreplace' (заменяет на & x #### кодовой точки), 'backslashreplace' (заменяет на \ x ###### кода)

Вам нужно будет кодировать каждую напечатанную строку Unicode, подобную этой.

-1
ответ дан 6 December 2019 в 07:06
поделиться

Я имел несчастье работать с некоторыми кодовыми базами, которые не соответствовали их кодировке.

Это функция, которую мы использовали, чтобы очистить ее:

def to_unicode(value):
    if isinstance(value, unicode):
        return value
    elif isinstance(value, str):
        try:
            if value.startswith('\xff\xfe'):
                return value.decode('utf-16-le')
            elif value.startswith('\xfe\xff'):
                return value.decode('utf-16-be')
            else:
                return value.decode('utf-8')
        except UnicodeDecodeError:
            return value.decode('latin-1')
    else:
        try:
            return unicode(value)
        except UnicodeError:
            return to_unicode(str(value))
        except TypeError:
            if hasattr(value, '__unicode__'):
                return value.__unicode__()

Итак, используя эту функцию вы можете использовать:

print u"Error reading file %s/%s" % (to_unicode(folder), to_unicode(f))
0
ответ дан 6 December 2019 в 07:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: