14 장파일 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 14 장파일 1 / 18
학습내용 파일입출력예포멧연산자 (format operator) 파일명과경로예외처리하기피클링 (pickling) 파일입출력디버깅 박창이 ( 서울시립대학교통계학과 ) 14 장파일 2 / 18
파일입출력예 >>> fout = open( output.txt, w ) >>> print(fout) <_io.textiowrapper name= output.txt mode= w encoding= cp949 > >>> line1 = "This here s the wattle,\n" >>> fout.write(line1) 24 >>> line2 = "the emblem of our land.\n" >>> fout.write(line2) 24 >>> fout.close() 박창이 ( 서울시립대학교통계학과 ) 14 장파일 3 / 18
포맷연산자 I write 의인자는문자열임 x = 52 fout.write(str(x)) 문자열로변환하는대신포맷연산자 % 를사용 >>> camels = 42 >>> %d % camels 42 >>> I have spotted %d camels. % camels I have spotted 42 camels. %d: 정수, %g: 실수, %s: 문자열 >>> In %d years I have spotted %g %s. % (3, 0.1, camels ) In 3 years I have spotted 0.1 camels. 박창이 ( 서울시립대학교통계학과 ) 14 장파일 4 / 18
포맷연산자 II 타입과갯수가맞아야함 >>> %d %d %d % (1,2) Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> %d %d %d % (1,2) TypeError: not enough arguments for format string >>> %d % dollars Traceback (most recent call last): File "<pyshell#13>", line 1, in <module> %d % dollars TypeError: %d format: a number is required, not str 박창이 ( 서울시립대학교통계학과 ) 14 장파일 5 / 18
파일명과경로 I os.getcwd 함수는현재디렉토리명을반환함 >>> import os >>> cwd = os.getcwd() >>> print(cwd) C:\Users\Changyi\AppData\Local\Programs\Python\Python36 상대경로 (relative path) 는현재디렉토리로부터출발하며절대경로 (absolute path) 는루트디렉토리에서출발함. 파일의절대경로를찾기위해서 os.path.abspath 함수를이용할수있음 박창이 ( 서울시립대학교통계학과 ) 14 장파일 6 / 18
파일명과경로 II 여러가지함수들 >>> os.path.exists( output.txt ) True >>> os.path.isdir( output.txt ) False >>> os.listdir(cwd) [ DLLs, Doc, include, Lib, libs, LICENSE.txt, NEWS.txt, output.txt, python.exe, python3.dll, python36.dll, pythonw.exe, Scripts, tcl, Tools, vcruntime140.dll ] 박창이 ( 서울시립대학교통계학과 ) 14 장파일 7 / 18
파일명과경로 III 디렉토리의모든파일명을프린트함 ( 모든디렉토리에재귀호출 ) def walk(dirname): for name in os.listdir(dirname): path = os.path.join(dirname, name) if os.path.isfile(path): print(path) else: walk(path) 박창이 ( 서울시립대학교통계학과 ) 14 장파일 8 / 18
예외처리하기 try 는문제가발생한경우 except 실행하고아니면그대로실행됨 try: fin = fopen( bad_file ) for line in fin: print(line) fin.close() except: print( Something went wrong. ) 박창이 ( 서울시립대학교통계학과 ) 14 장파일 9 / 18
피클링 I pickle 모듈은임의의객체를데이터베이스에저장하기적합한문자열로변환및역변환을함 pickle.dumps 는객체를문자열로변환하는데읽을수있는형태는아님 >>> import pickle >>> t = [1, 2, 3] >>> s = pickle.dumps(t) >>> print(s) b \x80\x03]q\x00(k\x01k\x02k\x03e. 박창이 ( 서울시립대학교통계학과 ) 14 장파일 10 / 18
피클링 II pickle.loads 는객체를재구성하는데값은기존과동일하지만객체자체는다름 >>> t2 = pickle.loads(s) >>> print(t2) [1, 2, 3] >>> t == t2 True >>> t is t2 False 박창이 ( 서울시립대학교통계학과 ) 14 장파일 11 / 18
파일입출력 I 텍스트파일입출력 file_for_reading = open( filename.txt, r ) file_for_writing = open( filename.txt, w ) file_for_appending = open( filename.txt, a ) file_for_writing.close() with: 작업이끝나면파일을자동적으로닫음 with open( filename.txt, r ) as f: data = function_that_gets_data_from(f) # don t use f from now on process(data) 박창이 ( 서울시립대학교통계학과 ) 14 장파일 12 / 18
파일입출력 II 텍스트파일전체를반복적으로읽기 starts_with_hash = 0 with open( input.txt, r ) as f: for line in f: if re.match("^#", line) # check if a line starts with # starts_with_hash += 1 각줄마다이메일주소가하나씩있는파일을사용하여메일도메인에대한히스토그램그리기 def get_domain(email_address): """ @ 기준으로주소를자르고마지막부분을반환 """ return email_address.lower().split("@")[-1] with open( email_addresses.txt, r ) as f: domain_counts = Counter(get_domain(line.strip()) for line in f if "@" in line) 박창이 ( 서울시립대학교통계학과 ) 14 장파일 13 / 18
파일입출력 III 구분자가있는파일탭으로분리된파일 >>> import csv >>> def process(date, symbol, price): print(date, symbol, price) >>> with open( D:/Dropbox/ 데이터백업 /Lecture/2018 년 1 학기고급통계프로그래밍 / 코드 /tab_delimited_stock_prices.txt, r, encoding= utf8, newline= ) as f: reader = csv.reader(f, delimiter= \t ) # reader = csv.reader(codecs.iterdecode(f, utf-8 ), delimiter for row in reader: date = row[0] symbol = row[1] closing_price = float(row[2]) process(date, symbol, closing_price) 박창이 ( 서울시립대학교통계학과 ) 14 장파일 14 / 18
파일입출력 IV 6/20/2014 AAPL 90.91 6/20/2014 MSFT 41.68 6/20/2014 FB 64.5 6/19/2014 AAPL 91.86 6/19/2014 MSFT 41.51 6/19/2014 FB 64.34 박창이 ( 서울시립대학교통계학과 ) 14 장파일 15 / 18
파일입출력 V 콜론으로분리된파일 >>> with open( D:/Dropbox/ 데이터백업 /Lecture/2018 년 1 학기고급통계프로그래밍 / 코드 /colon_delimited_stock_prices.txt, r, encoding= utf8,newline= ) as f: reader = csv.dictreader(f, delimiter= : ) # reader = csv.dictreader(codecs.iterdecode(f, utf-8 ), delim for row in reader: date = row["date"] symbol = row["symbol"] closing_price = float(row["closing_price"]) process(date, symbol, closing_price) 6/20/2014 AAPL 90.91 6/20/2014 MSFT 41.68 6/20/2014 FB 64.5 박창이 ( 서울시립대학교통계학과 ) 14 장파일 16 / 18
파일입출력 VI csv.writer 를이용하여구분자있는파일생성 >>> today_prices = { AAPL : 90.91, MSFT : 41.68, FB : 64.5 } >>> with open( D:/Dropbox/ 데이터백업 /Lecture/2018 년 1 학기고급통계프로그래밍 / 코드 /comma_delimited_stock_prices.txt, w, encoding= ut writer = csv.writer(f, delimiter=, ) for stock, price in today_prices.items(): writer.writerow([stock, price]) 12 12 9 박창이 ( 서울시립대학교통계학과 ) 14 장파일 17 / 18
디버깅 파일입출력시공백, 탭, 줄바꾸기등은눈으로볼수없는데 rexpr 을이용하면백슬래시기호로표현하여시각적으로볼수있어디버깅에도움이됨 >>> s = 1 2\t 3\n 4 >>> print(s) 1 2 3 4 >>> print(repr(s)) 1 2\t 3\n 4 시스템에따라가령줄바꿈문자가 \r 혹은 \n 일수있음 박창이 ( 서울시립대학교통계학과 ) 14 장파일 18 / 18