본문 바로가기
코딩취미/Python

파이썬 파일이동 os.rename, shutil.move 차이와 사용 방법

by 브링블링 2023. 12. 12.
728x90

개발 PC에서는 os 코드로 파일이동이 잘 되었는데, 배포 exe를 만들고 다른 pc에서 동작시켰더니 파일이동이 안됐다.

PC 사용자 계정문제 인가 싶어서, 실행파일을 관리자권한으로 실행했는데,

동작이 안됐고 폴더자체의 권한설정을 바꿔서 했는데도, 동작이 안됐다.

 

그런데, 폴더를 변경하지 않고 동작시키면 (os 모듈에서 파일이동을 사용하지 않으면) S/W의 전체적인 동작이 잘됐다.

 

결국, 파일이동할 때 문제가 생기는거라서, 파일이동을 시키는 코드를 확인하니 os.rename()을 사용하고 있었다.

os.rename 과 shutil.move의 차이점

  1. 원자성(Atomicity):
    • os.rename은 파일 또는 디렉토리 이동이 원자적이지 않습니다. 즉, 파일 이동 중 오류가 발생하면 중간 상태로 남을 수 있습니다. 이는 프로그램이 중단될 때 파일 시스템이 불안정한 경우 문제가 발생할 수 있습니다.
    • shutil.move는 이동 작업을 더 원자적으로 처리하려고 시도합니다. 이동 작업이 실패하면 원래 상태로 롤백하여 중간 상태를 방지합니다.
  2. 목적지 파일의 덮어쓰기:
    • os.rename은 목적지에 이미 동일한 이름의 파일이 있는 경우 덮어쓰기를 수행하지 않습니다. 이는 기존 파일이 있으면 에러를 발생시킬 수 있습니다.
    • shutil.move는 목적지에 동일한 이름의 파일이 있는 경우, 목적지 파일을 덮어쓰기를 시도하고, 성공하면 이동 작업을 완료합니다.
  3. 디렉토리 이동:
    • os.rename은 단일 파일 또는 빈 디렉토리를 다른 디렉토리로 이동할 때 사용됩니다.
    • shutil.move는 파일 및 디렉토리를 모두 처리할 수 있으며, 대상 디렉토리가 비어있지 않아도 됩니다.
  4. Cross-Filesystem 이동:
    • os.rename은 일반적으로 동일한 파일 시스템 내에서만 작동하며, 파일 시스템 경계를 넘어가는 이동에는 실패할 수 있습니다.
    • shutil.move는 파일 시스템 경계를 넘어가는 이동을 더 잘 처리하며, 필요한 경우 파일을 복사하고 삭제합니다.

 

동작 성공과 실패 : os.rename vs shutil.move

  1. Cross-Filesystem 이동:
    • os.rename은 일반적으로 동일한 파일 시스템 내에서만 작동합니다. 파일 시스템 경계를 넘어가는 이동이 필요한 경우에는 os.rename이나 shutil.move 모두 실패할 수 있습니다.
    • shutil.move는 파일 시스템 경계를 넘어가는 이동을 더 잘 처리할 수 있습니다. 이 경우, shutil.move는 os.rename을 시도하고, 만약 실패하면 파일을 복사하고 원본 파일을 삭제하여 이동을 시도합니다.
  2. Atomicity (원자성):
    • os.rename은 이동 작업 중간에 오류가 발생하면 파일 시스템에서 파일을 제대로 처리하지 못할 수 있습니다. 이는 일시적인 상태가 남을 수 있음을 의미합니다.
    • shutil.move는 보다 원자적으로 이동 작업을 수행하려고 시도합니다. 중간에 오류가 발생하면 원래 상태로 롤백하여 중간 상태를 방지하려고 합니다.
  3. 목적지 파일의 덮어쓰기:
    • os.rename은 목적지에 이미 동일한 이름의 파일이 있는 경우 덮어쓰기를 수행하지 않습니다. 따라서 목적지에 동일한 이름의 파일이 이미 존재하는 경우에는 실패할 수 있습니다.
    • shutil.move는 목적지에 동일한 이름의 파일이 있는 경우, 목적지 파일을 덮어쓰기를 시도하고, 성공하면 이동 작업을 완료합니다.

==> 결론, shutil.move는 더 많은 예외 처리 및 안전성을 갖추고 있어서 파일 이동 작업에 더 적합합니다. 따라서 파일 이동이나 이름 변경 작업을 수행할 때는 가능한한 shutil.move를 사용하는 것이 좋습니다.

 

728x90

os.rename 예제

이 코드에서 os.rename은 기존 파일의 경로와 새로운 파일의 경로를 받아들여 기존 파일의 이름을 변경합니다. 예외 처리를 통해 파일이 존재하지 않거나, 이미 동일한 이름의 파일이 존재하는 경우에 대한 예외를 처리할 수 있습니다.

import os

# 기존 파일 경로와 이름
old_path = 'old_name.txt'

# 새로운 파일 경로와 이름
new_path = 'new_name.txt'

try:
    # 파일 이름 변경
    os.rename(old_path, new_path)
    print(f'파일 이름 변경 성공: {old_path} -> {new_path}')
except FileNotFoundError:
    print(f'파일이 존재하지 않습니다: {old_path}')
except FileExistsError:
    print(f'이미 동일한 이름의 파일이 존재합니다: {new_path}')
except Exception as e:
    print(f'파일 이름 변경 실패: {e}')

 

shutil.move 예제

이 코드에서 shutil.move는 기존 파일의 경로와 새로운 파일의 경로를 받아들여 파일을 이동하거나 이름을 변경합니다. 예외 처리를 통해 파일이 존재하지 않거나 이동 작업이 실패한 경우에 대한 예외를 처리할 수 있습니다. shutil.Errorshutil.move에서 발생할 수 있는 다양한 예외들을 포함하는 범용적인 예외 클래스입니다.

import shutil

# 기존 파일 경로와 이름
old_path = 'old_name.txt'

# 새로운 파일 경로와 이름
new_path = 'new_name.txt'

try:
    # 파일 이동 또는 이름 변경
    shutil.move(old_path, new_path)
    print(f'파일 이동 또는 이름 변경 성공: {old_path} -> {new_path}')
except FileNotFoundError:
    print(f'파일이 존재하지 않습니다: {old_path}')
except shutil.Error as e:
    print(f'파일 이동 또는 이름 변경 실패: {e}')
728x90