Python-write () 대 writelines () 및 연결된 문자열


124

그래서 저는 파이썬을 배우고 있습니다. 레슨을 진행 중이며 각 사용자 입력 변수 (의 개체 ) 사이에 있는 동안 많은 수 target.write()를 단일으로 압축 write()해야하는 문제가 "\n"발생했습니다 write().

나는 다음을 생각 해냈다.

nl = "\n"
lines = line1, nl, line2, nl, line3, nl
textdoc.writelines(lines)

내가하려고하면 :

textdoc.write(lines)

오류가 발생합니다. 하지만 입력하면 :

textdoc.write(line1 + "\n" + line2 + ....)

그런 다음 잘 작동합니다. 줄 바꿈에 문자열을 사용할 수 없지만에서 사용할 수있는 이유 write()writelines()무엇입니까?

Python 2.7 Google을 검색했을 때 내가 찾은 대부분의 리소스는 내 머리 위에 있었지만 여전히 평신도입니다.


lines귀하의 예에서 문자열이 아닙니다. 6 개의 문자열로 구성된 튜플입니다.
Bachsau

답변:


147
  • writelines 반복 가능한 문자열이 필요합니다.
  • write 단일 문자열이 필요합니다.

line1 + "\n" + line2에 전달하기 전에 이러한 문자열을 단일 문자열로 병합합니다 write.

줄이 많은 경우를 사용할 수 있습니다 "\n".join(list_of_lines).


50
더 구체적으로, writelinesiterable을 기대합니다. 목록, 튜플 또는 생성기를 사용할 수 있습니다.
Mark Ransom 2012 년

대답 해주셔서 감사합니다. 문자열 목록을 만들고 .join (list)에 전달해야하는 이름 (list_of_lines)으로 가정하고 있습니다.
AbeLinkon

9
줄이 많은 경우 write대신 왜 사용해야 writelines합니까? Writelines는 임시로 연결된 문자열을 만들 필요가없고 줄을 반복하기 때문에 더 나은 성능을 발휘할 수 있습니다.
Bouke 2014 년

@ hBy2Py : 정확히 반대 : stackoverflow.com/a/6165711/281545
Mr_and_Mrs_D

1
단일 문자열도 Python에서 반복 가능합니다
natbusa

123

write ()에서 줄 바꿈에 문자열을 사용할 수 없지만 writelines ()에서 사용할 수있는 이유는 무엇입니까?

아이디어는 다음과 같습니다. 단일 문자열을 작성하려면 write(). 일련의 문자열이 있으면 다음을 사용하여 모두 쓸 수 있습니다.writelines() .

write(arg)인수로 문자열을 예상하고 파일에 씁니다. 문자열 목록을 제공하면 예외가 발생합니다 (그런데 오류를 표시합니다!).

writelines(arg)이터 러블을 인수로 예상합니다 (이터 러블 객체는 가장 일반적인 의미에서 튜플, 목록, 문자열 또는 반복자가 될 수 있습니다). 반복기에 포함 된 각 항목은 문자열이어야합니다. 문자열 튜플이 제공되었으므로 모든 것이 작동했습니다.

문자열의 특성은 두 함수 모두에 중요하지 않습니다. 즉, 사용자가 제공하는 파일에 기록합니다. 흥미로운 부분은 writelines()자체적으로 개행 문자를 추가하지 않기 때문에 메서드 이름이 실제로 매우 혼란 스러울 수 있다는 것입니다. 실제로라는 가상의 방법처럼 작동 write_all_of_these_strings(sequence)합니다.

다음은 파이썬에서 각 문자열을 자체 줄에 유지하면서 문자열 목록을 파일에 쓰는 관용적 방법입니다.

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.write('\n'.join(lines))

이렇게하면 파일이 닫힙니다. 이 구성 '\n'.join(lines)은 목록의 문자열을 연결 (연결) lines하고 문자 '\ n'을 접착제로 사용합니다. +연산자를 사용하는 것보다 더 효율적 입니다.

동일한 lines시퀀스 에서 시작 하여 동일한 출력으로 끝나지만 다음을 사용합니다 writelines().

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.writelines("%s\n" % l for l in lines)

