2010-05-17 8 views
21

Можно ли читать stdin как двоичные данные в Python 2.6? Если да, то как?Чтение двоичных данных из stdin

Я вижу в Python 3.1 documentation, что это довольно просто, но возможности для этого в 2.6, похоже, не существуют.

Если методы, описанные в 3.1, недоступны, существует ли способ закрыть stdin и повторно открыть в двоичном режиме?

Update

Просто чтобы быть ясно, я использую «тип» в оболочке MS-DOS к трубе содержимое двоичного файла на мой питона код. Насколько я понимаю, это должно быть эквивалентом команды «cat» Unix. Но когда я проверяю это, я всегда получаю на один байт меньше ожидаемого размера файла.

Update # 2

Во-первых, спасибо за все ответы. Я медленно работаю над настоящим, полезным решением. В конце концов, я все еще пытаюсь создать автономный JAR-файл, который выполняет мой код Python, автоматически проходящий через все аргументы командной строки, не испорченные.

Причина, по которой я иду по маршруту Java/JAR/Jython, состоит в том, что одна из моих основных внешних библиотек доступна только как Java JAR. Но, к сожалению, я начал свою работу как Python. Возможно, было проще конвертировать мой код в Java некоторое время назад, но поскольку этот материал был все совместим, я решил, что попробую проехать через него и доказать, что это можно сделать.

В случае, если кто-то задавался вопросом, это также связано с вопросом, который я задал несколько дней назад.

Packaging and deploying a Jython program from Eclipse

Некоторые из этого вопроса был дан в этом question.

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

ответ

13

Используйте команду -u command line switch, чтобы заставить Python 2 обрабатывать stdin, stdout и stderr как двоичные небуферизованные потоки.

C:> type mydoc.txt | python.exe -u myscript.py 
+0

Я тестировал это с помощью «type» и, похоже, работает. То есть, если я опускаю флаг -u, я получаю меньше символов на строку. –

+0

Cool. Спасибо за тест. Итак, только потому, что вы мне так нравитесь, любая идея передать параметр -u через класс JarRunner.java, который используется для запуска Jython через исполняемый JAR-файл? Я знаю. Я никогда не делаю ничего легкого. – thebeav

+1

Согласно документам, настройка переменной окружения PYTHONUNBUFFERED будет иметь тот же эффект. Не уверен, что это помогает. –

-2
import sys 

data = sys.stdin.read(10) # Read 10 bytes from stdin 

Если вам нужно интерпретировать двоичные данные, используйте модуль struct.

+0

Если я затем вызвать sys.stdin.read() без параметров, он должен прочитайте все двоичные данные, которые были отправлены по каналам, правильно? Как правильно определить длину? len (data) возвращает неверное значение, если последний байт данных равен нулю. Как вы проверяете и исправляете эту ситуацию? – thebeav

+1

'len' подсчитывает \ x00 символов в строке. Python не имеет ничейных строк. 'len (" Hello \ x00 ") == 6' –

+0

Интересно, может быть, это может быть команда типа из оболочки MS-DOS, которая вызывает потерю финального байта? Думаю, мне придется протестировать эквивалент в Linux. Благодарю. – thebeav

9

Если вам все еще нужно это ... Этот простой тест я использовал для чтения двоичный файл, содержащий 0x1A символ в

между
import os, sys, msvcrt 

msvcrt.setmode (sys.stdin.fileno(), os.O_BINARY) 
s = sys.stdin.read() 
print len (s) 

Мои данные проверочный файл был:

0x23, 0x1A, 0x45 

Без установки режима stdin в двоичный режим этот тест печатает 1, как только он обрабатывает 0x1A как EOF. Конечно, он работает только с окнами, потому что зависит от модуля msvcrt.

+1

Но Windows - единственная система, в которой большинство людей столкнутся с проблемой, поэтому это должно быть приемлемым решением. –

+1

Это правильное решение для Python 2 для извлечения необработанных байтов из stdin в Windows. В Unix нет разницы между двоичным и нормальным режимами. См. Эту тему: http://code.activestate.com/lists/python-list/20426/ (повторное открытие stdin в режиме raw (двоичный)?) –

+0

Также см. Http://cygwin.com/cygwin-ug- сеть/с использованием-textbinary.html –

17

Из документов (см here):

The standard streams are in text mode by default. To write or read binary data to these, use the underlying binary buffer. For example, to write bytes to stdout, use sys.stdout.buffer.write(b'abc') .

Но, как и в принятом ответе, ссылаясь на питона с -u еще один вариант, который заставляет STDIN, STDOUT и STDERR быть полностью небуферизован. Подробнее см. Справочную страницу python (1).

Дополнительную информацию о буферизации текста можно найти на странице documentation on io и использовать sys.stdin.detach(), чтобы отключить буферизацию из Python.

+6

, что doc ведет к документам py3k, а не к тому, с чем OP хочет иметь дело. –

+1

Я пробовал '-u' с Python v3.2.5, но ничего полезного не делал. Но использование 'sys.stdout.buffer' работает очень хорошо, хотя на Python 2.7.8 такой функции нет. – ony

+0

Вопрос OP был о Python 2.6. – Yuval

13

Вот окончательный вариант для Linux/Windows Python 2/3 совместимого кода для чтения данных из стандартного ввода без коррупции:

import sys 

PY3K = sys.version_info >= (3, 0) 

if PY3K: 
    source = sys.stdin.buffer 
else: 
    # Python 2 on Windows opens sys.stdin in text mode, and 
    # binary data that read from it becomes corrupted on \r\n 
    if sys.platform == "win32": 
     # set sys.stdin to binary mode 
     import os, msvcrt 
     msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) 
    source = sys.stdin 

b = source.read() 
Смежные вопросы