Pertanyaan Python 2.x - Tuliskan output biner ke stdout?


Apakah ada cara untuk menulis output biner ke sys.stdout dengan Python 2.x? Pada Python 3.x, Anda bisa menggunakan sys.stdout.buffer (atau lepaskan stdout, dll ...), tetapi saya belum dapat menemukan solusi untuk Python 2.5 / 2.6.

EDIT, Larutan: Dari tautan ChristopheD, di bawah ini:

import sys

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

EDIT: Saya mencoba untuk mendorong file PDF (dalam bentuk biner) ke stdout untuk melayani di server web. Ketika saya mencoba untuk menulis file menggunakan sys.stdout.write, itu menambahkan semua jenis pengangkutan kembali ke aliran biner yang menyebabkan PDF untuk membuat korup.

EDIT 2: Untuk proyek ini, saya harus menjalankan Windows Server, sayangnya, sehingga solusi Linux tidak tersedia.

Cukup Contoh Dummy (membaca dari file di disk, bukannya menghasilkan on the fly, supaya kita tahu bahwa kode generasi bukanlah masalah):

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

32
2018-03-03 19:47


asal


Jawaban:


Platform mana yang Anda ikuti?

Kamu bisa mencoba resep ini jika Anda menggunakan Windows (tautan tersebut menandakan bahwa Windows itu spesifik).

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

Ada beberapa referensi di web yang akan ada / harus berfungsi dengan Python 3.1 untuk membuka kembali sys.stdout dalam mode biner tetapi saya tidak benar-benar tahu jika ada alternatif yang lebih baik dari yang di atas untuk Python 2.x.


25
2018-03-03 20:01



Anda dapat menggunakan mode unbuffered: python -u script.py.

-U Angkatan stdin, stdout dan stderr harus benar-benar unbuffered.
       Pada sistem yang penting, masukkan stdin, stdout dan stderr
       dalam mode biner.

8
2018-02-17 20:12



Dalam Python 2.x, semua string adalah array karakter biner secara default, jadi saya yakin Anda seharusnya bisa

>>> sys.stdout.write(data)

EDIT: Saya telah mengonfirmasi pengalaman Anda.

Saya membuat satu file, gen_bytes.py

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

Dan lainnya 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"

Taruh di direktori yang sama dan jalankan read_bytes.py. Benar saja, tampak seolah-olah Python sebenarnya mengubah baris baru pada output. Saya menduga ini hanya terjadi di OS Windows.

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

Mengikuti pimpinan oleh ChristopheD, dan mengubah gen_bytes ke berikut mengoreksi masalah.

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

Saya menyertakan ini untuk kelengkapan. ChristopheD layak mendapat pujian.


6
2018-03-03 19:50



Kamu dapat memakai argopen.argopen (), ia menangani dash sebagai stdin / stdout, dan memperbaiki mode biner pada Windows.

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

5
2018-02-04 08:21



Saya memecahkan ini menggunakan pembungkus untuk file-descriptor. (Diuji dengan Python 3.2.5 di 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