os 모듈

on under python
15 minute read

1. 다양한 함수들

(1) getcwd 함수 - 현재 Python이 작업 중인 디렉터리를 부여줌

>>> import os
>>> os.getcwd()
'/Users/dokyungkim'

(2) chdir 함수 - 현재 작업 디렉터리를 변경하는 함수

>>> os.getcwd()
'/Users/dokyungkim'
>>> os.chdir("/Users/dokyungkim/temp/")
>>> os.getcwd()
'/Users/dokyungkim/temp'

(3) listdir 함수 - 입력한 경로의 파일과 폴더 목록을 리스트로 반환해 주는 함수

>>> os.listdir("/Users/dokyungkim/")
['.atom', '.bash_history', '.bash_profile', '.bashrc', '.bundle', '.CFUserTextEncoding', '.config', '.DS_Store', '.gem', '.gitconfig', '.lesshst', '.matplotlib', '.mplayer', '.oh-my-zsh', '.pyenv', '.python_history', '.sqlite_history', '.ssh', '.Trash', '.vim', '.viminfo', '.wget-hsts', '.zcompdump-DoKyung의 MacBook Pro-5.2', '.zprofile', '.zsh-update', '.zsh_history', '.zshrc', 'Applications', 'Desktop', 'Documents', 'doky', 'Downloads', 'Git', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'temp']

위와 같이 지정된 디렉터리에 있는 내용들이 한꺼번에 출력되어 보기가 불편합니다. 그래서 for문을 사용해서 보기 좋게 변경할 수 있습니다.

>>> for name in os.listdir("/Users/dokyungkim/"):
...     print(name)
...
.atom
.bash_history
# 이하 생략

(4) mkdir 하수 - 폴더를 만들어주는 함수

>>> os.getcwd()
'/Users/dokyungkim/temp'
>>> os.mkdir("/Users/dokyungkim/temp/test/")
>>> for name in os.listdir("/Users/dokyungkim/temp/"):
...     print(name)
...
test

(5) makedirs 함수 - 폴더를 만들어 주는 함수(하위폴더포함)

mkdir함수와 비슷하지만 mkdir함수는경로의 제일 마지막에 적힌 하나의 폴더만 생성하지만 makedirs함수는 시작부터 끝까지 모든 폴더를 만들어 줍니다.
유닉스의 mkdir-p 옵션돠 동일합니다.

>>> os.makedirs("/Users/dokyungkim/temp/dir1/dir2/dir3/")
>>> os.listdir("/Users/dokyungkim/temp/")
['dir1', 'test']

생성하려는 폴더가 이미 존재할 경우 에러가 발생합니다.

removeunlink함수는 같은 역할을 하는 함수입니다.

~/temp » ls
dir1     test     test.txt

# python
>>> os.remove("/Users/dokyungkim/temp/test.txt")

~/temp » ls
dir1 test

unlink도 동일한 동작을 합니다.

~/temp » ls
dir1     test     test.txt

# python
>>> os.unlink("/Users/dokyungkim/temp/test.txt")

~/temp » ls
dir1 test

(7) rmdir, removedirs 함수 - 폴더(디렉터리)를 삭제하는 함수

~/temp » ls
dir1 test

