Что печатает Python (), функция на самом деле делает?

Я смотрел на этот вопрос и начал задаваться вопросом, что делает print на самом деле сделайте.

Я никогда не узнавал, как использовать string.decode() и string.encode() для вывода строки unicode в Python интерактивная оболочка в том же формате как, печать делает. Независимо от того, что я делаю, я добираюсь также

  1. UnicodeEncodeError или
  2. завершенная строка с "\x##" нотацией...

Это - Python 2.x, но я уже пытаюсь исправить свои пути и на самом деле звонить print() :)

Пример:

>>> import sys
>>> a = '\xAA\xBB\xCC'
>>> print(a)
ª»Ì
>>> a.encode(sys.stdout.encoding)
Traceback (most recent call last):
  File "", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xaa in position 0: ordinal not in range(128)
>>> a.decode(sys.stdout.encoding)
u'\xaa\xbb\xcc'

Править:

Почему я спрашиваю это? Я являюсь больным и усталым от encode() ошибки и реализованный это с тех пор print может сделать это (по крайней мере, в интерактивной оболочке). Я знаю, что ДОЛЖЕН ЯВЛЯЕТСЯ СПОСОБОМ волшебно сделать кодирование ПРАВИЛЬНО путем рытья информации что, кодируя для использования от где-нибудь...

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: я запускаю Python 2.4.3 (#1, 3 сентября 2009, 15:37:12) [GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] на linux2

>>> sys.stdin.encoding
'ISO-8859-1'
>>> sys.stdout.encoding
'ISO-8859-1'

Однако результатами является то же с Python 2.6.2 (r262:71600, 8 сентября 2009, 13:06:43) на том же поле Linux.

9
задан Community 23 May 2017 в 10:29
поделиться

4 ответа

EDIT: (Основные изменения между этим редактированием и предыдущим... Примечание: Я использую Python 2.6.4 на коробке Ubuntu.)

Во-первых, в моей первой попытке ответить, я предоставил некоторую общую информацию о печати и str, которые я собираюсь оставить ниже, в пользу любого, у кого есть более простые вопросы с печати и направляя на этот вопрос. Что касается новой попытки решить проблему, с которой столкнулась ОП... В принципе, я склонен сказать, что здесь нет серебряной пули, и если печатает каким-то образом умудряется придать смысл странному струнному буквальному, то это не воспроизводимое поведение. К такому выводу меня приводит следующее забавное взаимодействие с Python в окне моего терминала:

>>> print '\xaa\xbb\xcc'
��

Пытались ли вы ввести ª "М прямо из терминала? В терминале Linux, использующем в качестве кодировки utf-8, это на самом деле считывается как шесть байт, которые затем можно сделать похожими на три символа юникода с помощью метода decode:

>>> 'ª»Ì'
'\xc2\xaa\xc2\xbb\xc3\x8c'
>>> 'ª»Ì'.decode(sys.stdin.encoding)
u'\xaa\xbb\xcc'

Итак, литерал '\xaa\xbb\xcc' имеет смысл только в том случае, если вы декодируете его как литерал latin-1 (ну, на самом деле, вы могли бы использовать другую кодировку, которая бы согласовывалась с латинским-1 на соответствующих символах). Что касается распечатки "просто работает" в вашем случае, то это определенно не для меня -- как уже упоминалось выше.

Это объясняется тем, что когда вы используете строковый литерал без префикса с u -- т.е. "asdf", а не u "asdf" -- результирующая строка будет использовать некоторую некодированную кодировку. Нет; на самом деле, сам строковый объект будет в кодировке - не в кодировке, и вам придется относиться к нему так, как будто он был закодирован в кодировке x, для правильного значения x. Эта основная идея приводит меня к следующему:

a = '\xAA\xBB\xCC'
a.decode('latin1')
# result: u'\xAA\xBB\xCC'
print(a.decode('latin1'))
# output: ª»Ì

Обратите внимание на отсутствие ошибок декодирования и правильный вывод (который, как я ожидаю, останется правильным на любом другом ящике). Видимо, ваш строковый литерал может быть понятен Python, но не без некоторой помощи.

Помогает ли это? (По крайней мере, в понимании того, как все работает, если не в облегчении работы с кодировками...)


Теперь для некоторых забавных битов с каким-то поясняющим значением (надеюсь)! Для меня это отлично работает:

sys.stdout.write("\xAA\xBB\xCC".decode('latin1').encode(sys.stdout.encoding))

Пропуск либо декодирования, либо части кодирования приводит к исключению, связанному с юникодом. Теоретически, это имеет смысл, так как первый дешифровочный код необходим, чтобы решить, какие символы в данной строке есть (единственное, что очевидно на первый взгляд, это то, что байты есть -- идея Python 3 иметь (уникодовые) строки для символов и байты для, ну, байтов, внезапно кажется очень разумной), в то время как кодирование необходимо для того, чтобы вывод уважал кодировку выходного потока. Теперь это

sys.stdout.write("ąöî\n".decode(sys.stdin.encoding).encode(sys.stdout.encoding))

также работает, как и ожидалось, но символы на самом деле идут с клавиатуры и поэтому на самом деле закодированы в кодировке stdin... Также

ord('ą'.decode('utf-8').encode('latin2'))

возвращает правильную 177 (моя входная кодировка utf-8), но '\xc4\x85'.encode('latin2') не имеет смысла для Python, так как он понятия не имеет, как понять '\xc4\x85' и цифры, что пробовать 'ascii' код - это лучшее, что он может сделать.


Первоначальный ответ:

Соответствующий бит Python docs (для версии 2.6.4) говорит, что print(obj) предназначен для распечатки строки, заданной str(obj). Я полагаю, что вы могли бы затем обернуть это в обращение к unicode (как в unicode(str(obj))), чтобы получить строку из unicode -- или вы могли бы просто использовать Python 3 и обменять эту конкретную неприятность на пару разных. ;-)

