Mischen von read () und write () auf Python-Dateien in Windows

Es scheint, dass ein write() unmittelbar nach einem read() auf einer Datei, die mit r+ (oder r+b ) Berechtigungen in Windows geöffnet wird, die Datei nicht aktualisiert.

Angenommen, es gibt eine Datei testfile.txt im aktuellen Verzeichnis mit folgendem Inhalt:

 This is a test file. 

Ich lege den folgenden Code aus:

 with open("testfile.txt", "r+b") as fd: print fd.read(4) fd.write("----") 

Ich würde erwarten, dass der Code zu drucken This und aktualisieren Sie die Datei Inhalt zu diesem:

 This----a test file. 

Das funktioniert gut auf mindestens Linux. Allerdings, wenn ich es auf Windows laufen lassen, dann wird die Nachricht korrekt angezeigt, aber die Datei wird nicht geändert – es ist wie das write() wird ignoriert. Wenn ich tell() auf dem filehandle anrufe, zeigt es an, dass die Position aktualisiert wurde (es ist 4 vor dem write() und 8 danach), aber keine Änderung an der Datei.

Allerdings, wenn ich eine explizite fd.seek(4) kurz vor der write() Zeile dann alles funktioniert, wie ich erwarten würde.

Kennt jemand den Grund für dieses Verhalten unter Windows?

Als Referenz benutze ich Python 2.7.3 auf Windows 7 mit einer NTFS-Partition.

BEARBEITEN

Als Antwort auf Kommentare, versuchte ich sowohl r+b und rb+ – die offiziellen Python-Dokumente scheinen zu implizieren, dass die ehemalige ist kanonisch.

Ich rufe an fd.flush() an verschiedenen Orten an und platziere einen zwischen dem read() und dem write() wie fd.flush() :

 with open("testfile.txt", "r+b") as fd: print fd.read(4) fd.flush() fd.write("----") 

… ergibt den folgenden interessanten Fehler:

 IOError: [Errno 0] Error 

BEARBEITEN 2

Indirekt, dass die Hinzufügung eines flush() geholfen hat, weil es mich zu diesem Beitrag führt , der ein ähnliches Problem beschreibt. Wenn einer der Kommentatoren auf es richtig ist, ist es ein Fehler in der zugrunde liegenden Windows C-Bibliothek.

4 Solutions collect form web for “Mischen von read () und write () auf Python-Dateien in Windows”

Die Python-Datei-Operation sollte der libc Konvention folgen, da sie intern mit den C-Datei-IO-Funktionen implementiert ist.

Zitat von fopen man Seite oder fopen Seite in cplusplus

Für Dateien, die zum Anhängen geöffnet sind (diejenigen, die ein "+" – Zeichen enthalten), auf denen sowohl Eingangs- als auch Ausgangsoperationen erlaubt sind, sollte der Stream zwischen einem Schreibvorgang, der gefolgt wird, gespült (fflush) oder neu positioniert werden (fseek, fsetpos, rewind) Einen Lesevorgang oder einen Lesevorgang, der das End-of-File nicht erreicht hat, gefolgt von einem Schreibvorgang.

fflush Sie zusammenfassen müssen, wenn Sie eine Datei nach dem Schreiben lesen müssen, fflush den Puffer und einen Schreibvorgang nach dem Lesen fseek , als fd.seek(0, os.SEEK_CUR)

Also ändere einfach dein Code-Snippet

 with open("test1.txt", "r+b") as fd: print fd.read(4) fd.seek(0, os.SEEK_CUR) fd.write("----") 

Das Verhalten ist konsistent mit dem, wie sich ein ähnliches C-Programm verhalten würde

 #include <cstdio> int main() { char buffer[5] = {0}; FILE *fp = fopen("D:\\Temp\\test1.txt","rb+"); fread(buffer, sizeof(char), 4, fp); printf("%s\n", buffer); /*without fseek, file would not be updated*/ fseek(fp, 0, SEEK_CUR); fwrite("----",sizeof(char), 4, fp); fclose(fp); return 0; } 

Es scheint, dass dies aufgrund des Verhaltens der zugrunde liegenden Windows-Bibliotheken (die ich persönlich in der Irrtum sehe) und nichts falsch mit Python. Beim Hinzufügen eines flush() Anrufs zwischen Lesen und Schreiben (was anscheinend gute Praxis ist ) bekam ich einen IOError mit einem Null errno, das ist das gleiche Problem wie in diesem Blog-Post diskutiert.

Von diesem Post fand ich diese Python-Frage, die das Problem erwähnt und sagt, dass die seek() Aufruf ist eigentlich die beste Workaround, zusammen mit einem flush() jedes Mal, wenn Sie vom Lesen zum Schreiben ändern.

Alles, was berücksichtigt wird, scheint es der beste Weg, um den Code oben so zu schreiben, dass es erfolgreich auf Windows läuft:

 with open("testfile.txt", "r+b") as fd: print fd.read(4) fd.flush() fd.seek(4) fd.write("----") 

Könnte etwas im Auge behalten für jeden, der versucht, portable Code zu schreiben.

Hast du versucht, zu spülen?

 fd.flush() 

Es ist OS-abhängig, da write den Dateisystem-Caching-Mechanismus verwendet

Ist es möglich, dass die Implementierung missinterpretestest "r + b"? Afaik "rb +" dient zum Lesen und Schreiben im Binär.

  • Python funktioniert nicht in der Kommandozeile von git bash
  • So entfernen Sie mehrere Versionen von Python aus der Windows Registry
  • Windows Logon als Benutzer ohne Passwort mit Python
  • Probleme mit Zwischenablage in Python
  • Python - Testverzeichnis Berechtigungen
  • Shutil.rmtree schlägt auf Windows mit "Zugriff verweigert"
  • Wie kann ich das Konsolenfenster in einer PyQt App unter Windows verbergen?
  • Schleife durch Registry Python
  • Plan Python Script - Windows 7
  • Gibt es Windows analog zum Supervisor?
  • Python, wie kann ich mehrere Dateien aus einer Liste umbenennen?
  • Python ist die beste Programmiersprache der Welt.