วิธีที่ถูกต้องในการเขียน line to file?


1069

ฉันเคยทำ print >>f, "hi there"

อย่างไรก็ตามดูเหมือนว่าprint >>จะเลิกใช้แล้ว วิธีที่แนะนำในการทำบรรทัดด้านบนคืออะไร?

ปรับปรุง : เกี่ยวกับคำตอบทั้งหมดที่มี"\n"... นี้เป็นสากลหรือเฉพาะ Unix? IE ฉันควรทำ"\r\n"บน Windows หรือไม่


11
"\ n" ไม่ใช่เฉพาะ Unix เมื่อไฟล์ถูกเปิดในโหมดข้อความ (ค่าเริ่มต้น) ไฟล์จะถูกแปลโดยอัตโนมัติเป็นบรรทัดที่ถูกต้องซึ่งลงท้ายด้วยแพลตฟอร์มปัจจุบัน การเขียน "\ r \ n" จะสร้าง "\ r \ r \ n" ซึ่งผิด
D Coetzee

เพียงเพิ่มคำสั่ง print ord (os.linesep) เพื่อดูรหัส ascii (10 ในระบบ UNIX ส่วนใหญ่)
Stefan Gruenwald

ทำไมคุณคิดว่าเลิกใช้แล้ว
xxx ---

คำตอบ:


1152

นี่ควรจะง่ายเหมือน:

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

จากเอกสาร:

อย่าใช้os.linesepเป็นตัวยุติบรรทัดเมื่อเขียนไฟล์ที่เปิดในโหมดข้อความ (ค่าเริ่มต้น); ใช้ '\ n' เพียงครั้งเดียวแทนบนทุกแพลตฟอร์ม

การอ่านที่มีประโยชน์:

  • withคำสั่ง
  • open()
    • 'a' ใช้สำหรับต่อท้ายหรือใช้
    • 'w' เพื่อเขียนด้วยการตัด
  • os(โดยเฉพาะos.linesep)

36
ตัวอย่างนี้ดีกว่าตัวอย่างเปิด / ปิด การใช้withเป็นวิธีที่ปลอดภัยกว่าในการจำปิดไฟล์
Eyal

18
ผมไม่ได้มีการโทรthe_file.close()?
ฮุสเซน

19
ไม่คุณไม่ได้: stackoverflow.com/questions/3012488/…
Tal Jerome

@Johnsyweb ทำไมคุณถึงพูดว่า "os.linesep มีหลายสิ่งที่ดีในระบบปฏิบัติการ!" เมื่อคุณก่อนหน้านี้ในโพสต์ที่แนะนำให้ใช้กับมันได้หรือไม่ ฉันสงสัยว่าจะมีการแก้ไขที่นี่และอาจเป็นสาเหตุของการลงคะแนนเสียง
Horse SMith

1
@ user3226167: นั่นเป็นจุดที่น่าสนใจ แต่ทำไมคุณถึงเปิดไฟล์ไบนารีเพื่อเขียนข้อความธรรมดา
Johnsyweb

961

คุณควรใช้print()ฟังก์ชั่นที่มีให้ตั้งแต่ Python 2.6+

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

สำหรับ Python 3 คุณไม่จำเป็นต้องใช้importเนื่องจาก print()ฟังก์ชั่นเป็นค่าเริ่มต้น

ทางเลือกอื่นคือใช้:

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

การอ้างอิงจากเอกสาร Pythonเกี่ยวกับการขึ้นบรรทัดใหม่:

บนเอาต์พุตถ้าขึ้นบรรทัดใหม่คือ None '\n'อักขระใด ๆ ที่เขียนจะถูกแปลเป็นตัวคั่นบรรทัดดีฟอลต์ของระบบ, os.linesep. หากขึ้นบรรทัดใหม่จะ''ไม่มีการแปลเกิดขึ้น หากการขึ้นบรรทัดใหม่เป็นค่าทางกฎหมายอื่นใด ๆ'\n'อักขระใด ๆ ที่เขียนจะถูกแปลเป็นสตริงที่กำหนด


35
-1 "ถ้าคุณต้องการให้แน่ใจว่าเพิ่ม os.linesep ลงในสตริงแทน\n" จะต้องมี newline = "" มิฉะนั้นคุณจะได้รับ\r\r\nบน Windows ไม่มีเหตุผลที่จะพูดถึงเรื่อง os.linesep เลย
John Machin