Кстати, это показывает, что вы можете манипулировать результатом распечатки объекта так же, как вы можете манипулировать результатом вызова str на объекте, т.е. путем манипулирования методом __str__. Пример:

class Foo(object):
    def __str__(self):
        return "I'm a Foo!"

print Foo()

Что касается фактической реализации print, то я ожидаю, что это будет совсем не полезно, но если вы действительно захотите узнать, что происходит.... Это находится в файле Python/bltinmodule.c в исходниках Python (я смотрю на версию 2.6.4). Ищите строку, начинающуюся с builtin_print. На самом деле это совершенно просто, никакой магии там не происходит. :-)

Надеюсь, это ответ на ваш вопрос... Но если у вас есть более загадочная проблема, которую я полностью пропустил, сделайте комментарий, я сделаю вторую попытку. Также, я предполагаю, что мы имеем дело с Python 2.x; в противном случае, я думаю, что у меня не было бы полезного комментария.

9
ответ дан 4 December 2019 в 13:02
поделиться

print() использует sys.stdout.encoding, чтобы определить, что выходная консоль может понять, а затем использует эту кодировку в вызове str.encode().

.

[EDIT] Если вы посмотрите на источник , он получает sys.stdout и затем звонит:

PyFile_WriteObject(PyTuple_GetItem(args, i), file,
                 Py_PRINT_RAW);

Я думаю, что магия находится в Py_PRINT_RAW , но источник просто говорит:

    if (flags & Py_PRINT_RAW) {
    value = PyObject_Str(v);
    }

Так что никакой магии здесь нет. Цикл по аргументам с sys.stdout.write(str(item)) должен выполнить этот трюк.

.
5
ответ дан 4 December 2019 в 13:02
поделиться
import sys

source_file_encoding = 'latin-1' # if there is no -*- coding: ... -*- line

a = '\xaa\xbb\xcc' # raw bytes that represent string in source_file_encoding

# print bytes, my terminal tries to interpret it as 'utf-8'
sys.stdout.write(a+'\n') 
# -> ��

ua = a.decode(source_file_encoding)
sys.stdout.write(ua.encode(sys.stdout.encoding)+'\n')
# -> ª»Ì

См. Определение исходного кода питона

0
ответ дан 4 December 2019 в 13:02
поделиться
[
>>> import sys
>>> a = '\xAA\xBB\xCC'
>>> print(a)
ª»Ì
] [

] Все, что [] распечатка [] делает здесь, это записывает необработанные [] байты [] в [] sys.stdout []. Строка []a[] представляет собой строку из байтов, а не символов Юникода.[

]. [
] [

] Почему я спрашиваю об этом? Я устал от ошибок encode() и понял, что так как print может это делать (по крайней мере, в интерактивной оболочке). Я знаю, что ДОЛЖЕН МОЖНО ПОЛУЧАТЬ магически сделать кодировку ПРЕДЛОЖИТЕЛЬНО, выкопав откуда-то информацию о том, какую кодировку использовать...[

]. [
] [

] Увы, нет, [] печать [] здесь совсем ничего не волшебного. Вы даете ему несколько байтов, а он сбрасывает байты в stdout. [

] [

] Чтобы правильно использовать [].encode()[] и [].decode()[], вы должны понимать разницу между байтами и символами, и я боюсь, что вам все-таки придется вычислить правильную кодировку, чтобы использовать ее.[

].
2
ответ дан 4 December 2019 в 13:02
поделиться
Другие вопросы по тегам:

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