존재하지 않을 수있는 파일을 삭제하는 가장 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.