Регистрация нулевых байтов через apache

1

Существует проблема с записью двоичных данных в stdout через Apache.

После настройки ведения журнала я пытаюсь записать строку '\x31\x00':

logging.getLogger().info('\x31\x00')

Все идет хорошо, если я использую консоль python - я ожидаю:

2011-05-01 22:21:27,430 INFO [test_logging:9][test_logging] 1

Но если я использую ведение журнала через Apache и mod_wsgi, я получаю трассировку:

Traceback (most recent call last):   
    File "/usr/local/lib/python2.6/logging/__init__.py", line 789, in emit
        stream.write(fs % msg) TypeError: write() argument 1 must be string without null bytes, not str

Где ошибка? Где я должен копаться?

Моя конфигурация регистрации:

[loggers]
keys=root

[formatters]
keys=stdoutFormatter

[handlers]
keys=stdoutHandler

[logger_root]
level=NOTSET
handlers=stdoutHandler

[handler_stdoutHandler]
class=StreamHandler
formatter=stdoutFormatter
args=(sys.stdout,)

[formatter_stdoutFormatter]
format=%(asctime)s %(levelname)s [%(module)s:%(lineno)d][%(funcName)s] %(message)s

Версия Apache 2.2.16

Python version 2.6.4

Mod_wsgi 2.8

Теги:
logging

3 ответа

1

Вы можете просто использовать

logging.getLogger().info('%r', binary_bytes)

и он должен поступать правильно.

В Apache/mod_wsgi ничего не происходит - это просто, что выходные потоки консоли не должны использоваться для двоичных данных.

  • 0
    Маловероятно, я не могу использовать это, так как я собираюсь регистрировать не только двоичные файлы.
0

Вы предоставили байтовую строку, когда ожидается строка символов (Unicode). Помните, что в Python 2.x тип "string" действительно байтовая строка, а не строка символов. (Это следует за C, где тип "char" действительно является байтом, а "A" - действительно 0x41.) Если вы используете либо синтаксис u'string, либо unicode(), встроенный непосредственно перед протоколированием, это будет убедитесь, что записаны только строки символов. В этом случае байтовые строки, которые не могут быть декодированы в символьные строки с использованием ASCII-кодирования перед протоколированием, получат вам исключение в этой точке, а не из-за вызовов Apache.

Чтобы на самом деле записывать байтовые строки, которые, как вам кажется, вы хотите сделать, вам сначала нужно каким-то образом закодировать их в (Unicode) символьные строки. base64 прост в использовании, но данные нужно будет снова декодировать, чтобы быть удобочитаемым для человека. Я написал функцию hex-dump, которая заняла у меня несколько часов, чтобы получить то, что я хотел.

0

Ошибка указана прямо здесь: stream.write не может принимать строковый аргумент, содержащий нулевые байты.

Возможно, вам следует написать функцию, которая преобразует строку, которая может содержать нулевые байты (или другие непечатаемые символы) и заменять их на управляемые escape-последовательности. Таким образом, передача в строке типа '\x31\x00' приведет к печати строки '1\\x00'.

Или, если строка your're logging - это все двоичные данные, просто преобразуйте каждый символ в его эквивалентный код \xDD. Или просто распечатайте каждый символ в строке в виде простого двухзначного шестнадцатеричного кода, поэтому строка entore записывается как последовательность шестнадцатеричных кодов.

  • 0
    Я в порядке с поведением консоли Python, вопрос - что не так с Apache?
  • 0
    Ничто не является «неправильным» в Apache, просто то, что он написан на C / C ++, следует соглашению, согласно которому строки представляются внутренне как последовательности байтов, по одному для каждого символа, заканчивающегося NUL ASCII (\ x00). Это стандартный способ представления простых строк в большинстве языков и является артефактом (я считаю) того, как первые компиляторы Си изначально обрабатывали строки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню