달나라 노트

Python : pathlib (OS 상관없이 호환되는 filepath 생성하기. Mac/Linux/Windows OS file path. 경로 분석. directory functinos. 파일 읽기. 파일 쓰기. file read. file write) 본문

Python/Python Basic

Python : pathlib (OS 상관없이 호환되는 filepath 생성하기. Mac/Linux/Windows OS file path. 경로 분석. directory functinos. 파일 읽기. 파일 쓰기. file read. file write)

CosmosProject 2023. 8. 13. 18:42
728x90
반응형

 

 

 

어떤 폴더나 파일의 경로를 나타낼 때 보통 우리는 아래와 같은 표현 방식을 사용합니다.

 

my_program/tester/Code/test_program.py

 

 

근데 위 표현식은 OS에 따라 에러를 일으킬 수 있습니다.

Mac/Linux에서는 폴더, 파일 구분자로서 슬래쉬(Slash, /)를 사용하지만,

Windows에서는 폴더, 파일 구분자로서 역슬래쉬(Backward slash, \)를 사용하기 때문입니다.

 

 

Mac/Linux = my_program/tester/Code/test_program.py
Windows = my_program\tester\Code\test_program.py

 

혼자서 프로그래밍을 한다면 또는 그렇게 규모가 크지 않은 협업을 한다면 위 차이가 전혀 상관없을 수 있습니다.

저 또한 Mac을 사용하며 개발을 할 때 그냥 위 file path string을 자주 사용하곤 합니다.

 

근데 어느정도 규모가 커지거나 다양한 OS를 넘나들어야 하는 상황이라면 위 차이는 꽤 거슬리는 문제가 될 수 있습니다.

 

이럴 때 사용할 수 있는 것이 바로 pathlib 라이브러리 입니다.

 

pathlib는 built-in module로서 별도로 pip install을 이용하여 설치할 필요가 없습니다.

 

 

 

 

 

 

my_program/tester/Code/test_program.py

위 경로를 pathlib 모듈을 이용해서 나타내면 아래와 같습니다.

 

import pathlib


# my_program/tester/Code/test_program.py
dir_path = pathlib.Path('my_program') / 'tester' / 'Code' / 'test_program.py'

print(dir_path)


-- Result
my_program/tester/Code/test_program.py

 

pathlib 모듈은 file path를 나타내는 string을 단순 string이 아닌 객체처럼 취급합니다.

사용법은 위와 같으며, 

 

dir_path = pathlib.Path('my_program') / 'tester' / 'Code' / 'test_program.py'

 

pathlib.Path class에 가장 상단의 directory를 두고 그 이하로 slash(/)를 이용하여 직관적으로 path를 명시해줍니다.

 

 

위 코드는 현재 코드를 실행하는 OS의 종류와는 상관없이 모두 실행됩니다.

 

 

 

기존에는 위같은 작동 방식을 os module을 이용해서 진행했었습니다.

 

import os

dir_path = os.path.join('my_program', 'tester', 'Code', 'test_program.py')
print(dir_path)



-- Result
my_program/tester/Code/test_program.py

위처럼 os.path.join() method를 이용해도 동일한 결과를 얻을 수 있습니다.

 

 

 

 

 

그러면 pathlib 모듈을 이용했을 때에는 고전적으로 계속 이용하던 my_program/tester/Code/test_program.py 같은 형식의 directory string은 사용할 수 없을까요?

 

아뇨 사용 가능합니다.

 

import pathlib


dir_path = pathlib.Path('my_program/tester/Code/test_program.py')
print(dir_path)



-- Result
my_program/tester/Code/test_program.py

위 예시를 보면 그냥 Path class의 parameter로서 full directory string을 전달해도 정상적으로 인식하긴 합니다.

 

 

 

 

 

 

 

 

 

 

pathlib 모듈은 단순히 path를 객체로 만드는 것 뿐 아니라 이를 이용한 다양한 기능을 가집니다.

 

그 기능 몇가지에 대해 알아봅시다.

 

 

1. 파일 읽기

 

pathlib 모듈을 이용하면 특정 파일에 적힌 텍스트를 읽을 수 있습니다.

마치 open을 사용하는 것 처럼요.

 

project_test
├── main.py
└── inputs
    └── text_files
        └── text_contents.txt

현재 디렉토리 구조는 위와 같습니다.

제가 코드를 실행할 파일은 main.py입니다.

 

 

import pathlib

dir_path = pathlib.Path('inputs') / 'text_files' / 'test_contents.txt'
print(dir_path, '\n')

file_contents = dir_path.read_text()
print(file_contents)



-- Result
inputs/text_files/test_contents.txt

This is test contents.txt
This file contains test contents that will be read using pathlib module.
1
2
3
4
5

위 예시는 inputs/text_files/test_contents.txt의 내용을 읽는 것입니다.

 

dir_path = pathlib.Path('inputs') / 'text_files' / 'test_contents.txt'

내용을 읽어들이기 위해 test_contents.txt 파일이 있는 경로를 main.py 기준 상대경로로 지정해줍니다.

 

여기서 dir_path를 print하면 inputs/text_files/test_contents.txt 처럼 print될 것입니다.

근데 이건 단순히 string이 아니라 경로 객체입니다.

 

 

 

file_contents = dir_path.read_text()

그래서 이렇게 dir_path에 read_text() method를 사용하면 dir_path에 명시된 파일에 담겨있는 텍스트를 읽어옵니다.

 

 

 

 

 

 

2. 파일 쓰기

 

파일 읽기가 되면 파일 쓰기도 될 것 같지 않나요.

파일 쓰기도 당연히 됩니다.

 

import pathlib

dir_path = pathlib.Path('inputs') / 'text_files' / 'test_contents_2.txt'
file_contents = dir_path.write_text('''
This is new file created by using pathlib module.
6
7
8
9
10
.
''')

위 예시처럼 write_text() method를 사용하면 파일을 생성할 수 있습니다.

생성되는 파일의 내용은 write_text() method의 parameter로서 전달하면 됩니다.

 

위 코드를 실행하면 아래처럼 dir_path에 명시한 경로에 text_contents_2.txt 라는 새로운 파일이 하나 생성된 것을 볼 수 있을 것입니다.

project_test
├── main.py
└── inputs
    └── text_files
        ├── text_contents.txt
        └── text_contents_2.txt

 

 

 

3. 현재 경로 파악 (cwd)

Mac terminal에서 cwd (current working directory) 명령어는 현재 디렉토리 위치를 나타내줍니다.

pathlib 또한 cwd 기능을 가지고 있습니다.

 

import pathlib


current_path = pathlib.Path.cwd()
print(current_path)



-- Result
/Users/Documents/code/project_test

위 예시를 보면 현재 파일이 있는 곳의 상위 directory를 나타내줍니다.

main.py는 project_test 폴더 안에 있고, 그리고 그보다 더 상단의 directory 구조까지 절대경로로서 나타내줍니다.

 

 

 

 

 

 

4. 경로 존재 여부 파악

os 모듈에는 특정 directory 또는 파일이 존재하는지를 True/False로 return해주는 exists method가 있습니다.

이와 비슷한 기능이 pathlib 모듈에도 있습니다.

 

import pathlib


dir_path = pathlib.Path('inputs') / 'text_files' / 'test_contents.txt'
print(dir_path.exists())


-- Result
True

 

 

 

 

 

5. 존재하는 파일 list 얻기 (glob)

pathlib 모듈은 glob와 비슷한 기능도 가지고 있습니다.

 

import pathlib


dir_path = pathlib.Path('.')
print(dir_path)

list_files = list(dir_path.glob('*'))
print(list_files)


-- Result
[PosixPath('main.py'), PosixPath('test_contents.txt'), PosixPath('inputs'), PosixPath('.idea')]

 

- dir_path = pathlib.Path('.')

.은 현재 경로를 의미합니다.

 

- list(dir_path.glob('*'))

glob를 사용할 때에는 파일 이름의 pattern을 glob의 parameter로서 전달하는데 여기서는 *를 적었으므로 모든 파일/폴더를 return하라는 의미입니다.

이렇게 glob method의 pattern만 변경해가면서 사용할 수 있습니다.

 

 

 

 

 

 

6. 절대 경로로 변환

 

import pathlib


dir_path = pathlib.Path('test_code') / 'test' / 'text_file' / 'text_contents.txt'
print(dir_path)

print(dir_path.absolute())


-- Result
test_code/test/text_file/text_contents.txt
/Users/Documents/code/project_test/test_code/test/text_file/text_contents.txt

absolute method를 이용하면 상대경로로 명시된 path를 현재 코드가 실행되는 파일을 기준으로 한 absolute path로 바꿔줍니다.

 

 

 

 

 

7. 다양한 경로의 분석

더 상위 경로를 return해주거나, 경로의 구성 요소를 return해주는 등 다양한 경로 분석 기능을 제공합니다.

 

import pathlib


dir_path = pathlib.Path('test_code') / 'test' / 'text_file' / 'text_contents.txt'
print(dir_path, '\n')


print(dir_path.parent)
print(list(dir_path.parents))
print(dir_path.parts)



-- Result
test_code/test/text_file/text_contents.txt 

test_code/test/text_file
[PosixPath('test_code/test/text_file'), PosixPath('test_code/test'), PosixPath('test_code'), PosixPath('.')]
('test_code', 'test', 'text_file', 'text_contents.txt')

 

위 예시를 봅시다.

 

- dir_path.parent

parent 속성은 현재 path 객체의 바로 위 parent 경로를 나타내줍니다.

간단하게 말하면 그냥 경로 string에서 가장 하위의 단계(= 가장 오른쪽 단계) 부터 하나를 지운거라고 보면 됩니다.

test_code/test/text_file/text_contents.txt

기존 dir_path가 위와 같았으나 가장 하위에 있는 text_contents.txt를 지우면 parent 속성의 결과와 같아집니다.

 

 

- dir_path.parents

parents 속성은 parent 속성과 비슷합니다.

다만 parent 속성이 바로 상위의 경로 하나만 return했다면,

parents 속성은 현재 path 객체에서 가장 오른쪽부터 하나씩 없애가며 가능한 모든 상위 directory 구조를 나타내줍니다.

따라서 그 결과가 여러개일 수 있으므로 list의 형태로 변환해서 봐야합니다.

 

 

- dir_path.parts

parts 속성은 현재 path 객체를 구성하는 모든 요소를 하나씩 분할해서 나타내줍니다.

 

test_code/test/text_file/text_contents.txt

('test_code', 'test', 'text_file', 'text_contents.txt')

결과를 보면 연결된 경로 string이 마치 slash를 기준으로 하나씩 다 나눠진 형태가 return된 것을 알 수 있습니다.

 

 

 

 

 

 

728x90
반응형
Comments