python binary stdout

Python 2.x-¿Escribir salida binaria a stdout?



binary (5)

¿En que plataforma Estas tu?

Puedes probar esta receta si estás en Windows (el enlace sugiere que es específico de Windows de todos modos).

if sys.platform == "win32": import os, msvcrt msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

Hay algunas referencias en la web que deberían / ​​deberían ser una función en Python 3.1 para volver a abrir sys.stdout en modo binario, pero realmente no sé si hay una mejor alternativa que la anterior para Python 2.x.

¿Hay alguna forma de escribir salida binaria a sys.stdout en Python 2.x? En Python 3.x, puede simplemente usar sys.stdout.buffer (o separar stdout, etc ...), pero no he podido encontrar ninguna solución para Python 2.5 / 2.6.

EDITAR, Solución : del enlace de ChristopheD, a continuación:

import sys if sys.platform == "win32": import os, msvcrt msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

EDITAR: Estoy tratando de enviar un archivo PDF (en formato binario) a stdout para servir en un servidor web. Cuando intento escribir el archivo usando sys.stdout.write, agrega todo tipo de retornos de carro a la secuencia binaria que hace que el PDF se vuelva corrupto.

EDIT 2: para este proyecto, necesito ejecutar en un servidor de Windows, desafortunadamente, para que las soluciones Linux estén fuera.

Ejemplo simple simulado (leer de un archivo en disco, en lugar de generar sobre la marcha, solo para que sepamos que el código de generación no es el problema):

file = open(''C://test.pdf'',''rb'') pdfFile = file.read() sys.stdout.write(pdfFile)


En Python 2.x, todas las cadenas son matrices de caracteres binarios de forma predeterminada, por lo que creo que debería poder

>>> sys.stdout.write(data)

EDIT: he confirmado tu experiencia.

Creé un archivo, gen_bytes.py

import sys for char in range(256): sys.stdout.write(chr(char))

Y otro read_bytes.py

import subprocess import sys proc = subprocess.Popen([sys.executable, ''gen_bytes.py''], stdout=subprocess.PIPE) res = proc.wait() bytes = proc.stdout.read() if not len(bytes) == 256: print ''Received incorrect number of bytes: {0}''.format(len(bytes)) raise SystemExit(1) if not map(ord, bytes) == range(256): print ''Received incorrect bytes: {0}''.format(map(ord, bytes)) raise SystemExit(2) print "Everything checks out"

Póngalos en el mismo directorio y ejecute read_bytes.py. Efectivamente, parece como si Python estuviera convirtiendo líneas nuevas en la salida. Sospecho que esto solo ocurre en un sistema operativo Windows.

> ./read_bytes.py Received incorrect number of bytes: 257

Siguiendo el ejemplo de ChristopheD, y cambiando gen_bytes a lo siguiente, corrige el problema.

import sys if sys.platform == "win32": import os, msvcrt msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) for char in range(256): sys.stdout.write(chr(char))

Incluyo esto para completar. ChristopheD merece el crédito.


Lo resolví usando un contenedor para un descriptor de archivo. (Probado en Python 3.2.5 en Cygwin)

class BinaryFile(object): '''''' Wraps a file-descriptor to binary read/write. The wrapped file can not be closed by an instance of this class, it must happen through the original file. :param fd: A file-descriptor (integer) or file-object that supports the ``fileno()`` method. '''''' def __init__(self, fd): super(BinaryFile, self).__init__() fp = None if not isinstance(fd, int): fp = fd fd = fp.fileno() self.fd = fd self.fp = fp def fileno(self): return self.fd def tell(self): if self.fp and hasattr(self.fp, ''tell''): return self.fp.tell() else: raise io.UnsupportedOperation( ''can not tell position from file-descriptor'') def seek(self, pos, how=os.SEEK_SET): try: return os.lseek(self.fd, pos, how) except OSError as exc: raise io.UnsupportedOperation(''file-descriptor is not seekable'') def write(self, data): if not isinstance(data, bytes): raise TypeError(''must be bytes, got %s'' % type(data).__name__) return os.write(self.fd, data) def read(self, length=None): if length is not None: return os.read(self.fd, length) else: result = b'''' while True: data = self.read(1024) if not data: break result += data return result


Puede usar argopen .argopen (), maneja dash como stdin / stdout, y arregla el modo binario en Windows.

import argopen stdout = argopen.argopen(''-'', ''wb'') stdout.write(some_binary_data)


Puede usar el modo sin búfer: python -u script.py .

-u Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode.