Open with ifadesini kullanarak dosya nasıl açılır


201

Python dosya giriş ve çıkış yapmak nasıl bakıyorum. Dosyadaki adlara karşı bir ad kontrol ederken ve dosyadaki olaylara metin eklerken, bir dosyadan başka bir dosyaya adların listesini (satır başına bir tane) okumak için aşağıdaki kodu yazdım. Kod çalışır. Daha iyi yapılabilir mi?

with open(...Hem giriş hem de çıkış dosyaları için deyimi kullanmak istedim ama aynı blokta nasıl olabileceğini göremiyorum.

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')

"yani adları geçici bir yerde saklamam gerekecek mi?" Bununla ne demek istediğini açıklayabilir misin?
S.Lott

4
Not filter()olduğu yerleşik bir fonksiyonu ve muhtemelen işlev için farklı bir ad seçmelisiniz böylece.
Tom

2
@ İsim alanındaki bir işlev yerleşik işlevi geçersiz kılar mı?
UpTide

2
@ UpTide: Evet, Python LEGB düzeninde çalışır - Yerel, Çevreleyen, Global, Yerleşik (bkz. Stackoverflow.com/questions/291978/… ). Yani, global bir işlev ( filter()) yaparsanız , yerleşik filter()
Tom

Yanıtlar:


309

Python, open()tek bir ifadeye birden fazla ifade koymaya izin verir with. Onları virgülle ayırırsınız. Kodunuz şöyle olur:

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')

Ve hayır, açık bir şekilde koyarak hiçbir şey kazanamazsınız. return fonksiyonunuzun sonuna . returnErken çıkmak için kullanabilirsiniz , ancak sonunda vardı ve işlev onsuz çıkacaktır. (Elbette bir değer döndüren işlevlerde, döndürülecek değeri returnbelirtmek için kullanın.)

İle birden çok open()öğe kullanılması with, Python 2.5'tewith veya Python 2.6'da , ancak Python 2.7 ve Python 3.1 veya daha yenisinde destekleniyor.

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

Python 2.5, 2.6 veya 3.0'da çalışması gereken bir kod yazıyorsanız, withifadeleri önerilen diğer yanıtlar olarak kullanın veya kullanın contextlib.nested.


29

Bunun gibi iç içe bloklar kullanın,

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

12

Bloklarla iç içe yerleştirebilirsiniz. Bunun gibi:

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)

Bu, sürümünüzden daha iyidir, çünkü outfilekodunuz istisnalarla karşılaşsa bile kapatılacağını garanti edersiniz . Açıkçası bunu dene / son olarak yapabilirsin, amawith bunu yapmanın doğru yolu budur.

Ya da, az önce öğrendiğim gibi , @steveha tarafından açıklandığı gibi bir with ifadesinde birden fazla içerik yöneticiniz olabilir . Bana öyle geliyor ki iç içe olmaktan daha iyi bir seçenek.

Ve son küçük sorunuz için, geri dönüş gerçek bir amaca hizmet etmez. Çıkardım.


Çok teşekkürler. Denerim ve işe yararsa / cevabını kabul edeceğim.
Disnami

Tekrar teşekkürler. Kabul etmeden önce yedi nane beklemek zorundayım.
Disnami

7
@Disnami doğru yanıtı kabul ettiğinizden emin olun (ve bu değil!) ;-)
David Heffernan

1

Bazen, değişken miktarda dosya açmak ve her birine aynı şekilde davranmak isteyebilirsiniz, bunu contextlib

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())                   
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.