927 Stimmen

Wie kann ich mit "with open" in Python mehrere Dateien öffnen?

Ich möchte mehrere Dateien auf einmal ändern, wenn Ich kann sie alle anschreiben. Ich frage mich, ob ich die mehrfachen offenen Aufrufe irgendwie mit dem with Erklärung:

try:
  with open('a', 'w') as a and open('b', 'w') as b:
    do_something()
except IOError as e:
  print 'Operation failed: %s' % e.strerror

Wenn das nicht möglich ist, wie sähe dann eine elegante Lösung für dieses Problem aus?

1418voto

Sven Marnach Punkte 525472

Ab Python 2.7 (bzw. 3.1) können Sie schreiben

with open('a', 'w') as a, open('b', 'w') as b:
    do_something()

In früheren Versionen von Python können Sie manchmal contextlib.nested() um Kontextmanager zu verschachteln. Dies funktioniert jedoch nicht wie erwartet, wenn mehrere Dateien geöffnet werden sollen - siehe die verlinkte Dokumentation für Details.


Für den seltenen Fall, dass Sie eine variable Anzahl von Dateien gleichzeitig öffnen wollen, können Sie contextlib.ExitStack ab der Python-Version 3.3:

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # Do something with "files"

In den meisten Fällen haben Sie eine variable Anzahl von Dateien, die Sie wahrscheinlich nacheinander öffnen möchten.

130voto

Michael Punkte 8614

Einfach ersetzen and をもって , und Sie sind fertig:

try:
    with open('a', 'w') as a, open('b', 'w') as b:
        do_something()
except IOError as e:
    print 'Operation failed: %s' % e.strerror

97voto

Michael Ohlrogge Punkte 9771

Wenn Sie viele Dateien auf einmal öffnen oder lange Dateipfade verwenden, kann es sinnvoll sein, die Dateien auf mehrere Zeilen aufzuteilen. Vom Python Style Guide wie von @Sven Marnach in einem Kommentar zu einer anderen Antwort vorgeschlagen:

with open('/path/to/InFile.ext', 'r') as file_1, \
     open('/path/to/OutFile.ext', 'w') as file_2:
    file_2.write(file_1.read())

56voto

Chris_Rands Punkte 34669

Ab Python 3.10 gibt es eine neue Funktion von Eingeklammerte Kontextmanager , die eine Syntax wie die folgende erlaubt:

with (
    open("a", "w") as a,
    open("b", "w") as b
):
    do_something()

33voto

timgeb Punkte 72448

Seit Python 3.3 können Sie die Klasse ExitStack de la contextlib Modul zur sicheren
eine beliebige Anzahl von Dateien öffnen .

Es kann eine dynamisch Anzahl von kontextbezogenen Objekten, was bedeutet, dass es sich als besonders nützlich erweisen wird wenn Sie nicht wissen, wie viele Dateien Sie bearbeiten werden .

Der klassische Anwendungsfall, der in der Dokumentation erwähnt wird, ist die Verwaltung einer dynamischen Anzahl von Dateien.

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

Wenn Sie an den Details interessiert sind, finden Sie hier ein allgemeines Beispiel, um zu erklären, wie ExitStack arbeitet:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(len(stack._exit_callbacks)) # number of callbacks called on exit
    nums = [stack.enter_context(x) for x in xs]
    print(len(stack._exit_callbacks))

print(len(stack._exit_callbacks))
print(nums)

Ausgabe:

0
enter X1
enter X2
enter X3
3
exit X3
exit X2
exit X1
0
[1, 2, 3]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X