15. 입력과 출력

프로그램을 만들다 보면 간혹 프로그램이 사용자와 상호 작용을 해야 할 때가 있습니다. 예를 들어, 사용자로부터 뭔가를 입력받고 처리 결과를 출력하는 일입니다. raw_input() 함수와 print 문으로 이를 구현할 수 있습니다.

결과를 출력하는 데 str(문자열) 클래스가 제공하는 여러 메소드를 사용할 수도 있습니다. 예를 들면, rjust 메소드를 사용하여 출력될 문자열이 특정 폭의 문자열 안에서 오른쪽 정렬이 되도록 할 수 있습니다. help(str)을 실행하여 str이 제공하는 여러 메소드에 대해 살펴보기 바랍니다.

또 다른 입/출력 형식은 파일을 다루는 것입니다. 파일을 생성하고, 읽고, 쓰는 것은 많은 프로그램에서 중요한 부분을 차지하고 있습니다. 이 장에서도 이러한 기능에 대해 좀 더 깊이 살펴볼 것입니다.


15.1 사용자로부터 입력받기


https://github.com/swaroopch/byte-of-python/blob/master/programs/io_input.py

def reverse(text):
    return text[::-1]

def is_palindrome(text):
    return text == reverse(text)

something = raw_input("Enter text: ")
if is_palindrome(something):
    print "Yes, it is a palindrome"
else:
    print "No, it is not a palindrome"
io_input.py(이 코드를 io_input.py로 저장하세요)

실행 결과는 다음과 같습니다.

$ python io_input.py
Enter text: sir
No, it is not a palindrome

$ python io_input.py
Enter text: madam
Yes, it is a palindrome

$ python io_input.py
Enter text: racecar
Yes, it is a palindrome


문자열을 뒤집기 위해서는 슬라이스를 사용합니다. 앞서 보았듯이 12.5 열거형의 슬라이스 기능을 이용하여 seq[a:b]와 같은 코드를 통해 위치 a부터 위치 b까지 문자열을 얻을 수 있습니다. 슬라이스 숫자에 세 번째 인수를 넘겨 슬라이스 스텝을 지정할 수 있습니다. 스텝을 지정하지 않으면 기본값 1이 지정되며, 이 경우 지정된 문자열을 차례로 슬라이스하는 것을 의미합니다. 음의 스텝을 지정하면 열거형의 마지막부터 반대 방향으로 슬라이스가 진행되며, 예를 들어 -1을 지정하면 뒤집혀진 문자열이 반환됩니다.

raw_input() 함수는 인수로 넘겨받은 문자열을 화면에 표시합니다. 그리고 나서는 사용자가 무언가를 입력하고 Enter 키를 누를 때까지 기다립니다. 사용자가 입력을 마치고 Enter 키를 누르면 raw_input() 함수는 사용자가 입력한 내용을 문자열로 반환합니다.

이제 이 문자열을 받아서 뒤집어 줍니다. 여기서 뒤집혀진 문자열이 뒤집혀지지 않았을 때의 문자열과 같으면, 이를 영어로 palindrome이라고 부릅니다.


15.1.1 연습 문제

어떤 문자열이 palindrome인가는 그 안에 포함된 문장 부호와 공백을 제외한 문자를 가지고만 판단해야 합니다. 예를 들어, "Rise to vote, sir." 은 palindrome이지만 위 예제 프로그램은 이것은 palindrome이 아니라고 판단할 것입니다. 15.1 프로그램을 고쳐서 이러한 문자열을 palindrome으로 인식하도록 수정해 보기 랍니다.

너무 어렵다고요? 힌트01를 참고하기 바랍니다.


01 튜플을 사용하여 (필요한 모든 문장 부호들은 여기에 있습니다.) 필요 없는 문자 문자를 담습니다. 멤버십 테스트를 통해 각 문자가 제거되어야 하는지 여부를 판단할 때 사용하시기 바랍니다. 즉, forbidden = (!?., …​) 와 같이 튜플을 만드세요.



15.2 파일 입/출력

입/출력을 위해 파일을 열고 사용하려면 file 클래스의 객체를 생성한 후 readreadlinewrite와 같은 메소드를 적절히 사용하면 됩니다. 파일을 열때 파일을 읽는 모드와 쓰는 모드를 따로 지정할 수 있습니다. 마지막으로 파일을 읽거나 쓰는 일을 모두 마친 후에는 close 메소드를 호출하여 파이썬에게 그 파일을 다 사용했다는 것을 알려주어야 합니다.


https://github.com/swaroopch/byte-of-python/blob/master/programs/io_using_file.py

poem = '''\
Programming is fun
When the work is done
if you wanna make your work also fun:
    use Python!
'''

# Open for 'w'riting
f = open('poem.txt', 'w')
# Write text to file
f.write(poem)
# Close the file
f.close()

# If no mode is specified,
# 'r'ead mode is assumed by default
f = open('poem.txt')
while True:
    line = f.readline()
    # Zero length indicates EOF
    if len(line) == 0:
        break
    # The `line` already has a newline
    # at the end of each line
    # since it is reading from a file.
    print line,
# close the file
f.close()
io_using_file.py(이 코드를 io_using_file.py로 저장하세요)

실행 결과는 다음과 같습니다.

$ python io_using_file.py
Programming is fun
When the work is done
if you wanna make your work also fun:
    use Python!


