2010-05-17 25 views
21

¿Es posible leer stdin como datos binarios en Python 2.6? ¿Si es así, cómo?Lectura de datos binarios de stdin

veo en el Python 3.1 documentation que esto es bastante simple, pero las instalaciones para hacer esto en 2.6 no parecen estar allí.

Si los métodos descritos en 3.1 no están disponibles, ¿hay alguna manera de cerrar stdin y volver a abrir en modo binario?

actualización

Para que quede claro, yo estoy usando 'tipo' en un shell de MS-DOS a la tubería el contenido de un archivo binario a código Python. Esto debería ser el equivalente de un comando Unix 'cat', por lo que yo entiendo. Pero cuando pruebo esto, siempre obtengo un byte menor que el tamaño de archivo esperado.

Actualización # 2

En primer lugar, gracias por todas las respuestas. Estoy trabajando lentamente hacia una solución real y útil aquí. Al final, sigo intentando construir un archivo JAR autónomo que ejecute mi código Python pasando automáticamente por todos los argumentos de la línea de comandos sin contaminar.

La razón por la que voy por la ruta Java/JAR/Jython es porque una de mis bibliotecas externas principales solo está disponible como Java JAR. Pero desafortunadamente, comencé mi trabajo como Python. Pudo haber sido más fácil convertir mi código a Java hace un tiempo, pero dado que se suponía que todo esto era compatible, pensé que intentaría probarlo y probar que se podía hacer.

En caso de que alguien se esté preguntando, esto también está relacionado con la pregunta que hice hace unos días.

Packaging and deploying a Jython program from Eclipse

Parte de esa pregunta fue respondida en este question.

Así que trataré de actualizar mi pregunta original con algunas notas sobre lo que he averiguado hasta ahora.

Respuesta

13

Utilice -u command line switch para obligar a Python 2 a tratar stdin, stdout y stderr como flujos binarios sin búfer.

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

He probado esto con 'tipo' y parece funcionar. Es decir, si dejo fuera el indicador -u, obtengo un carácter menos por línea. –

+0

Cool. Gracias por la prueba. Entonces, solo porque me gustas tanto, ¿alguna idea de cómo pasar la opción '-u' a través de la clase JarRunner.java que se usa para disparar a Jython a través de un archivo JAR ejecutable? Lo sé. Nunca hago nada de la manera fácil. – thebeav

+1

De acuerdo con los documentos, establecer la variable de entorno PYTHONUNBUFFERED tendrá el mismo efecto. No estoy seguro si eso ayuda. –

-2
import sys 

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

Si necesita interpretar datos binarios, use el módulo struct.

+0

si yo llamo sys.stdin.read() sin parámetros, lo que debería leer todos los datos binarios que fueron conectados, ¿correcto? ¿Cómo determino la longitud correctamente? len (data) devuelve el valor incorrecto si el último byte de los datos fue cero. ¿Cómo verifica y corrige esta situación? – thebeav

+1

'len' cuenta los caracteres \ x00 en la cadena. Python no tiene cadenas terminadas nulas. 'len (" Hello \ x00 ") == 6' –

+0

Me pregunto entonces si podría ser el comando 'tipo' del shell de MS-DOS que está causando la pérdida del byte final? Creo que tendré que probar el equivalente en Linux. Gracias. – thebeav

9

Si aún necesita esta ... Esta prueba sencilla que he usado para leer archivo binario que contiene el carácter 0x1A en entre

import os, sys, msvcrt 

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

Mis datos de archivos de prueba fue:

0x23, 0x1A, 0x45 

Sin establecer stdin en modo binario, esta prueba imprime 1 tan pronto como trate 0x1A como EOF. Por supuesto, solo funciona en Windows, porque depende del módulo msvcrt.

+1

Pero Windows es el único sistema donde la mayoría de la gente se encontrará con un problema, por lo que esta debería ser una solución aceptable. –

+1

Esta es la solución correcta para que Python 2 recupere los bytes sin formato de stdin en Windows. En Unix, no hay diferencia entre el modo binario y el normal. Ver este hilo: http://code.activestate.com/lists/python-list/20426/ (¿volver a abrir stdin en modo raw (binary)?) –

+0

Ver también http://cygwin.com/cygwin-ug- net/using-textbinary.html –

17

A partir de los documentos (ver 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') .

Pero, como en la respuesta aceptada, la invocación de pitón con un -u es otra opción que fuerza la entrada estándar, stdout y stderr a ser totalmente sin búfer. Consulte la página de manual de python (1) para más detalles.

Consulte el documentation on io para obtener más información sobre el almacenamiento en búfer de texto, y use sys.stdin.detach() para deshabilitar el almacenamiento en búfer desde dentro de Python.

+6

que doc conduce a documentos py3k, no es lo que OP quiere tratar. –

+1

He intentado '-u' con Python v3.2.5 pero no ha sido útil. Pero el uso de 'sys.stdout.buffer' funciona bastante bien, aunque en Python 2.7.8 no existe dicha función. – ony

+0

La pregunta del OP fue sobre Python 2.6. – Yuval

13

Aquí es el corte final para Linux/Windows Python 2/3 código compatible para leer datos de la entrada estándar sin corrupción:

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()