2012-04-17 26 views
9

Ich möchte einen gepufferten Stream verwenden, weil ich eine peek()-Methode verwenden möchte, um einen Blick zu werfen, aber meinen Stream mit einer anderen Methode verwenden, die ein dateiähnliches Objekt erwartet. (I seek() verwenden würde, aber kann verrohrt-I/O zu handhaben, die nicht zufällig Zugriff nicht unterstützt.)Python: Verwenden von io.BufferedReader auf einem Stream mit open() erhalten?

Aber dieser Testfall versagt:

Attribute: ‚Datei‘ Objekt hat kein Attribut ' _checkReadable '

Was passiert und wie kann ich es beheben? Ich dachte, BufferedReader sollte einen Stream puffern. Wenn ja, warum gibt die open() Funktion nicht etwas zurück, das damit kompatibel ist?

+0

Es ist interessant. Obwohl wir die gleichen Versionen (2.7.x) haben, erhalten wir leicht unterschiedliche Fehlermeldungen. – username

+0

Ich habe es herausgefunden. Es gibt einen Kommentar in io.py als "" "Methodenbeschreibungen und Standardimplementierungen werden jedoch von der C-Version geerbt." "" Es hängt also von den c-Versionen oder dem Betriebssystem ab. – username

+0

@username: Dies ist nicht betriebssystemspezifisch. Mein Python 2.6.7 beschwert sich auch über _checkReadable, während sich mein 2.7.2 über "lesbar" beschwert.Ich kann das Commit jetzt nicht finden, aber das wurde wahrscheinlich irgendwo zwischen 2.7.0 und 2.7.2 geändert. –

Antwort

1

können Sie die Menge an Pufferung in Bytes festgelegt, indem die buffering argument vorbei zu öffnen:

import sys 

srcfile = sys.argv[1] 
with open(srcfile, 'rb', buffering=30) as f: 
    print(f.peek(30)) 
    print(f.read(20)) 

Dies ist ein BufferedReader:

>>> with open("test.txt", 'rb', buffering=30) as f: 
...  type(f) 
<class '_io.BufferedReader'> 

Beachten Sie, dass in der Standardeinstellung es 1 gepuffert wird - Zeile gepuffert.

+0

sicher, das ist in Ordnung , aber irgendwann werde ich andere Eingabequellen puffern wollen, die nicht gepuffert werden ... oder wird alles nur gepuffert? sys.stdin? Netzwerk-Streams? –

+0

Nun, dann können Sie tun, was Sie getan haben und '' BufferedReader (f) '' - da es bereits ein '' BufferedReader'' ist, wird es funktionieren. –

+1

Dies ist die Python 3-Lösung. In Python 2 sollte das OP 'io.open' verwenden. –

15

Durch das Aussehen Ihrer print Anweisung, sind Sie mit Python 2. Auf dieser Version ein file ist kein gültiges Argument für den Konstruktor BufferedReader:

Under Python 2.x, this is proposed as an alternative to the built-in file object, but in Python 3.x it is the default interface to access files and streams. (1)

Sie io.open stattdessen verwenden sollten:

>>> f = io.open(".bashrc", "rb") 

Wenn Sie dies tun, dann ist es nicht erforderlich, explizit wickeln in einem BufferedReader denn das ist genau das, was io.open kehrt standardmäßig:

>>> type(f) 
<type '_io.BufferedReader'> 

Siehe its docs für Details; Es gibt ein buffering Argument, das die Pufferung steuert.

In Python 3, open is io.open, so dass die beiden I/O-Bibliotheken in einem zusammengefasst wurden. Es scheint, dass io Python 2.6 hauptsächlich für die Vorwärtskompatibilität hinzugefügt wurde.

+0

+1 - das ist die richtige Antwort für 2.x –

+1

gibt es keine Notwendigkeit, für das Öffnen einer Datei zu umbrechen, aber was ist, wenn ich stattdessen sys.stdin verwende? –

+0

@JasonS: dann ist der [Hack] (http://Stackoverflow.com/questions/6065173/making-io-bufferedreader-from-sys-stdin-in-python), auf den 'username' gezeigt hat, gültig. Oder 'io.open ("/dev/stdin ")' wenn Ihre Plattform diese Datei hat (aber in jedem Fall von 'sys.stdin' frei ist). –

0

In Python2, wenn Sie file Objekt verwenden, wie durch open (oder beispielsweise zur Verfügung gestellt von einigen Modulroutinen, die nicht geändert werden können) zurückgeführt, können Sie Dateideskriptor durch fileno() für io.FileIO Konstruktor erhalten verwenden, dann übergibt io.FileIO Objekt io.BufferedReader Konstrukteur.

Also, probieren Sie Code neu geschrieben werden können wie folgt:

import sys 
import io 

srcfile = sys.argv[1] 
with open(srcfile, 'rb') as f: 
    fio = io.FileIO(f.fileno()) 
    fbuf = io.BufferedReader(fio) 
    print fbuf.read(20)