파일 입출력
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
mode
"r" | 읽기 |
"w" | 쓰기 |
"x" | 생성 전용 열기. 파일이 이미 있는 경우 에러 발생 |
"a" | 쓰기. 파일 끝에 추가 |
"b" | 바이너리 모드 열기 |
"t" | 텍스트 모드 열기 |
"+" | 읽기 쓰기 |
파일 쓰기
f = open("test.txt", "wt", encoding='utf-8')
print(type(f))
f.write("안녕하세요!")
f.close()
위 코드를 실행하면 현재 소스코드가 있는 위치에 txt 파일이 생성된다.
텍스트를 영어로 쓰면 아무 문제도 일어나지 않지만 이외의 언어로 작성하면 인코딩 문제가 생긴다. encoding에 인자를 넘겨주지 않으면 txt 편집기(메모장)의 기본 인코딩 타입이 ANSI이기 때문에 메모장으로 열었을 때는 정상적으로 뜨지만 PyCharm이나 다른 여러 가지 환경에서는 글자가 깨진다.
인코딩 종류에는 여러가지가 있는데 그 중에서 많이 쓰는 것이 아스키 코드와 Unicode이다.
유니코드는 국제 표준 규격이고 전 세계 언어가 표현 가능하다. utf-8은 아스키코드와 호환이 된다.
특정 위치에 파일을 만드려면 다음과 같이 경로를 함께 쓰면 된다. 주의할 점은 파일 탐색기에서 복사한 경로를 그대로 사용하면 안 되고 폴더를 구분하는 부분을 수정해야 한다는 것이다. 원래 역슬래쉬는 escape sequence를 나타내기 때문이다.
f = open("C:/Users/Public/PythonStudy/test.txt", "wt", encoding='utf-8')
print(type(f))
f.write("안녕하세요!")
f.close()
위와 같이 역슬래쉬(\)를 슬래쉬(/)로 바꾸거나
f = open("C:\\Users\\Public\\PythonStudy\\test.txt", "wt", encoding='utf-8')
print(type(f))
f.write("안녕하세요!")
f.close()
위와 같이 escape sequence인 역슬래쉬를 한 번 더 쓰면 된다.
절대경로(absolute path): 가장 최상단 폴더부터 시작해 (root를 기준으로) 경로 작성
e.g. C:\\Users\\Public\\PythonStudy\\test.txt
상대경로(relative path): 프로그램이 구동되는 폴더를 기준으로 경로 작성
e.g. ./test.txt, ../test.txt
test.txt의 경우는 ./가 생략된 것이다.
파일 읽기
정수 배열을 파일로 작성하고 다시 읽어와 정수 배열에 저장하는 프로그램이다.
In:
f = open("C:/Users/Public/PythonStudy/test.txt", "w+t", encoding="utf-8")
lt_num = [10, 23, 29, 33, 37, 40]
lt_num_str = ""
for i in lt_num:
lt_num_str += str(i) + " "
print(lt_num_str)
f.write(lt_num_str.rstrip())
data = f.readline()
print("Data: ")
print(data)
print("Offset: ")
print(f.tell())
f.seek(0)
data = f.readline()
print("Data:")
print(data)
lt_num_data = []
temp = data.split()
print(temp)
for i in temp:
lt_num_data.append(int(i))
print(lt_num_data)
f.close()
Out:
10 23 29 33 37 40
Data:
Offset:
17
Data:
10 23 29 33 37 40
['10', '23', '29', '33', '37', '40']
[10, 23, 29, 33, 37, 40]
readline은 파일에서 현재 오프셋에서부터 읽기 때문에 처음 data를 출력했을 때는 오프셋이 마지막으로 파일 작성이 끝난 부분에 있기 때문에 아무것도 읽어 오지 못했다.
seek을 사용해 파일의 가장 첫 부분에서 readline을 하도록 한다.
그리고 읽어온 문자열을 분할해 배열에 할당하면 문자열로 저장이 되는데 모든 요소를 int로 변환 후 배열에
위 코드를 함수를 호출해서 실행되도록 변경했다.
In:
def load_data(file):
f = open(file, "rt", encoding="utf-8")
data = f.readline()
print("Data:")
print(data)
lt_num_data = []
temp = data.split()
print(temp)
for i in temp:
lt_num_data.append(int(i))
print(lt_num_data)
f.close()
return lt_num_data
data = load_data("C:/Users/Public/PythonStudy/test.txt")
print("Succeeded to load data")
print(data)
Out:
Data:
10 23 29 33 37 40
['10', '23', '29', '33', '37', '40']
[10, 23, 29, 33, 37, 40]
Succeeded to load data
[10, 23, 29, 33, 37, 40]
코드를 잘 보면 load_data 함수 내부에도 data라는 변수가 있고 밑에서 세 번째 줄에도 data 변수가 있다. 언뜻 보면 data 변수를 재사용한 것처럼 보이지만 두 변수는 별개의 변수이다.
변수의 범위(scope)
- 지역(local) 변수: 모든 범위에서 사용 가능한 변수
- 전역(global) 변수: 특정 범위 내에서만 사용 가능한 변수
- 빌트인(built-in) 변수: 파이썬에서 이미 정의된 변수
위 코드를 PyCharm에서 작성했다면 load_data 내부의 변수 data에 밑줄이 생긴다. 커서를 올려 보면
Shadows name 'data' from outer scope
이라는 메시지가 뜬다. 이 상태로 실행해도 에러는 발생하지 않고 이름이 같은 두 변수를 다른 변수로 취급한다. 하지만 상황에 따라 함수 밖에서 선언한 변수를 함수 안에서도 사용해야 할 수도 있다.
data = []
global_scope_variable = "나는 전역 변수입니다!"
def load_data(file):
f = open(file, "rt", encoding="utf-8")
# print(data) # 변수 쉐도잉
print(global_scope_variable)
data = f.readline()
print("Data:")
print(data)
위와 같이 코드를 작성하면 print(global_scope_variable)은 실행이 가능하지만 print(data)에서는 에러가 발생한다.
이렇게 다른 변수로 인식되지만 같은 이름을 가진 경우를 변수 쉐도잉이라고 한다.
data와 global_scope_variable 모두 함수 외부에서 선언되었지만 data만 사용이 불가능한 이유는 print(data) 아래에 data에 값을 또 할당하기 때문에 data = []의 data와 data = f.readline()의 data를 별개의 변수로 인식한다. 별개의 변수인데 같은 범위에서 사용되면 구분이 되지 않기 때문에 함수 안에서 선언된 data는 (다른 언어와 마찬가지로) 함수 밖에서 사용할 수 없고 함수 밖에서 선언된 data는 (다른 변수 data가 선언된) 함수 안에서 사용할 수 없는 것이다.
함수 밖에서 선언된 data와 함수 안에서 사용되는 data를 같은 변수로 취급되게 하려면 global이라는 키워드를 사용하면 된다.
data = []
global_scope_variable = "나는 전역 변수입니다!"
def load_data(file):
f = open(file, "rt", encoding="utf-8")
global data
print(data)
print(global_scope_variable)
data = f.readline()
print("Data:")
print(data)
이제 변수 data를 함수 내부에서 재사용할 수 있게 되었다.
'파이썬 Python' 카테고리의 다른 글
초급 8 REST, JSON (0) | 2021.01.14 |
---|---|
초급 7 딕셔너리, 프로그램 설계 (0) | 2021.01.14 |
초급 5 문자열 (0) | 2021.01.13 |
초급 4 함수 정의, 문자열 (0) | 2021.01.13 |
초급 3 조건문, 반복문 (0) | 2021.01.11 |