it-swarm.com.de

So öffnen Sie eine Datei mit der Anweisung open with

Ich schaue mir an, wie man Dateien in Python ein- und ausgibt. Ich habe den folgenden Code geschrieben, um eine Liste von Namen (einen pro Zeile) aus einer Datei in eine andere Datei zu lesen, während ein Name mit den Namen in der Datei verglichen und Text an die Vorkommen in der Datei angehängt wird. Der Code funktioniert. Könnte es besser gemacht werden?

Ich wollte die with open(... -Anweisung sowohl für Eingabe- als auch für Ausgabedateien verwenden, kann aber nicht erkennen, wie sie sich im selben Block befinden könnten, was bedeutet, dass ich die Namen an einem temporären Ort speichern muss.

def filter(txt, oldfile, newfile):
    '''\
    Read a list of names from a file line by line into an output file.
    If a line begins with a particular name, insert a string of text
    after the name before appending the line to the output file.
    '''

    outfile = open(newfile, 'w')
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

    outfile.close()
    return # Do I gain anything by including this?

# input the name you want to check against
text = input('Please enter the name of a great person: ')    
letsgo = filter(text,'Spanish', 'Spanish2')
179
Disnami

Mit Python können Sie mehrere open() -Anweisungen in eine with einfügen. Sie trennen sie durch Kommas. Ihr Code wäre dann:

_def filter(txt, oldfile, newfile):
    '''\
    Read a list of names from a file line by line into an output file.
    If a line begins with a particular name, insert a string of text
    after the name before appending the line to the output file.
    '''

    with open(newfile, 'w') as outfile, open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

# input the name you want to check against
text = input('Please enter the name of a great person: ')    
letsgo = filter(text,'Spanish', 'Spanish2')
_

Und nein, Sie erhalten nichts, wenn Sie ein explizites return am Ende Ihrer Funktion einfügen. Sie können return verwenden, um vorzeitig zu beenden, aber Sie hatten es am Ende, und die Funktion wird ohne sie beendet. (Natürlich verwenden Sie bei Funktionen, die einen Wert zurückgeben, return, um den zurückzugebenden Wert anzugeben.)

Die Verwendung mehrerer open() -Elemente mit with wurde in Python 2.5 bei der Einführung der with -Anweisung oder in Python 2.6 nicht unterstützt wird in Python 2.7 und Python 3.1 oder neuer unterstützt.

http://docs.python.org/reference/compound_stmts.html#the-with-statementhttp://docs.python.org/release/3.1/reference/compound_stmts. html # the-with-statement

Wenn Sie Code schreiben, der in Python 2.5, 2.6 oder 3.0 ausgeführt werden muss, verschachteln Sie die with -Anweisungen als die anderen vorgeschlagenen Antworten, oder verwenden Sie contextlib.nested .

282
steveha

Verwenden Sie verschachtelte Blöcke wie folgt,

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        # your logic goes right here
26
RanRag

Sie können Ihre mit Blöcken verschachteln. So was:

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

Dies ist besser als Ihre Version, da Sie garantieren, dass outfile geschlossen wird, auch wenn in Ihrem Code Ausnahmen auftreten. Natürlich könnten Sie das mit try/finally tun, aber with ist der richtige Weg, dies zu tun.

Oder, wie ich gerade erfahren habe, können Sie mehrere Kontextmanager in einer with-Anweisung als beschrieben von @steveha haben. Das scheint mir eine bessere Option zu sein, als zu nisten.

Und für Ihre letzte kleine Frage dient die Rückkehr keinem wirklichen Zweck. Ich würde es entfernen.

11
David Heffernan

Manchmal möchten Sie möglicherweise eine variable Anzahl von Dateien öffnen und alle gleich behandeln. Dies können Sie mit contextlib tun.

from contextlib import ExitStack
filenames = [file1.txt, file2.txt, file3.txt]

with open('outfile.txt', 'a') as outfile:
    with ExitStack() as stack:
        file_pointers = [stack.enter_context(open(file, 'r')) for file in filenames]                
            for fp in file_pointers:
                outfile.write(fp.read())                   
1
brother-bilo