file handler - Problem bei mehrmaligem Durchlauf einer Befehlssequenz

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
thorstein
User
Beiträge: 3
Registriert: Sonntag 16. August 2020, 11:23

Hallo,
ich bin hier neu und hab bisher eher kleine Skripts geschrieben, was sich aber gerade ändert - es wird mehr und kontinuierlich. Darum lese und teste mich gerade durch die Lib-Doku - aktuell os und os.path - und bin auf folgendes Problem gestoßen.

Der erste, unten stehende Codeblock läuft nur einmal fehlerfrei durch (os/os.path lade ich nur einmal), weil der file handler für file3/fd3 beim nächsten Durchlauf nicht mehr erzeugt werden kann:
Fehler OSError: [WinError 6] Das Handle ist ungültig"

Verwende ich hingegen die os.open()-Methode auch für den dritten file handler (siehe zweiten Codeblock, kann der Code problemlos mehrfach ausgeführt werden. Mir scheint, das Problem kommt aus der Ecke, dass Python manche Sachen nur einmal in einer Session ausführt. Es wundert mich aber, dass mit der with open() as -Methode der file-handler wiederholt erzeugt wird. Ist die letztendlich nicht nur ein Wrapper um die vollständige Sequenz von file = open()… file.close() inkl. try/except?

Verwendet wird Python 3.6.6 (Anaconda)-

Vielen Dank, wenn hier jemand ein bisschen Licht ins Dunkel der Abläufe bringen kann!!!

Code: Alles auswählen

# Codeblock 1
import os
from os.path import *

datei1 = 'punch.txt'
fd1 = os.open(datei1, os.O_RDONLY)

datei2 = 'punch2.txt'
with open(datei2, 'a') as file2:
  print('sameopenfile(fd1,file2.fileno()) -->', sameopenfile(fd1, file2.fileno()))

datei3 = 'punch.txt'
file3 = open(datei3, mode = 'r')
fd3 = file3.fileno()
print('sameopenfile(fd1, fd3) -->', sameopenfile(fd1, fd3))

os.close(fd1)
os.close(fd3)
del fd1, fd3

Code: Alles auswählen

# Codeblock 2
datei3 = 'punch.txt'
fd3 = os.open(datei3, os.O_RDONLY)
print('sameopenfile(fd1, fd3) -->', sameopenfile(fd1, fd3))
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Was meinst du mit "nur beim ersten Mal?" Wie führst du den Code denn aus?
Die Funktionen aus os sind sehr low-Level und man braucht die in normalen Programmen nicht. Dateien, die man mit open öffnet, sollte man auch mit close wieder schließen, nicht mit os.close, am besten implizit mit dem with-Statement.
del für Variablen braucht man nie. Das macht hier sich wenig Sinn.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@thorstein: Vergiss auch gleich mal den *-Import insbesondere aus solchen Modulen die so gar nicht dafür gemacht sind. Du importierst da beispielsweise auch den Namen `os`, der an der Stelle glücklicherweise das davor importierte `os`-Modul durch das gleiche Modul ersetzt.

Und wo kommt im zweiten Codeblock eigentlich `fd1` her?
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
thorstein
User
Beiträge: 3
Registriert: Sonntag 16. August 2020, 11:23

@Sirius3, Danke für den entscheidenden Hinweis mit dem falschen close! Hat einen ja schon angesprungen... Ich hab im Interpreter gearbeitet, d.h. ich hab den Code einfach wiederholt eingegeben oder neu reinkopiert.
Dass die os-funktionen low-Level sind und gewöhnlich keine Rolle spielen, habe ich der Dok entnommen. Es ist eben eine kleine Python-Lib-Kennenlern-Tour, wo es weniger um Sinn im Sinne von Programme schreiben geht. Außerdem soll keine Lib-Funktionen diskriminiert werden :wink:
thorstein
User
Beiträge: 3
Registriert: Sonntag 16. August 2020, 11:23

@__blackjack__
__blackjack__ hat geschrieben: Sonntag 16. August 2020, 14:39 @thorstein: Vergiss auch gleich mal den *-Import insbesondere aus solchen Modulen die so gar nicht dafür gemacht sind. Du importierst da beispielsweise auch den Namen `os`, der an der Stelle glücklicherweise das davor importierte `os`-Modul durch das gleiche Modul ersetzt.
In diesem spezifischen Fall wollte ich alle Funktionen aus os.path ohne viel Tipperei mit kleinen Beispielen ausprobieren. Dafür war es mir sehr recht, den path-Teil aus dem os-Namensraum entsprechend zu überschreiben, weil es auch keine Gefahr durch Namenskollisionen gab.
OS ist jetzt vielleicht kein gut passendes Beispiel, aber mal angenommen, ich wüsste, in einem realen Programm kämen die meisten Funktionen aus os.path und nur einzelne aus os. Wäre folgendes guter Python-Stil(?):
import os
import os.path as op

Letztlich ist es ja nur das Überschreiben eines Teilnamensraums und bleibt m.E. trotzdem übersichtlich.
Den *-Import sollte man wegen mgl. Namenskonflikte vermeiden, oder gab es da auch andere Gründe?
__blackjack__ hat geschrieben: Sonntag 16. August 2020, 14:39 Und wo kommt im zweiten Codeblock eigentlich `fd1` her?
Der zweite Codeblock sollte nur der Alternativcode aus dem ersten Teil sein, wo die dritte Datei geöffnet wird. Ich hatte ja fälschlicherweise angenommen, dass da irgendwas mit Python ist, was ich nicht verstehe. Aber es war letztlich nur die falsche os.close(fd3)-Anweisung. Die print-Anweisung wollte ich gar nicht mitkopieren.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@thorstein: Kryptische Abkürzungen sind eher nicht so toll. Das macht man nur bei bestimmten Modulen die wirklich sehr viel enthalten und auch weil die oft aus Ecken kommen wo so etwas, auch wenn es nicht so toll ist, normal ist. Also beispielsweise der ganze Numpy, Pandas, Matplotlib Bereich.

In einem realen Programm kommt nicht so viel aus `os.path`, denn die Prämisse, dass keine Lib-Funktionen diskriminiert werden, stimmt nicht so ganz. In `os.path` ist vieles nur noch ”Bürger” zweiter Klasse seitdem es das `pathlib`-Modul gibt.

Neben Namenskonflikten ist es auch sehr unübersichtlich wenn man *-Importe hat, weil man dann nicht mehr so einfach sehen/herausfinden kann wo ein Name her kommt.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten