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


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

32
2018-03-03 19:47


origen


Respuestas:


¿En que plataforma Estas tu?

Tu podrías intentar 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 reabrir sys.stdout en modo binario, pero realmente no sé si hay una mejor alternativa que la anterior para Python 2.x.


25
2018-03-03 20:01



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

-u Fuerza stdin, stdout y stderr para ser totalmente sin buffer.
       En sistemas donde es importante, también ponga stdin, stdout y stderr
       en modo binario

8
2018-02-17 20:12



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.


6
2018-03-03 19:50



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

5
2018-02-04 08:21



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

0
2017-11-26 13:30