이것은 생성기 표현식을 사용하고 개행으로 끝나는 문자열을 동적으로 생성합니다. writelines()이 문자열 시퀀스를 반복하고 모든 항목을 씁니다.

편집 : 알아야 할 또 다른 사항 :

write()그리고 readlines()전에 존재 writelines()도입되었다. writelines()나중에를 readlines()통해 읽은 파일 내용을 쉽게 작성할 수 있도록 의 대응으로 나중에 소개되었습니다 readlines().

outfile.writelines(infile.readlines())

writelines이름이 그렇게 헷갈리는 주된 이유가 바로 이것이다 . 또한 오늘날 우리는 더 이상이 방법을 사용하고 싶지 않습니다. 데이터 쓰기 readlines()writelines()시작하기 전에 전체 파일을 컴퓨터의 메모리로 읽습니다 . 우선, 이것은 시간을 낭비 할 수 있습니다. 다른 부분을 읽는 동안 데이터의 일부를 쓰기 시작하지 않겠습니까? 그러나 가장 중요한 것은이 접근 방식이 메모리를 많이 소비 할 수 있다는 것입니다. 입력 파일이 컴퓨터의 메모리보다 큰 극단적 인 시나리오에서는이 방법이 작동하지 않습니다. 이 문제에 대한 해결책은 반복자 만 사용하는 것입니다. 실제 예 :

with open('inputfile') as infile:
    with open('outputfile') as outfile:
        for line in infile:
            outfile.write(line)

입력 파일을 한 줄씩 읽습니다. 한 줄을 읽는 즉시이 줄이 출력 파일에 기록됩니다. 개략적으로 말하면 메모리에는 항상 한 줄만 있습니다 (readlines / writelines 접근 방식의 경우 메모리에있는 전체 파일 내용과 비교).


5
@AbeLinkon : 나는이 결론을지지하지 않을 것입니다. write()writelines()기본적으로 동일하고 그들의 사용은 개인 취향의 문제이다. 그러나 매우 긴 문자열 목록 (이라고 함 lines)의 경우 작성하는 f.write('\n'.join(lines))것이 for l in line: f.write('%s\n' % l). 첫 번째 경우에는 쓰기 전에 완전히 새롭고 매우 긴 문자열이 메모리에 생성됩니다. 두 번째 경우에는 데이터가 조각별로 기록됩니다.
박사 1 월 필립 Gehrcke

3
f.write ( '\ n'.join (lines)) 실행했을 때 마지막 nl을 추가하지 않았습니다.
Jiminion 2013-07-26

5
물론 그렇게하지 않을 outf.writelines(inf.readlines())outf.writelines(inf)입니다. 우리는 더 이상 사용하지 않는 기능은 readlines()없습니다 writelines().
moooeeeep

2
@moooeeeep :의 기능 / 구현에 잘못된 것은 없지만 writelines()설명 된대로 의미론은 이상적이지 않습니다. 이것이 내가 한 번도 사용하지 않은 이유입니다. 그리고 나는 그것을 놓친 적이 없습니다.
Dr. Jan-Philip Gehrcke

2
@AbeLinkon가 - 어쩌면 당신은 더 나은 원래 허용 된 것보다 분명히,이 답변을 받아 들일 생각한다
피터 M. - 모니카의 약자

-4

목록을 저장하고로드하려면 Pickle을 사용 해보세요.

피클 저장 :

with open("yourFile","wb")as file:
 pickle.dump(YourList,file)

및로드 :

with open("yourFile","rb")as file:
 YourList=pickle.load(file)

-5

사실 문제는 변수 "라인"이 나쁘다는 것입니다. 라인을 튜플로 정의했지만 write ()에는 문자열이 필요하다고 생각합니다. 쉼표를 플러스 (+)로 바꾸면됩니다.

nl = "\n"
lines = line1+nl+line2+nl+line3+nl
textdoc.writelines(lines)

작동합니다.


-5

Zed Shaw의 책에서 운동 16? 다음과 같이 이스케이프 문자를 사용할 수 있습니다.

paragraph1 = "%s \n %s \n %s \n" % (line1, line2, line3)
target.write(paragraph1)
target.close()

매우 약한 솔루션입니다. 이러한 방식으로 여러 줄을 연결하려면 다음과 같이해야합니다 " \n ".join((line1, line2, line3))..
Bachsau
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.