먼저, 내장 함수 open을 이용하여 파일을 엽니다. 이때 파일을 어떤 용도로 사용할 것인지도 함께 지정합니다. 각 모드로는 읽기 모드('r'), 쓰기 모드('w'), 덧붙임 모드('a')가 있습니다. 또한 우리가 다룰 파일을 일반적인 텍스트 모드('t') 로 다룰지 또는 바이너리 모드 ('b') 로 다룰지 여부도 함께 지정할 수 있습니다. 이외에도 여러 가지 다른 모드가 있으며, help(open)을 통해 그 목록을 확인할 수 있습니다. 모드에 아무것도 지정하지 않으면, open()은 기본적으로 파일을 텍스트('t’ext) 모드의 읽기('r’ead) 모드로 파일을 열어줍니다.

이 예제에서는 먼저 파일을 쓰기/텍스트 모드로 열고 파일 객체의 write 메소드를 사용하여 파일에 데이터를 쓴 후 close로 파일을 닫습니다.

그런 다음, 똑같은 파일을 이번에는 읽기 모드로 엽니다. 이때 아무 모드도 지정하지 않으면 기본값인 '읽기/텍스트 모드'가 지정됩니다. 파일을 연 후에는 반복문을 이용하여 파일의 readline 메소드를 통해 파일의 내용을 한 줄씩 읽어옵니다. 이 메소드는 파일 내용을 읽다가 줄바꿈 문자를 만날 때까지 한 줄을 읽어서 그 모든 내용을 반환합니다. 만약  문자열이 반환되었을 경우, 이것은 파일의 끝을 의미하므로 'break' 문을 통해 반복문을 빠져나갑니다.

마지막으로, close 문으로 파일을 닫습니다.

이제 poem.txt 파일을 직접 열어 예제 프로그램이 올바른 내용을 쓰고 읽었는지 확인해보기 바랍니다.


15.3 Pickle

파이썬은 pickle이라고 불리우는 기본 모듈을 제공하는데, 이것은 어떤 파이썬 객체이든지 파일로 저장했다가 나중에 불러와서 사용하기 위한 모듈입니다. 이를 "객체를 영구히 저장한다"고 합니다.


https://github.com/swaroopch/byte-of-python/blob/master/programs/io_pickle.py

import pickle

# The name of the file where we will store the object
shoplistfile = 'shoplist.data'
# The list of things to buy
shoplist = ['apple', 'mango', 'carrot']

# Write to the file
f = open(shoplistfile, 'wb')
# Dump the object to a file
pickle.dump(shoplist, f)
f.close()

# Destroy the shoplist variable
del shoplist

# Read back from the storage
f = open(shoplistfile, 'rb')
# Load the object from the file
storedlist = pickle.load(f)
print storedlist
io_pickle.py(이 코드를 io_pickle.py로 저장하세요)

실행 결과는 다음과 같습니다.

$ python io_pickle.py
['apple', 'mango', 'carrot']


파일에 객체를 저장하기 위해 먼저 open 문을 이용하여 쓰기/바이너리 모드로 파일을 열은 후 pickle 모듈의 dump 함수를 호출합니다. 이 과정을 피클링pickling이라고 합니다.

다음으로 pickle 모듈의 load 함수를 이용하여 파일에 저장된 객체를 불러옵니다. 이 과정을 언피클링unpickling이라고 합니다.


15.4 유니코드

지금까지 우리가 문자열을 쓰거나 읽고, 또 파일에 쓸 때에는 영어 알파벳 문자를 주로 사용했습니다. 만약 여러분이 영어가 아닌 다른 언어로 된 문자를 읽고 쓰고 싶을 경우에는 unicode 형식을이용해야 하며, 이는 문자 u를 앞에 붙여 지정할 수 있습니다.

>>> "hello world"
'hello world'
>>> type("hello world")
<type 'str'>
>>> u"hello world"
u'hello world'
>>> type(u"hello world")
<type 'unicode'>


비 영어권 언어를 다룰 때에는 str 대신 unicode 형식을 사용하여 문자를 다루어야 합니다. 그러나 여러분이 파일을 읽고 쓰거나 인터넷 상의 다른 컴퓨터와 교신하려고 할 때에는 유니코드 문자열을 송수신 가능한 형태로 바꿔야 하며, 그 형식을 UTF-8이라고 부릅니다. 다음과 같이 open 표준 함수에 간단한 키워드 인수를 넘겨주어 UTF-8 형식을 사용하여 파일을 읽고 쓸 수 있습니다.

# encoding=utf-8
import io

f = io.open("abc.txt", "wt", encoding="utf-8")
f.write(u"Imagine non-English language here")
f.close()

text = io.open("abc.txt", encoding="utf-8").read()
print text


 import 문에 대해서는 11. 모듈 장에서 살펴봤으므로 설명을 생략합니다.

이 코드처럼 유니코드 문자가 포함된 프로그램을 작성할 때에는 반드시 파이썬에게 이 프로그램이 UTF-8 형식을 사용하여 작성됐음을 알려줘야 합니다. 프로그램의 맨 윗줄에 # encoding=utf-8과 같이 주석을 한 줄 입력하면 됩니다.

io.open 문을 사용할 때에는 "encoding" 과 "decoding" 인수를 넘겨서 파이썬에게 유니코드를 사용할 것임을 알려주고, 또 문자열을 넘겨 줄 때에는 u"" 와 같이 명시하여 유니코드 문자열임을 알려줘야 합니다.

다음 글들을 읽어 보시면 더 많은 것들을 배울 수 있을 것입니다:

15.5 요약

지금까지 여러 종류의 입/출력 및 파일을 다루는 법과 pickle 모듈을 다루는 법 그리고 유니코드에 대해 배웠습니다. 다음으로는 예외 처리의 개념에 대해 알아봅니다.