Как стать автором
Обновить

Комментарии 35

это:
logging.getLogger().addHandler(setupcon.ColoredLogger())
вот так:
logging.getLogger().addHandler(setupcon.ColoredHandler())
?
Разумеется :)
Ох уж мне этот автопилот… Поправил, благодарю
Ох. С этим в питоне всегда столько секса. Помню в QT мучался. Там был какой то хак, не знаю что он такого делал, но после этого все работало
reload(sys)
sys.setdefaultencoding('utf-8')
Только что заметил, что в топике как раз описан этот способ :)
Когда же начнется переход на Py3…
Для windows чудеса с cp866 в консоли и cp1251 во всех остальных местах остаются.
Py3k уменьшает проблемы со строками — но от знаний основ работы с кодировоками не избавляет.
Для логов есть полустандартный велосипед pypi.python.org/pypi/logutils/
Раскрашивает консоль, помимо всего прочего.

Использовать reload(sys) и sys.setdefaultencoding(...) — дурной тон.
Одно то, что site убирает эту функцию из модуля — должно непрозрачно намекать, что разработчики языка хотели максимально ограничить использование setdefaultencoding. Не стоит гладить кошку против шерсти.
Ну, да, получил тот же велосипед, «но свой» :) Как оправдание — мой таки одноколёсный и в абстрактном сферическом линуксе не тянет за собой ничего стороннего. По большому счёту статья — заметка на память, дабы каждый раз не искать «и как же оно там делалось-то».