# python
>>> os.rmdir("/Users/dokyungkim/temp/dir1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 66] Directory not empty: '/Users/dokyungkim/temp/dir1'

기본적으로 rmdir 명령으로 삭제할 수 있지만 해당 디렉터리 안에 내용이 있다면 위와 같은 에러가 발생합니다. 안에 내용을 모두 삭제 후 진행하면 에러 없이 진행되는 것을 확인 할 수 있습니다.

~/temp/dir1/dir2 » pwd
/Users/dokyungkim/temp/dir1/dir2
~/temp/dir1/dir2 » ls
dir3

# python
>>> os.rmdir("/Users/dokyungkim/temp/dir1/dir2/dir3")
# 빈 폴더를 삭제할 수 있습니다.

~/temp/dir1/dir2 » ls

그런데 만약 내용이 무지막지하게 많이 있는 경우 removedirs함수를 사용합니다.(내용이란 일반 파일들이 아닌 하위 폴더를 말함)

~/temp/dir1/dir2 » pwd
/Users/dokyungkim/temp/dir1/dir2

# python
>>> os.removedirs("./dir1/dir2")


~/temp » ls
test

2. op.path 모듈

os.path모듈은 파일이나 폴더에 대한 정보를 알아볼 수 있는 모듈입니다.
파일이나 폴더의 생성시간, 접근권한, 파일존재 유무 같은 것들도 판단할 수 있습니다.

(1) isdir 함수 - 폴더 유무 판단하기

isdir함수는 인수로 전달한 경로가 폴더인지 아닌지 판별해주는 함수입니다. 만약 폴더라면 ‘True’를 반환하고 그 밖에는 ‘False’를 반환합니다.

예를 들어서 해당 이름을 가진 폴더나 파일이 없어도 ‘False’가 나오고 이름은 같지만 폴더가 아니라 파일이라면 ‘False’가 나옵니다. 무조건 폴더이어야 ‘True’를 반환하기 때문에 해당 폴더가 존재하는지 안하는지 판단하는데 자주 사용하는 함수입니다.

>>> os.path.isdir("/Users/dokyungkim/temp/test") # 폴더가 존재할 때
True
>>> os.path.isdir("/Users/dokyungkim/temp/test.txt") # 폴더가 아닐 때
False
>>> os.path.isdir("/Users/dokyungkim/temp/dir1") # 폴더가 없을 때
False

(2) isfile 함수 - 파일 유무 판단하기

>>> os.path.isfile("/Users/dokyungkim/temp/test.txt") # 파일이 존재할 때
True
>>> os.path.isfile("/Users/dokyungkim/temp") # 파일이 아닐 때
False
>>> os.path.isfile("/Users/dokyungkim/temp/test1.txt") # 파일이 없을 때
False

(3) exists함수 - 파일이나 폴더가 존재하는지 판단하기

exists함수는 isdir함수와 isfile함수와는 다르게 같은 이름의 폴더나 파일이 존재하기만 하면 무조건 ‘True’를 반환해줍니다.

>>> os.path.exists("/Users/dokyungkim/temp/test") # 폴더가 있을 때
True
>>> os.path.exists("/Users/dokyungkim/temp/test.txt") # 파일이 있을 때
True
>>> os.path.exists("/Users/dokyungkim/temp/test1.txt") # 파일이 없을 때
False
>>> os.path.exists("/Users/dokyungkim/temp/dir1") # 폴더가 없을 때
False

(4) getsize함수 - 파일의 크기(size)를 반환해 주는 함수

일단 테스트하기 위해 준비한 txt파일의 size를 먼저 확인해 봅니다.

~/temp » l
total 24
drwxr-xr-x   5 dokyungkim  staff   170B  6 12 17:39 .
drwxr-xr-x+ 42 dokyungkim  staff   1.4K  6 12 17:44 ..
-rw-r--r--@  1 dokyungkim  staff   6.0K  6 12 17:40 .DS_Store
drwxr-xr-x   2 dokyungkim  staff    68B  6 12 16:33 test
-rw-r--r--@  1 dokyungkim  staff     9B  6 12 17:38 test.txt

# python
>>> os.path.getsize("/Users/dokyungkim/temp/test")
68
>>> os.path.getsize("/Users/dokyungkim/temp/test.txt")
9

조회해보면 같은 값이 나옴을 확인할 수 있습니다.

(5) split, splitext 함수 - 파일과 폴더의 경로를 구분해 주는 함수

>>> os.path.split("/Users/dokyungkim/temp/test.txt")
('/Users/dokyungkim/temp', 'test.txt')
>>> os.path.splitext("/Users/dokyungkim/temp/test.txt")
('/Users/dokyungkim/temp/test', '.txt')

이 함수를 더 유용하게 사용하는 방법은 이미지 크롤러에 적용시키는 것입니다. 이미지태그의 이미지 url부분을 가져와서 split함수에 넣어주면 이미지파일의 경로와 파일 이름을 분리해서 만들어줍니다.

(6) join 함수 - 파일 이름과 폴더 이름을 합쳐주는 함수

>>> join_1 = os.path.split("/Users/dokyungkim/temp/test.txt")
>>> join_1
('/Users/dokyungkim/temp', 'test.txt')
>>> os.path.join(join_1[0], join_1[1])
'/Users/dokyungkim/temp/test.txt'
>>> join_2 = ("123", "abc")
>>> os.path.join(join_2[0], join_2[1])
'123/abc'

python의 기본 join함수와는 다르게 join을 하면 경로를 나타내는 ‘/’가 삽입되어 join 됩니다.

(7) dirname, basename 함수

이 두 함수는 split함수와 조금 비슷한데, dirname함수는 완성경로의 폴더경로만 꺼내주고, basename은 파일이름만 꺼내주는 함수입니다. split함수를 사용했을 때 튜플로 반환이 되는 것을 미리 나눠거 반환해 주는 개념입니다.

>>> os.path.dirname("/Users/dokyungkim/temp/test.txt")
'/Users/dokyungkim/temp'
>>> os.path.basename("/Users/dokyungkim/temp/test.txt")
'test.txt'

3. 파일 생성 및 수정하기

파일을 생성하거나 열 때 모드라는걸 정해 줄 수 있는데, 예를 들어 파일에 들어갈 데이터들이 텍스트라면 텍스트모드, 그림(바이너리)이라면 바이너리모드를 설정할 수 있습니다.

sign mode
t 텍스트(기본)
b 바이너리
r 읽기(기본)
w 쓰기
a 이어쓰기
+ 읽기, 쓰기

(1) 쓰기 모드

>>> f = open("test.txt", "w")
>>> f.write("텍스트 파일 만들기 연습입니다.")
17
>>> f.close()

파일에 내용을 저장하는 순서는 open-write-close 의 순서라는 것입니다.

~/temp » cat test.txt
텍스트 파일 만들기 연습입니다.%

참고로 write함수 아래에 나오는 숫자는 글자수를 의미합니다.
파일을 생성하거나 열 때 경로를 별도로 지정해주지 않으면 python이 설치된 기본 경로에 저장합니다. 이때 경로에 해당 파일이 존재하면 기존 내용을 덮어쓰게 되며 존재하지 않으면 생성하고 열게 됩니다.

>>> f = open("test.txt", "w")
>>> f.write("텍스트 연습 한번더!!")
12
>>> f.close()

~/temp » cat test.txt
텍스트 연습 한번더!!%

만약에 내용을 덮어쓰지 않고 추가하고 싶다면 “a”(이어쓰기)모드를 사용하면 됩니다.

>>> f = open("test.txt", "a")
>>> f.write("텍스트 추가하기 연습!!")
13
>>> f.close()

~/temp » cat test.txt
텍스트 파일 만들기 연습 한번더!!텍스트 추가하기 연습!!%

close함수의 역할은 열려 있는 파일의 수정사항들을 저장하고 종료시킵니다.

매번 파일을 열고 닫고 하는 것이 귀찮을 경우 파일 관리를 하는 콘텍스트 매니저를 사용하면 자동으로 열고 닫고를 수행합니다. 이 방법은 with 구문으로 시작하면 됩니다.

>>> with open("test.txt","a") as test:
...     test.write("\n with 절 테스트입니다.")
...
16

~/temp » cat test.txt
텍스트 파일 만들기 연습 한번더!!텍스트 추가하기 연습!!
 with 절 테스트입니다.%

with 구문을 사용할 경우 close() 함수를 사용하지 않아도 자동으로 저장 후 파일을 닫아줍니다. 많이 사용되는 방법입니다.

(2) 읽기 모드

테스트를 위해 test.txt 파일을 수정했습니다.

~/temp » cat test.txt
1. 햄버거
2. 치즈 돈가스
3. 쭈꾸미 볶음
4. 불닭발
5. 매운 떡볶이
6. 먹고 싶어요~

a. readline() 함수로 한 줄씩 읽기

>>> f = open("test.txt", "r")
>>> f.readline()
'1. 햄버거\n'
>>> f.readline()
'2. 치즈 돈가스\n'
>>> f.readline()
'3. 쭈꾸미 볶음\n'
>>> f.readline()
'4. 불닭발\n'
>>> f.readline()
'5. 매운 떡볶이\n'
>>> f.readline()
'6. 먹고 싶어요~\n'

b. readlines() 함수로 한꺼번에 여러 줄 읽어서 출력하기

>>> f = open("test.txt", "r")
>>> f.readlines()
['1. 햄버거\n', '2. 치즈 돈가스\n', '3. 쭈꾸미 볶음\n', '4. 불닭발\n', '5. 매운 떡볶이\n', '6. 먹고 싶어요~\n']

위의 내용을 for 반복문을 이용해서 하 줄씩 보기 좋게 리스트 형태로 출력할 수 있습니다.

>>> f = open("test.txt", "r")
>>> foods = f.readlines()
>>> for food in foods:
...     print(food)
...
1. 햄버거

2. 치즈 돈가스

3. 쭈꾸미 볶음

4. 불닭발

5. 매운 떡볶이

6. 먹고 싶어요~

c. 파일 포인터 - 파일에서 현재 어디까지 읽었는지 위치 관리하기

tell함수를 사용하면 현재 파일 포인터의 위치를 알 수 있습니다. 파일 포인터는 1바이트당 1글자를 의미하는데 한글은 글자당 2바이트입니다. 마지막의 줄 바꿈 기호(\n)도 2바이트 입니다.

>>> f = open("test.txt", "r")
>>> f.readline()
'1. 햄버거\n'
>>> f.tell()
13
>>> f.readline()
'2. 치즈 돈가스\n'
>>> f.tell()
33

seek 함수는 전달된 인수로 파일 포인터를 이동시켜 줍니다. 여기서 알 수 있는 것은 파일의 내용을 읽어올 때 파일 포인터에서부터 읽어온다는 것을 알 수 있습니다.

>>> f = open("test.txt", "r")
>>> f.readline()
'1. 햄버거\n'
>>> f.tell()
13
>>> f.seek(0)
0
>>> f.readline()
'1. 햄버거\n'
>>> f.tell()
13

d. 바이너리 모드

바이너리모드 사용의 대표적인 예로 이미지를 하나 생성해 둡니다.
사진을 복사하기 위해 아래 순서로 작업합니다.

  • 사진 원본을 바이너리, 읽기 모드로 엽니다. -> docker.png
  • 사진을 복사할 파일을 하나 만듭니다. -> docker2.png
  • 원본 사진의 데이터를 read로 읽어서 복사할 파일에 write 시켜줍니다.
  • 파일을 닫습니다.
>>> d_image = open("docker.png", "rb")
>>> d_image_2 = open("docker2.png", "wb")
>>> d_image_2.write(d_image.read())
17226
>>> d_image.close()
>>> d_image_2.close()

Docker 이미지가 하나 더 생겼네요 ㅎ

아래의 빈칸 채우기 퀴즈를 풀면서 정리해봅시다.


~/temp » cat test.txt
1. 먹어도
2. 먹어도
3. 배가 고픈
4. 이유는
5. 뭘까요

위 test.txt 파일을 사용해서 아래와 같이 코드를 작성할 때 빈칸에 올 적당한 코드를 생각해 보세요.

f = open(    )
>>> f.readline()
(          )
>>> f.tell()
(          )
>>> f.readline()
'2. 먹어도\n'

답안.

>>> f = open("test.txt", "r")
>>> f.readline()
'1. 먹어도\n'
>>> f.tell()
13
>>> f.readline()
'2. 먹어도\n'

[출처] 왕초보! 파이썬 배워 크롤러 DIY 하다

python
comments powered by Disqus