존재하지 않을 수있는 파일을 삭제하는 가장 pythonic 방법


453

파일이 filename있으면 삭제하고 싶습니다 . 말하는 것이 적절합니까?

if os.path.exists(filename):
    os.remove(filename)

더 좋은 방법이 있습니까? 한 줄 방법?


7
파일이있는 경우 파일을 삭제하려고 시도하고 (권한이 없으면 실패) 최선을 다해 삭제하고 다시는 오류가 발생하지 않습니까?
— Donal Fellows

@DonalFellows가 말한 것의 "전"을하고 싶었습니다. 이를 위해 Scott의 원래 코드가 좋은 접근 방식이라고 생각하십니까?
— LarsH

함수를 호출 unlink하여 네임 스페이스 PHP에 넣습니다.
— lama12345

1
@LarsH 허용되는 답변의 두 번째 코드 블록을 참조하십시오. 예외가 "그러한 파일이나 디렉토리 없음"오류 이외의 경우 예외를 다시 발생시킵니다.
— jpmc26

답변:


613

더 파이썬적인 방법은 다음과 같습니다.

try:
    os.remove(filename)
except OSError:
    pass

이것은 더 많은 행을 취하고 매우 추악하게 보이지만 os.path.exists()예외를 과도하게 사용하는 파이썬 규칙을 불필요하게 호출하고 피합니다 .

이를 위해 함수를 작성하는 것이 좋습니다.

import os, errno

def silentremove(filename):
    try:
        os.remove(filename)
    except OSError as e: # this would be "except OSError, e:" before Python 2.6
        if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
            raise # re-raise exception if a different error occurred

17
그러나 제거 작업이 실패한 경우 (파일 시스템 또는 다른 예기치 않은 문제 만 읽음)이 과정이 통과됩니까?
— Scott C Wilson

134
또한 파일이 os.path.exists()실행될 때 존재한다는 것이 파일이 실행될 때 존재 한다는 것을 의미하지는 않습니다 os.remove().
— kindall

8
내 +1이지만 예외를 과도하게 사용하는 것은 Python 규칙이 아닙니다. :) 그렇지 않습니까?
— pepr

8
@pepr 나는 예외가 어떻게 파이썬에서 정상적인 행동의 일부인지 유머러스하게 비판했다. 예를 들어, 반복자 는 반복을 중지하기 위해 예외를 발생 시켜야합니다 .
— Matt

5
+2 할 수 없기 때문에 +1 좀 더 파이썬적인 것 외에도, 이것은 실제로 정확하지만 원본은 그렇지 않습니다. 이와 같은 경쟁 조건으로 인해 보안 허점, 재현하기 어려운 버그 등이 발생합니다.
— abarnert

159

TOCTTOU 버그 를 피하기 위해 파일의 존재를 확인하는 대신 예외를 억제하는 것을 선호합니다 . Matt의 대답은 이에 대한 좋은 예이지만 다음을 사용하여 Python 3에서 약간 단순화 할 수 있습니다 contextlib.suppress().

import contextlib

with contextlib.suppress(FileNotFoundError):
    os.remove(filename)

경우 filenameA는 pathlib.Path문자열이 아닌 객체가, 우리는 호출 할 수 있습니다 .unlink()사용하는 대신 방법을 os.remove(). 필자의 경험에 따르면 Path 객체는 파일 시스템 조작에 문자열보다 유용합니다.

이 답변의 모든 내용은 Python 3에만 적용되므로 업그레이드해야 할 또 다른 이유를 제공합니다.


7
이것은 2015 년 12 월과 같이 가장 파이썬적인 방법입니다. 파이썬은 계속 발전하고 있습니다.
— Mayank Jaiswal

2
Python 3.6에서 pathlib.Path 객체에 대한 remove () 메소드를 찾지 못했습니다.
— BrianHVB

1
@jeffbyrnes : 필자는 Zen of Python을 위반한다고 말합니다. "한 가지 분명한 방법이 있어야합니다." 동일한 작업을 수행하는 두 가지 방법이 있다면 소스 코드를 실행하는 방법이 혼합되어 독자가 따르기가 더 어려워집니다. 나는 그들이 unlink(2)가장 오래된 관련 인터페이스 인과의 일관성을 원한다고 생각 합니다.
— 케빈

1
@nivk : except절이 필요하면 try/ 를 사용해야합니다 except. 첫 번째 블록을 소개하는 줄, 블록 자체, 두 번째 블록을 소개하는 줄, 그리고 그 블록이 있어야하기 때문에 try/ except는 이미 간결 하기 때문에 의미를 줄일 수 없습니다 .
— Kevin

1
try / except 블록과 달리이 솔루션은 테스트 범위 메트릭이 관련성을 갖도록하기 위해 예외 생성을 망칠 필요가 없음을 의미합니다.
— thclark

50

os.path.existsTrue폴더와 파일을 반환 합니다. os.path.isfile대신 파일이 존재하는지 확인 하는 데 사용 하십시오.


4
존재 여부를 테스트 한 다음 해당 테스트를 기반으로 제거 할 때마다 경쟁 조건에 처하게됩니다. (파일이 중간에 사라지면 어떻게합니까?)
— Alex L

34

Andy Jones의 대답의 정신에서 진정한 삼항 연산은 어떻습니까?

os.remove(fn) if os.path.exists(fn) else None

41
못생긴 삼항의 오용.
— bgusach

19
@BrianHVB 삼항은 분기를 수행하지 말고 조건에 따라 두 값 중에서 선택해야하므로
— bgusach

1
흐름 제어에 예외를 사용하고 싶지 않습니다. 그것들은 코드를 이해하기 어렵게 만들고, 더 중요한 것은 파일 삭제를 막는 권한 문제와 같은 다른 오류가 마스킹되어 자동 실패를 유발할 수 있다는 것입니다.
— Ed King

11
이것은 원자가 아닙니다. 존재하는 호출과 제거 사이에 파일을 삭제할 수 있습니다. 작업을 시도하고 실패하는 것이 더 안전합니다.
— ConnorWGarvey 2012

1
@ nam-g-vu 참고로, 원래 질문자의 구문을 대안으로 추가했기 때문에 편집 내용을 롤백했습니다. 그들은 그와 다른 것을 찾고 있었기 때문에 편집 이이 특정 답변과 관련이 있다고 생각하지 않습니다.
— Tim Keating

9

파일 (들)이 존재하는지 알고 제거하는 또 다른 방법은 모듈 glob를 사용하는 것입니다.

from glob import glob
import os

for filename in glob("*.csv"):
    os.remove(filename)

Glob은 * nix 와일드 카드로 패턴을 선택할 수있는 모든 파일을 찾고 목록을 반복합니다.


8

Python 3.8부터 missing_ok=Trueand pathlib.Path.unlink( docs here )를 사용 하십시오.

from pathlib import Path

my_file = Path("./dir1/dir2/file.txt")

# Python 3.8+
my_file.unlink(missing_ok=True)

# Python 3.7 and earlier
if my_file.exists():
    my_file.unlink()

1
내 의견으로는 실용적인 python3에 대한 최고의 답변.
— mrgnw


6
if os.path.exists(filename): os.remove(filename)

하나의 라이너입니다.

많은 사람들이 동의하지 않을 수도 있습니다. 아마도 삼항 사용을 "추악한"사용을 고려하는 것과 같은 이유로 비표준적인 "못생긴"이라고 부르는 표준을 사용하는 사람들의 말에 귀를 기울여야하는지에 대한 의문이 생깁니다.


3
이것은 깨끗합니다-흐름 제어에 예외를 사용하고 싶지 않습니다. 그것들은 코드를 이해하기 어렵게 만들고, 더 중요한 것은 파일 삭제를 막는 권한 문제와 같은 다른 오류가 마스킹되어 자동 실패를 유발할 수 있다는 것입니다.
— Ed King

2
파일 이름을 수정하는 프로세스가 하나만 있다고 가정하기 때문에 좋지 않습니다. 원자가 아닙니다. 작업을 시도하고 정상적으로 실패하는 것이 안전하고 정확합니다. 파이썬이 표준화 할 수 없다는 것은 짜증납니다. 디렉토리가 있다면 shutil을 사용하고 원하는 것을 정확하게 지원할 것입니다.
— ConnorWGarvey


1

이 같은? 단락 평가를 활용합니다. 파일이 존재하지 않으면 전체 조건이 참이 될 수 없으므로 파이썬은 두 번째 부분을 평가하지 않습니다.

os.path.exists("gogogo.php") and os.remove("gogogo.php")

25
이것은 "더 파이썬적인"것은 아닙니다. 사실 Guido가 구체적으로 경고하고 부울 연산자의 "남용"을 말합니다.
— abarnert

1
오, 나는 동의한다-질문의 일부는 한 줄 길을 요구했다. 그리고 이것은 나의 머리에 튀어 나온 첫 번째 것이었다
— Andy Jones

4
콜론 다음에 줄 바꿈을 제거하여 하나의 라이너로 만들 수도 있습니다. os.path.exists ( "gogogo.php") if os.remove ( "gogogo.php") else None. :)
— abarnert 2016 년

0

KISS 오퍼링 :

def remove_if_exists(filename):
  if os.path.exists(filename):
    os.remove(filename)

그리고:

remove_if_exists("my.file")

1
전체 기능을 작성해야한다면, 하나의 라이너의 요점을 놓치게됩니다
— Ion Lesan

@Ion Lesan OP는이 문제를 해결하는 "최상의"방법을 따릅니다. 가독성을 떨어 뜨릴 경우 하나의 라이너가 더 좋은 방법은 아닙니다.
— Baz

"최고"의 본질적으로 광범위한 정의를 감안할 때, 나는 TOCTOU의 영향을 분명히 받았지만, 이런 의미에서 논쟁하지는 않을 것입니다. 그리고 KISS 솔루션은 아닙니다.
— 이온 레산

@ 매트 사실이지만 여기에 제공된 여러 가지 솔루션으로 인해이 문제가 발생하지 않습니까?
— Baz

0

이것은 또 다른 해결책입니다.

if os.path.isfile(os.path.join(path, filename)):
    os.remove(os.path.join(path, filename))

0

예외적으로 자신의 메시지를 가진 또 다른 솔루션.

import os

try:
    os.remove(filename)
except:
    print("Not able to delete the file %s" % filename)

-1

내가 사용한 rm에 존재하지 않는 파일을 삭제하는 강제 할 수있는 --preserve-root에 옵션으로 rm.

--preserve-root
              do not remove `/' (default)

rm --help | grep "force"
  -f, --force           ignore nonexistent files and arguments, never prompt

safe-rm ( sudo apt-get install safe-rm)을 사용할 수도 있습니다

Safe-rm은 / bin / rm을 래퍼로 바꾸어 실수로 중요한 파일이 삭제되는 것을 방지하기위한 안전 도구로, 제거 할 수없는 파일 및 디렉토리의 구성 가능한 블랙리스트에 대해 지정된 인수를 검사합니다.

먼저 폴더 / 파일 경로가 있는지 확인합니다. 변수 fileToRemove /folderToRemove to the string-r /`를 설정하지 못하게합니다 .


import os, subprocess

fileToRemove = '/home/user/fileName';
if os.path.isfile(fileToRemove):
   subprocess.run(['rm', '-f', '--preserve-root', fileToRemove]
   subprocess.run(['safe-rm', '-f', fileToRemove]

1
이 사소한 일에 쉘을 사용하는 것은 지나치지 않으며이 접근법은 크로스 플랫폼 (예 : Windows)에서도 작동하지 않습니다.
— Nabla

4
표준 라이브러리 대신 쉘을 사용하는 것 (예 : os.remove)은 항상 가장 비법적이고 깨끗한 방법 중 하나입니다. 예를 들어 셸에서 반환 된 오류를 수동으로 처리해야합니다.
— Nabla

1
나는 rm안전하게 사용 하고 예방하기 위해 답변을 추가했습니다 rm -r /. @JonBrave
— alper

1
rm -f --preserve-root충분하지 않습니다 ( --preserve-root어쨌든 기본값 일 것입니다). 나는 -r / 예를 들어 , 그것이 -r /home무엇이든 아니면 무엇입니까? 아마도 원 rm -f -- $fileToRemove하지만 그게 요점이 아닙니다.
— JonBrave

3
변수 이름 (환경 변수), 인용 부호 및 보호 기능이없는 사용 방식이 아닙니다. 그리고이 질문에 대해서는 아닙니다. 경고에 노출하는 os.system('rm ...')것은 매우 위험합니다. 죄송합니다.
— JonBrave
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.