Про reload — согласен, а толку… Если то же Qt норовил (боролся в pyQt 4.6.что-то, дальше не знаю) воспользоваться именно sys.getdefaultencoding() и корёжить всякий ввод/вывод. Можно сделать reload опцией, например…
Нет версии для Win64.
В смысле — нет?
Там же чистый питоновский код и пара вызовов ctypes, которые работают одинаково что на win32 что на win64.
Не так?
Всё так. Я про установщик. Конечно, можно распотрошить tar.gz и взять в свой проект. Немного некрасиво, но работает.
Не нужно потрошить — следует делать python setup.py install
Удивительно встретить на просторах Хабра статью о скрипте для самиздата — тоже ваял его для себя, правда, в итоге добавил Qt-шный интерфейс и выложил.
Чем СИшные страницы парсите?
Начинал с BeautifulSoap. Тормоз и глюкало :(

В работающей версии — re+lxml+неработающий гуй на Qt (фактически иконка в трее и окно настроек частоты проверки), тем более что lxml даёт более подходящий мне diff на html-e. Какая-то версия этого дела даже лежит в гуглокоде. Там, кажись только re и htmldiff+ElementTree на генерацию diff-ов и нговостей (http://code.google.com/p/py-samizdat/)

В неспешно пишущейся сейчас — ручной разбор строк, re, HTMLParser. Во что выльется дальше — пока не ясно…

ЗЫ: я те только качаю новости, но и выкачиваю тексты чтоб не потерять, если автор убирает произведение…
Есть очень простое решение — не писать на питоне.
Есть и еще более простое — не писать. Тогда эффект «кривых рук» никак не проявится.
К тому, что виндоус — говно (во многих местах), питон отношения не имеет. Если бы его создатели думали мозгом больше, то проблем было бы меньше. Консольное окошко — это просто изделие века. Миксовать 3 разных кодировки по системе — это супер.
таки logging всёравно же будет вызывать __repr__ или __str__ для конвертирования объектов в строку.
ваши махинации с консолью спасут от необходисомти везде лепить
__repr__ = lambda self: unicode(self).encode("utf-8")?
тоесть даже unicode(self).encode(get_whatever_console_encoding()) для кросплатформизма.
Ничего не понял. Для каких-таких объектов будет вызываться __str__ или __repr__?
например, для
logging.debug(«foo=%s»,MyClass(u«блабла»))
logging.debug(«foo=%s»,{'foo': MyClass(u«блабла»)})
logging.debug(«foo=%s»,ForeignClass(MyClass(u«блабла»)))
насколько я понимаю, в первом случае вызовется Foo.__str__ из logger
во втором — изнутри dict.__repr__ и там уже непонятно repr или str

в третьем случае может случиться вобще всё что угодно.
(такой случай происходит, например, при рисовании графа сделанного networx через graphviz)

Достаточно иметь
logging.debug(u'foo=%s', 'string')
Logging handler (или stream для StreamHandler, например) должен знать, как преобразовать юникод в байты для дальнейшего использования.

Преобразование объектов, выполняемое для форматирования строк — не забота системы логирования.
Тем не менее создание необходимых __unicode__ (если мы говорим о python 2.x) не считаю чем-то сложным или непонятным.
Я уж надеялся, что это полное решение проблемы Юникода в Python под Windows…
То есть я хочу сказать, что печатать Юникод в консоль Windows можно. И не ограничиваясь системной (или какой-то одной) восьмибитной кодировкой. Для этого есть соответствующие API. А Python использует stdout, который идёт из стандартной библитеки Си, которая все эти приколы Windows не знает.
Python использует GetStdHandle(STD_OUTPUT_HANDLE) в качестве stdout.
Это — обычный дескриптор. Работает с байтами (WriteFile и так далее).
Где там Unicode API?
stdout — это ведь не всегда консоль!
Python/sysmodule.c
PyObject *
_PySys_Init(void)
{
//...
sysin = PyFile_FromFile(stdin, "", "r", NULL);
sysout = PyFile_FromFile(stdout, "", "w", _check_and_flush);
syserr = PyFile_FromFile(stderr, "", "w", _check_and_flush);
//...
}

А вы что нашли?

Эти функции корректно работают с Юникодом. Кодовая страница не имеет никакого значения (хотя на терминале охвата шрифтов не хватит для всего Юникода). Попробуйте, скажем:
import ctypes
ctypes.windll.msvcrt._putwch(1093)


Ну хорошо, это файл. Только к чему вы это сказали? Проверить, что это на самом деле, во время выполнения - не так сложно.
Я попытался вспомнить, как создается stdout в CRT. А сверху — да. Файлы из стандартной библиотеки.

Теперь займемся предложенными функциями из console io.

Скрестить их и sys.stdout (который в питоне полноценный файл по определению) не совсем легко.
Насколько я помню, в последний раз это обсуждалось в python-dev прошедшими весной-летом — и ни к чему не пришли.
Получалось, что если запустили не в консоли — то stdout прикидывается файлом (pipe на самом деле, сейчас не важно). А если консоль — то уже не файл а console io. Со своими тараканами.

Выходило, что полной совместимости и прозрачности так не добиться. На Windows свои штучки, на Posix — свои.
И если уж не получается сделать так, чтобы один и тот же код работал везде одинаково — то не стоит предлагать полурабочее решение.

Если хочется работать с console io — следует делать import msvcrt, там все есть. Оборачивать их в file-like object (или io.TextIOBase для тройки) и подставлять в sys.stdout. Проблемы, способные выползти при subprocess.Popen(..., stdout=subprocess.PIPE), например — пусть разработчик решает сам. Или что там еще может произойти при вызове C Extension, которая печатает в CRT stdout.Если что-то поломается — пусть будут виноваты не внутренности Питона, а программист в явном виде.

Быть может когда-нибудь найдется разработчик, который починит всё-всё-всё. Пока такого нет, а возможные неоднозначности при решении «в лоб» — есть. И различных аспектов, неочевидных при беглом осмотре — очень много.

Еще раз повторюсь: тема консоли и юникода для Windows возникает регулярно. И спецы, съевшие на этом деле не один пуд соли, вываливали десятки специфических случаев в которых простое решение не работало. Я этим спецам верю.
А разве стандартная библиотека C, в свою очередь, не оборачивает тот самый Console IO?
Мы говорим о _putwch или fwrite?
О stdout или таки о console io?
Стандартная библиотека C, то бишь fwrite и компания, не есть самый низкий уровень. Она же построена поверх чего-то.
Было бы странно, если текст в консоль попадал принципиально иными путями. Мне кажется, это все равно в итоге сводится к Console IO.
_putch превращается в WriteConsoleW (возвращаясь к WriteConsoleA есть WriteConsoleW возвращает ERROR_CALL_NOT_IMPLEMENTED — кажется возможно только на Win9x).
fwrite — это WriteFile с буферизацией.

Довольно разные штуки. Т.е. если есть handle для stdout — с ним можно работать через file api или через console api (оба из kernel32). Они очень слабо пересекаются. Смешивать способы настоятельно не рекомендуется.
Почитал комментарии к багу на багтрекере Python, и понял, что ждать фикса в ближайшем времени бессмысленно. Ох, Windows.
Ааа. Знаменитый баг.
После него проникаешься могучей любовью к cmd.exe
При этом, что обидно, само по себе API вполне приличное, можно было бы работать. Именно cmd.exe создает массу проблем на пустом месте.
а cygwin использовать, не?
Насколько знаю, cygwin стоит не у каждого пользователя Windows. Большинство обходится без него — и они тоже хотят запускать программы, написанные на Питоне.
Ну так и питон мало у кого стоит. А если вы ПО распространяете, то можно сделать сборку cygwin + python.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории