Dosyaya satır yazmanın doğru yolu var mı?


1069

Yapmaya alışkınım print >>f, "hi there"

Ancak, print >>kullanımdan kaldırılıyor gibi görünüyor . Yukarıdaki satırı yapmanın önerilen yolu nedir?

Güncelleme : Tüm bu cevaplarla ilgili olarak "\n"... bu evrensel mi Unix'e mi özgü? IE, "\r\n"Windows'ta mı yapmalıyım ?


11
"\ n" Unix'e özgü değil. Dosya metin modunda açıldığında (varsayılan), otomatik olarak geçerli platform için biten doğru satıra çevrilir. "\ R \ n" yazılması yanlış "\ r \ r \ n" üretir.
D Coetzee

ASCII kodunu (çoğu UNIX sisteminde 10) görmek için print ord (os.linesep) ifadesini eklemeniz yeterlidir
Stefan Gruenwald

Sizce neden kullanımdan kaldırıldı?
xxx ---

Yanıtlar:


1152

Bu kadar basit olmalıdır:

with open('somefile.txt', 'a') as the_file:
    the_file.write('Hello\n')

Belgelerden:

os.linesepMetin modunda açılan dosyaları yazarken satır sonlandırıcı olarak kullanmayın (varsayılan); bunun yerine tüm platformlarda tek bir '\ n' kullanın.

Bazı yararlı okumalar:


36
Bu örnek açma / kapama örneğinden daha iyidir. Kullanmak withbir dosyayı kapatmayı hatırlamanın daha güvenli bir yoludur.
Eyal

18
Aramam gerekmiyor the_file.close()mu?
Hussain

19
hayır
Tal Jerome

@Johnsyweb Neden "os.linesep. Os'da çok iyi şeyler var!" Burada bir düzenleme olduğundan şüpheleniyorum ve bu aşağı oyların nedeni olabilir.
Horse Smith

1
@ user3226167: Bu ilginç bir nokta. Ama neden düz metin yazmak için bir ikili dosya açasın ki?
Johnsyweb

961

print()Python 2.6+ sürümünden bu yana kullanılabilen işlevi kullanmalısınız

from __future__ import print_function  # Only needed for Python 2
print("hi there", file=f)

İşlev varsayılan importolduğundan, Python 3 için gerekmez print().

Alternatif kullanmak:

f = open('myfile', 'w')
f.write('hi there\n')  # python will convert \n to os.linesep
f.close()  # you can omit in most cases as the destructor will call it

Yeni satırlarla ilgili Python belgelerinden alıntı :

Çıktıda, yeni satır Yok ise, '\n'yazılan karakterler sistemin varsayılan satır ayırıcısına çevrilir os.linesep. Newline ise '', çeviri yapılmaz. Yeni satır diğer yasal değerlerden biriyse, '\n'yazılan karakterler verilen dizeye çevrilir.


35
-1 "Emin olmak istiyorsanız, dizeye \n" newline = "" yerine os.linesep ekleyin, aksi takdirde \r\r\nWindows'a girersiniz . Os.linesep ile futz hakkında hiçbir neden yok.
John Machin

7
@Sorin: Yazma modu eklemek için yaptığınız düzenleme elbette bir gelişmedir. Ancak garip bir şekilde os.linesep hakkında uzlaşmaz kalırsınız. Cevabımı gör. Bu arada, teklif ettiğiniz belgeler 3.x içindir, ancak bu bölüm metin modunda 2.x için de geçerlidir: yazılan tüm '\ n' karakterleri sistem varsayılan satır ayırıcısına, os.linesep * 'e çevrilir . .. Windows: os.linesep yazmak, os.linesep diline çevrilmiş olan yazı \r\nile aynıdır ve bu da sonuçtur . \n\r\n\r\r\n
John Machin

7
@ Haklısın, os.linesep hatasını düzelttim. Teşekkürler.
sorin

3
Eklemek için open('myfile','a')değil open('myfile','w')mi?
NeDark

6
@BradRuderman Bu , bir metin dosyasındaki "satır" ı neyin oluşturduğu POSIX standardının bir parçasıdır , yani bir metin dosyasındaki her satır son satırla birlikte bir satırsonu ile sonlandırılmalıdır.
wheeler

116

Piton dokümanlar bu yolu tavsiye:

with open('file_to_write', 'w') as f:
    f.write('file contents\n')

Bu yüzden genellikle böyle yaparım :)

Dan Bildirimi docs.python.org :

Dosya nesneleriyle uğraşırken 'with' anahtar kelimesini kullanmak iyi bir uygulamadır . Bunun avantajı, yolda bir istisna olsa bile, paketin tamamlanmasından sonra dosyanın düzgün bir şekilde kapatılmasıdır. Aynı zamanda eşdeğer try-finally blokları yazmaktan çok daha kısadır.


1
withBir döngüyü iç içe yerleştirmem gerektiğinde bu şekilde hoşlanmıyorum . Bu, döngümde ilerlerken dosyayı sürekli olarak açıp kapatmamı sağlıyor. Belki burada bir şey eksik, ya da bu gerçekten bu senaryoda bir dezavantaj?
Sibbs Kumar

38
İle döngü nasıl olur?
j7nn7k

fd hattı için @ j7nn7k:
momstouch

86

Os.linesep ile ilgili olarak:

İşte Windows'da tam bir düzenlenmemiş Python 2.7.1 tercüman oturumu:

Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.linesep
'\r\n'
>>> f = open('myfile','w')
>>> f.write('hi there\n')
>>> f.write('hi there' + os.linesep) # same result as previous line ?????????
>>> f.close()
>>> open('myfile', 'rb').read()
'hi there\r\nhi there\r\r\n'
>>>

Windows'ta:

Beklendiği gibi, os.linesep yok DEĞİL aynı sonucu üretmek '\n'. Aynı sonucu üretebilmesinin hiçbir yolu yoktur. 'hi there' + os.linesepeşdeğerdir 'hi there\r\n'olan DEĞİL eşdeğer 'hi there\n'.

Bu basit: \notomatik olarak os.linesep'e çevrilecek olan kullanımı. Python'un Windows'a ilk limanından bu yana bu kadar basitti.

Windows olmayan sistemlerde os.linesep kullanmanın bir anlamı yoktur ve Windows'ta yanlış sonuçlar üretir.

Os.linesep KULLANMAYIN!


harika bir örnek - bir ipython kullanıcısı olup olmadığınızı mı merak ediyorsunuz? oturumları biçimlendirmek için güzel fonksiyonlar
Alvin

Bize burada ne anlatmaya çalıştığınızdan tam olarak emin değilim. os.linesep, işletim sistemi tarafından tanımlandığı şekilde satır terimi karakterini (veya dizesini) döndürür. Windows varsayılan olarak satır sonları için \ r \ n kullanır. Ancak, tek bir \ n tanınır. \ N kullanımı tamamen taşınabilir bir ÇIKIŞ verecektir, ancak os.linesep pencerelerde yanlış değildir.
Gusdor

5
@Gusdor: Mesele şu ki os.linesep, Windows'da açıkça metin modunda kullanırsanız, sonuç \r\r\nyanlıştır. "Windows kullanıyor ..." anlamsız. C çalışma zamanı kitaplığı (ve dolayısıyla Python) çevirmek \niçin \r\nmetin modunda çıkışına. Diğer yazılımlar farklı davranabilir. Windows üzerinde çalışan tüm yazılımların \nmetin modunda okurken yalnız bir satır ayırıcı olarak tanıması DEĞİLDİR . Python yapar. Microsoft'un Not Defteri metin düzenleyicisi bunu yapmaz.
John Machin

6
Tartışmasız bir başkası onu okuyacak, sen değil, ekstra hakkında barf yapacak bazı mickey-mouse yazılımı ile \r...
John Machin

2
@Gusdor, farklı bir dilden python'a mı geliyorsunuz, burada '\ n' kullanıldığında, '\ r \ n' yerine '\ n' çıktısı ortaya çıkıyor - bu yüzden aptalca beklenen '\ r' eksik metin editörleri? John'un dediği gibi, Python böyle davranmaz - '\ n' otomatik olarak '\ r \ n' ile değiştirilir, eğer os.linesep böyle yaparsa. Bu nedenle, açıkça söyleyerek os.linesep olduğunu burada "yanlış". Bu gibi Department of Redundancy Department. Evet, bunu yapabilirsin. Hayır, istemiyorsun.
ToolmakerSteve

55

"Doğru" bir yol olduğunu düşünmüyorum.

Kullanmak istiyorum:

with open ('myfile', 'a') as f: f.write ('hi there\n')

Anısına Tim Toady .


Ancak OP dosyaya ek şeyler yazmak isteyebilir. Burada withkapsam dışına çıktığında dosya kapatılacaktır .
Keith

Bu, open(..., 'a')hatta olmak isteyebilir 'at'.
mtrw

5
Eee, evet. Birlikte kullanma fikri budur. Dosyayı açık tutmak istiyorsanız, başlangıçta açık ara ve işiniz bittiğinde aramayı kapat ...
Hyperboreus

1
@mtrw. Doğru. OP ekliyordu.
Hyperboreus

1
Python ile ilgili olarak RIP Tim Toady - ve çok çok çok haklı olarak
Mr_and_Mrs_D

21

Python 3'te bir işlevdir, ancak Python 2'de bunu kaynak dosyanın en üstüne ekleyebilirsiniz:

from __future__ import print_function

Sonra yaparsın

print("hi there", file=f)

17

Eğer çok fazla veri yazıyorsanız ve hız büyük olasılıkla gitmeniz gereken bir konudur f.write(...). Hızlı bir hız karşılaştırması yaptım ve print(..., file=f)çok sayıda yazma işleminden çok daha hızlıydı .