7
@ โซริน: การแก้ไขเพื่อเพิ่มโหมดการเขียนของคุณเป็นการปรับปรุง อย่างไรก็ตามคุณยังคงแปลกใจเกี่ยวกับ os.linesep ดูคำตอบของฉัน โดยวิธีการที่เอกสารที่คุณพูดสำหรับ 3.x แต่ส่วนนี้ยังเป็นที่ถูกต้องสำหรับ 2.x ในโหมดข้อความ: อักขระ '\ n' เขียนแปลงคั่นบรรทัดเริ่มต้นระบบ os.linesep * .. Windows: การเขียน os.linesep เหมือนกับการเขียน\r\nที่มีการ\nแปลเป็น os.linesep ซึ่งเป็น\r\nผลลัพธ์ที่\r\r\nได้
John Machin

7
@ John คุณพูดถูกฉันแก้ไขข้อผิดพลาด os.linesep ขอบคุณ
sorin

3
สำหรับการผนวกไม่ได้open('myfile','a')แทนopen('myfile','w')?
NeDark

6
@BradRuderman นั่นเป็นส่วนหนึ่งของมาตรฐานPOSIXสำหรับสิ่งที่ถือเป็น "บรรทัด" ในไฟล์ข้อความนั่นคือทุกบรรทัดในไฟล์ข้อความจะต้องถูกยกเลิกโดยการขึ้นบรรทัดใหม่แม้แต่บรรทัดสุดท้าย
เลอ

116

เอกสารหลามแนะนำวิธีนี้:

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

ดังนั้นนี่คือวิธีที่ฉันมักจะทำ :)

คำชี้แจงจากdocs.python.org :

เป็นวิธีปฏิบัติที่ดีที่จะใช้คำหลัก'พร้อม'เมื่อจัดการกับวัตถุไฟล์ นี่เป็นข้อได้เปรียบที่ไฟล์ถูกปิดอย่างถูกต้องหลังจากชุดไฟล์เสร็จสิ้นแม้ว่าจะมีข้อยกเว้นเกิดขึ้น นอกจากนี้ยังสั้นกว่าการเขียนบล็อกลองในที่สุดเทียบเท่า


1
ฉันไม่ชอบวิธีนี้เมื่อฉันต้องการที่จะซ้อนwithด้านในของวง นั่นทำให้ฉันเปิดอย่างต่อเนื่องและปิดไฟล์ขณะที่ฉันดำเนินการต่อไป บางทีฉันอาจจะพลาดบางสิ่งบางอย่างที่นี่หรือนี่เป็นข้อเสียจริงในสถานการณ์นี้โดยเฉพาะ?
การพนัน Sibbs

38
วิธีการเกี่ยวกับการวนรอบภายในด้วยหรือไม่
j7nn7k

@ j7nn7k เพื่อรับสายใน fd:
momstouch

86

เกี่ยวกับ os.linesep:

นี่คือเซสชันล่าม Python 2.7.1 ที่ไม่ได้แก้ไขบน Windows:

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:

เป็นที่คาดหวัง os.linesep ไม่ไม่'\n'ผลิตผลเช่นเดียวกับ ไม่มีทางที่มันจะให้ผลลัพธ์ที่เหมือนกัน 'hi there' + os.linesepเทียบเท่ากับ'hi there\r\n'ซึ่งเป็นไม่'hi there\n'เทียบเท่ากับ

ง่ายมาก: ใช้งาน\nซึ่งจะแปลโดยอัตโนมัติเป็น os.linesep และมันก็ง่ายมากตั้งแต่พอร์ตแรกของ Python ไปยัง Windows

ไม่มีจุดในการใช้ os.linesep บนระบบที่ไม่ใช่ของ Windows และจะสร้างผลลัพธ์ที่ไม่ถูกต้องบน Windows

ห้ามใช้ os.linesep!


ตัวอย่างที่ดี - อยากรู้ว่าถ้าคุณเป็นผู้ใช้ ipython? ฟังก์ชั่นที่ดีสำหรับการจัดรูปแบบเซสชัน
Alvin

ฉันไม่แน่ใจว่าคุณกำลังพยายามบอกอะไรกับเราที่นี่ os.linesep จะส่งคืนอักขระบรรทัดคำ (หรือสตริง) ตามที่กำหนดโดยระบบปฏิบัติการ Windows ใช้ \ r \ n สำหรับการสิ้นสุดบรรทัดโดยค่าเริ่มต้น อย่างไรก็ตามมีการรับรู้ \ n หนึ่งรายการ การใช้ \ n กำลังจะให้ OUTPUT แบบพกพาอย่างเต็มที่ แต่ os.linesep ไม่ผิดกับ windows
Gusdor

5
@Gusdor: ประเด็นคือถ้าคุณใช้งานos.linesepWindows ในโหมดข้อความอย่างชัดเจนผลลัพธ์\r\r\nจะผิด "Windows ใช้ ... " ไม่มีความหมาย C runtime library (และ Python นั้น) แปล\nเป็น\r\non output ใน text mode ซอฟต์แวร์อื่นอาจทำงานแตกต่างกัน ไม่ใช่กรณีที่ซอฟต์แวร์ทั้งหมดที่ทำงานบน Windows รับรู้โดด ๆ\nว่าเป็นตัวคั่นบรรทัดเมื่ออ่านในโหมดข้อความ Python ทำ เครื่องมือแก้ไขข้อความ Notepad ของ Microsoft ไม่ได้
John Machin

6
เนื้อหาที่คนอื่นจะอ่านมันไม่ใช่คุณกับบางซอฟแวร์มิกกี้เมาส์ที่จะ barf เกี่ยวกับการพิเศษ\r...
จอห์นเมชิน

2
@Gusdor คุณกำลังเข้าสู่ภาษาไพ ธ อนจากภาษาอื่นโดยการใช้ '\ n' ผลลัพธ์เป็นผลลัพธ์ของ '\ n' บนหน้าต่างแทนที่จะเป็น '\ r \ n' - ดังนั้นมันจึงขาด '\ r' ที่คาดหวังโดยใบ้ บรรณาธิการข้อความ? ดังที่จอห์นบอกว่านั่นไม่ใช่วิธีที่ Python ทำงาน - '\ n' จะถูกแทนที่ด้วย '\ r \ n' โดยอัตโนมัติถ้านั่นคือสิ่งที่ os.linesep บอกว่าต้องทำ ดังนั้นอย่างชัดเจนบอกว่าos.linesep เป็น "ผิด" ที่นี่ Department of Redundancy Departmentเหมือน ใช่คุณสามารถทำได้ ไม่คุณไม่ต้องการ
ToolmakerSteve

55

ฉันไม่คิดว่าจะมีวิธี "ถูกต้อง"

ฉันจะใช้:

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

ใน Memoriam ทิม Toady


แต่ OP อาจต้องการเขียนข้อมูลเพิ่มเติมลงในไฟล์ ที่นี่ไฟล์จะถูกปิดเมื่อwithขอบเขตออกไป
Keith

ที่อาจต้องการที่จะเป็นหรือแม้กระทั่งopen(..., 'a') 'at'
mtrw

5
เอ่อใช่ นั่นคือแนวคิดของการใช้กับ หากคุณต้องการที่จะเก็บไฟล์ที่เปิดเพียงโทรเปิดที่จุดเริ่มต้นและปิดโทรศัพท์เมื่อคุณทำ ...
hyperboreus

1
@mtrw จริง OP กำลังต่อท้าย
Hyperboreus

1
ส่วนที่เกี่ยวกับไพ ธ อนนั้นก็คือ RIP Tim Toady - และถูกต้องตามกฎหมายมาก
Mr_and_Mrs_D

21

ใน Python 3 มันเป็นฟังก์ชั่น แต่ใน Python 2 คุณสามารถเพิ่มสิ่งนี้ไว้ที่ด้านบนของไฟล์ต้นฉบับ:

from __future__ import print_function

จากนั้นคุณทำ

print("hi there", file=f)

17

หากคุณกำลังเขียนข้อมูลจำนวนมากและความเร็วเป็นสิ่งที่คุณควรคำนึงf.write(...)ถึง ฉันทำการเปรียบเทียบความเร็วอย่างรวดเร็วและเร็วกว่าprint(..., file=f)เมื่อเขียนเป็นจำนวนมาก

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)

โดยเฉลี่ยwriteแล้วเสร็จใน 2.45s บนเครื่องของฉันในขณะที่printใช้เวลานานประมาณ 4 เท่า (9.76 วินาที) ที่ถูกกล่าวว่าในสถานการณ์จริงส่วนใหญ่สิ่งนี้จะไม่เป็นปัญหา

หากคุณเลือกที่จะไปกับprint(..., file=f)คุณอาจจะพบว่าคุณต้องการระงับการขึ้นบรรทัดใหม่เป็นครั้งคราวหรือแทนที่ด้วยอย่างอื่น สิ่งนี้สามารถทำได้โดยการตั้งค่าendพารามิเตอร์ทางเลือกเช่น;

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

