2010-03-03 18 views
31

Czy istnieje sposób zapisu danych binarnych do sys.stdout w Pythonie 2.x? W Pythonie 3.x możesz po prostu użyć sys.stdout.buffer (lub odłączyć standardowe wyjście, etc ...), ale nie znalazłem żadnych rozwiązań dla Pythona 2.5/2.6.Python 2.x - Napisz wyjście binarne na standardowe wyjście?

EDIT, Rozwiązanie: Od linku ChristopheD jest poniżej:

import sys 

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

EDIT: próbuję naciskać plik PDF (w postaci binarnej) do stdout do serwowania się na serwerze WWW. Kiedy próbuję zapisać plik przy użyciu sys.stdout.write, dodaje on wszystkie rodzaje powrotów karetki do strumienia binarnego, który powoduje, że plik PDF jest uszkodzony.

EDYCJA 2: W przypadku tego projektu, muszę uruchomić na serwerze Windows, niestety, więc rozwiązania dla systemu Linux są obecnie niedostępne.

Wystarczy Dummy Przykład (odczyt z pliku na dysku, zamiast generować w locie, tak więc wiemy, że kod pokolenie nie jest problem):

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

Kiedy zrobiłeś 'sys.stdout.write()' co nie działało? –

+0

Zobacz powyżej dla wyjaśnienia, ale problem jest w zasadzie, że python dodaje zwraca karetki, gdy próbuje konwertować strumień binarny na ciąg do pisania. – Eavesdown

+0

Czy 'sys.stdout = os.fdopen (1," wb ")' działa, aby wyeliminować konwersje w trybie tekstowym? (Będziesz nadal potrzebował użyć sys.stdout.write, jeśli nie chcesz, aby NL-y były drukowane.) (Http://docs.python.org/library/os.html#os.fdopen) –

Odpowiedz

24

Na jakiej platformie jesteś?

Możesz spróbować this recipe, jeśli jesteś w systemie Windows (link sugeruje, że jest to i tak specyficzne dla systemu Windows).

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

Istnieją pewne odniesienia w sieci, że nie będzie/powinna być funkcją w Pythonie 3.1 do ponownego sys.stdout w trybie binarnym, ale ja naprawdę nie wiem, czy istnieje lepsza alternatywa to powyższe dla Pythona 2. x.

+0

Zrobiłem test po prostu czytając plik PDF z pliku i zapisując go z powrotem, powraca karetki są nadal dodawane. – Eavesdown

+0

Podany link do rozwiązania Windows to idealne rozwiązanie. Nie mogę ci wystarczająco podziękować; to doprowadzało mnie absolutnie do ściany. – Eavesdown

+0

+1 Dzięki za to! – Sabuncu

6

w Pythonie 2.x, wszystkie ciągi binarne są tablice znakowe domyślnie, więc uważam, że powinniśmy być w stanie tylko

>>> sys.stdout.write(data) 

EDIT: mam potwierdziła swoje doświadczenia.

stworzyłem jeden plik, gen_bytes.py

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

a inny 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" 

umieścić je w tym samym katalogu i uruchomić read_bytes.py. Oczywiście, wygląda na to, że Python faktycznie konwertuje nowe linie na wyjściu. Podejrzewam, że dzieje się tak tylko w systemie operacyjnym Windows.

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

Po wprowadzeniu ChristopheD i zmianie gen_bytes na następujące poprawki rozwiązuje problem.

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

Załączam to dla kompletności. ChristopheD zasługuje na uznanie.

+0

Działa to, jeśli próbujesz tylko dodać dane ciągów, ale Python próbuje powiązać dane binarne podczas wywoływania zapisu, uszkadzając dane. – Eavesdown

+0

Uruchomiłem 'gen_bytes.py' i' read_bytes.py' na Mac OS X (Python 2.5 z niewielkimi modyfikacjami dla brakujących słów kluczowych "format") i "Wszystko się zgadza" –

+0

Wygląda na to, że jest to problem wyłącznie dla Windows . – Eavesdown

5

Możesz użyć argopen .argopen(), obsługuje myślnik jako stdin/stdout i naprawia tryb binarny w systemie Windows.

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

To jest o wiele ładniejszy niż przepis ActiveState. Jak to rozgryzłeś? Moduł jest ledwo udokumentowany. –

+0

Nie działa dla mnie - moja dystrybucja nie ma argopen. Nie chcę go instalować, ponieważ "msvcrt.setmode()", o którym mowa powyżej, zadziałało właśnie dla mnie. –

7

Można użyć trybu niebuforowanego: 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. 
0

Rozwiązałem to za pomocą opakowania dla deskryptora pliku. (Testowane w Pythonie 3.2.5 na Cygwin)

Powiązane problemy