import time    

start = start = time.time()
with open("test.txt", 'w') as f:
    for i in range(10000000):
        # print('This is a speed test', file=f)
        # f.write('This is a speed test\n')
end = time.time()
print(end - start)

writeMakinemde ortalama olarak 2.45'lerde bitti, oysa printyaklaşık 4 kat daha uzun sürdü (9.76s). Bununla birlikte, çoğu gerçek dünya senaryosunda bu bir sorun olmayacaktır.

Eğer gitmeyi print(..., file=f)seçerseniz, muhtemelen yeni satırı zaman zaman bastırmak veya başka bir şeyle değiştirmek isteyeceksiniz. Bu, isteğe bağlı endparametre ayarlanarak yapılabilir ;

with open("test", 'w') as f:
    print('Foo1,', file=f, end='')
    print('Foo2,', file=f, end='')
    print('Foo3', file=f)

Hangi yolu seçerseniz seçin with, kodun okunmasını kolaylaştırdığı için kullanmanızı öneririm .

Güncelleme : Performanstaki bu fark write, yüksek oranda arabelleğe alınmış ve diske yazma işlemi gerçekleşmeden önce geri dönen ( bu cevaba bakınız ), oysa print(muhtemelen) satır arabelleğe alma işleviyle açıklanmaktadır. Bunun için basit bir test, satır arabelleğe alma için dezavantajların (hız açısından) daha az belirgin olacağı uzun yazmaların performansını kontrol etmek olacaktır.

start = start = time.time()
long_line = 'This is a speed test' * 100
with open("test.txt", 'w') as f:
    for i in range(1000000):
        # print(long_line, file=f)
        # f.write(long_line + '\n')
end = time.time()

print(end - start, "s")

Performans farkı şimdi çok daha az belirgin hale geliyor ve ortalama süresi 2.20s writeve 3.10s print. Bu loooong hat performansının düşmesi için bir dizi dizeyi birleştirmeniz gerekiyorsa, printdaha verimli olacağı kullanım durumları biraz nadirdir.


10

3.5'ten beri pathlibbu amaçla da kullanabilirsiniz :

Path.write_text(data, encoding=None, errors=None)

İşaretli dosyayı metin modunda açın, üzerine veri yazın ve dosyayı kapatın:

import pathlib

pathlib.Path('textfile.txt').write_text('content')

5

Satır dediğinde, '\ n' karakterleriyle biten bazı serileştirilmiş karakterler anlamına gelir. Satır bir noktada son olmalıdır, bu yüzden her satırın sonunda '\ n' düşünmeliyiz. İşte çözüm:

with open('YOURFILE.txt', 'a') as the_file:
    the_file.write("Hello")

ekleme modunda her yazma işleminden sonra imleç yeni satıra taşınır, wmodu kullanmak istiyorsanız işlevin \nsonuna karakterler eklemelisiniz write():

the_file.write("Hello\n")

1
"Her yazma işleminden sonra ekleme modunda imleç yeni satıra taşınır" - hayır değil.
Se Se

3

Bir de iomodülü aşağıdaki gibi kullanabilirsiniz :

import io
my_string = "hi there"

with io.open("output_file.txt", mode='w', encoding='utf-8') as f:
    f.write(my_string)

1

Şişedeki bir dosyaya metin yazmak için kullanılabilir:

filehandle = open("text.txt", "w")
filebuffer = ["hi","welcome","yes yes welcome"]
filehandle.writelines(filebuffer)
filehandle.close()

0

Ayrıca deneyebilirsiniz filewriter

pip install filewriter

from filewriter import Writer

Writer(filename='my_file', ext='txt') << ["row 1 hi there", "row 2"]

İçine yazar my_file.txt

Bir yinelenebilir veya __str__destekli bir nesne alır .


0

Çok fazla yeni satır yazmam gerektiğinde, bir printişlevi kullanan bir lambda tanımlarım :

out = open(file_name, 'w')
fwl = lambda *x, **y: print(*x, **y, file=out) # FileWriteLine
fwl('Hi')

Bu yaklaşım, printişlevle birlikte kullanılabilen tüm özellikleri kullanabilme avantajına sahiptir .

Güncelleme: Georgy tarafından yorum bölümünde belirtildiği gibi, bu fikri şu partialişlevle daha da geliştirmek mümkündür :

from functools import partial
fwl = partial(print, file=out)

IMHO, bu daha işlevsel ve daha az şifreli bir yaklaşım.


2
Ya da başka bir (muhtemelen temizleyici) yolu bunu yazmak için: from functools import partial; fwl = partial(print, file=out).
Georgy

@Georgy Yaklaşımınız o kadar iyi ki, yeni bir cevap olarak verilebilir.
MxNx

1
Fikir sizinkilerle aynı, sadece uygulama biraz farklı. İsterseniz cevabınıza bir düzenlemeye ekleyebilirsiniz. Onunla iyiyim.
Georgy
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.