วิธีใดที่คุณเลือกฉันจะแนะนำให้ใช้withเนื่องจากจะทำให้อ่านง่ายขึ้น

อัปเดต : ความแตกต่างของประสิทธิภาพนี้อธิบายได้จากข้อเท็จจริงที่writeมีบัฟเฟอร์สูงและส่งคืนก่อนที่การเขียนไปยังดิสก์จะเกิดขึ้นจริง (ดูคำตอบนี้ ) ในขณะที่print(อาจ) ใช้การบัฟเฟอร์บรรทัด การทดสอบอย่างง่ายสำหรับสิ่งนี้คือการตรวจสอบประสิทธิภาพสำหรับการเขียนแบบยาวเช่นกันโดยที่ข้อเสีย (ในแง่ของความเร็ว) สำหรับการบัฟเฟอร์บรรทัดจะเด่นชัดน้อยกว่า

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

ความแตกต่างที่ผลการดำเนินงานในขณะนี้จะกลายเป็นมากน้อยเด่นชัดกับเวลาเฉลี่ยของการ 2.20s สำหรับwriteและ 3.10s printสำหรับ หากคุณจำเป็นต้องเชื่อมสตริงจำนวนมากเพื่อให้ประสิทธิภาพการทำงานของสาย Loooong นี้แย่ลงดังนั้นกรณีการใช้งานที่printมีประสิทธิภาพมากขึ้นนั้นค่อนข้างหายาก


10

ตั้งแต่ 3.5 คุณสามารถใช้pathlibเพื่อวัตถุประสงค์ดังกล่าว:

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

เปิดไฟล์ที่ชี้ไปที่ในโหมดข้อความเขียนข้อมูลลงไปและปิดไฟล์:

import pathlib

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

5

เมื่อคุณพูด Line หมายถึงอักขระบางตัวที่ต่อเนื่องกันซึ่งลงท้ายด้วยอักขระ '\ n' บรรทัดควรอยู่ในบางจุดดังนั้นเราควรพิจารณา '\ n' ที่ท้ายบรรทัดแต่ละบรรทัด นี่คือทางออก:

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

ในโหมดต่อท้ายหลังจากที่แต่ละเคอร์เซอร์เขียนย้ายไปยังบรรทัดใหม่หากคุณต้องการใช้wโหมดคุณควรเพิ่ม\nอักขระที่ท้ายwrite()ฟังก์ชั่น:

the_file.write("Hello\n")

1
"ในโหมดต่อท้ายหลังจากเขียนเคอร์เซอร์แต่ละครั้งจะย้ายไปยังบรรทัดใหม่" - ไม่เลย
เซ

3

ท่านสามารถใช้ioโมดูลดังต่อไปนี้ใน:

import io
my_string = "hi there"

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

1

เพื่อเขียนข้อความในไฟล์ในขวดสามารถใช้:

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

0

คุณยังสามารถลอง filewriter

pip install filewriter

from filewriter import Writer

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

เขียนลงไป my_file.txt

ใช้การทำซ้ำหรือวัตถุที่มี__str__การสนับสนุน


0

เมื่อฉันต้องการเขียนบรรทัดใหม่มากฉันกำหนดแลมบ์ดาที่ใช้printฟังก์ชั่น:

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

วิธีนี้มีประโยชน์ที่จะสามารถใช้คุณสมบัติทั้งหมดที่มีอยู่ในprintฟังก์ชั่น

อัปเดต:ตามที่จอร์จเอ่ยถึงในส่วนความคิดเห็นเป็นไปได้ที่จะปรับปรุงความคิดนี้เพิ่มเติมด้วยpartialฟังก์ชั่น:

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

IMHO นี่เป็นวิธีที่ใช้งานได้ดีกว่าและมีความลับน้อยกว่า


2
หรืออื่น (อาจจะทำความสะอาด) from functools import partial; fwl = partial(print, file=out)วิธีการที่จะเขียนนี้:
จอร์จ

@Georgy วิธีการของคุณดีมากจนสามารถได้รับคำตอบใหม่
MxNx

1
แนวคิดนี้เหมือนกันกับคุณเพียงแค่การนำไปใช้นั้นแตกต่างกันเล็กน้อย หากคุณต้องการคุณสามารถเพิ่มในการแก้ไขคำตอบของคุณ ฉันสบายดี
Georgy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.