फ़ाइल को हटाने के लिए अधिकांश पायथोनिक तरीका जो मौजूद नहीं हो सकता है


453

मैं फ़ाइल को हटाना चाहता हूँ filenameअगर यह मौजूद है। क्या यह कहना उचित है?

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

क्या कोई बेहतर तरीका है? एक-तरफ़ा रास्ता?


7
क्या आप किसी फ़ाइल को हटाने का प्रयास करना चाहते हैं यदि वह मौजूद है (और यदि आपके पास अनुमतियों की कमी है तो विफल हो) या सर्वश्रेष्ठ-प्रयास को हटाने के लिए और कभी भी आपके चेहरे पर कोई त्रुटि नहीं हुई है?
डोनल फेलो

मैं @DonalFellows क्या कहा के "पूर्व" करना चाहता था। उसके लिए, मुझे लगता है कि स्कॉट का मूल कोड एक अच्छा तरीका होगा?
लार्श डे

नामक एक फंक्शन करें unlinkऔर इसे नाम स्थान PHP में रखें।
लामा १२५४५

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
लेकिन अगर यह निष्कासन ऑपरेशन विफल हो जाता है (केवल फ़ाइल सिस्टम या कुछ अन्य अप्रत्याशित समस्या पढ़ें)?
स्कॉट सी विल्सन

136
इसके अलावा, फ़ाइल os.path.exists()निष्पादित होने पर मौजूद तथ्य का मतलब यह नहीं है कि os.remove()निष्पादित होने पर यह मौजूद है।
टाइप करें

8
मेरा +1, लेकिन अपवादों का अति प्रयोग एक पायथन सम्मेलन नहीं है :) या यह है?
पीप्र

8
@pepr मैं सिर्फ इस बात की आलोचना कर रहा था कि अपवाद अजगर में सामान्य व्यवहार का हिस्सा कैसे हैं। उदाहरण के लिए, पुनरावृत्तियों को रोकने के लिए पुनरावृत्तियों को अपवाद बनाना होगा
मैट

5
+1 क्योंकि मैं +2 नहीं कर सकता। अधिक पायथोनिक होने के अलावा, यह वास्तव में सही है, जबकि मूल कारण का सुझाव नहीं दिया गया है। रेस जैसी स्थितियां सुरक्षा छेद, हार्ड-टू-
रिप्रो

160

मैं TOCTTOU बग से बचने के लिए फ़ाइल के अस्तित्व की जाँच करने के बजाय एक अपवाद को दबाने को प्राथमिकता देता हूं । मैट का उत्तर इसका एक अच्छा उदाहरण है, लेकिन हम इसका उपयोग करते हुए अजगर 3 के तहत इसे थोड़ा सरल कर सकते हैं contextlib.suppress():

import contextlib

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

यदि एक स्ट्रिंग के बजाय filenameएक pathlib.Pathऑब्जेक्ट है, तो हम .unlink()उपयोग करने के बजाय इसकी विधि को कॉल कर सकते हैं os.remove()। मेरे अनुभव में, फ़ाइल सिस्टम मैनिपुलेशन के लिए स्ट्रिंग्स की तुलना में पथ ऑब्जेक्ट अधिक उपयोगी हैं।

चूंकि इस उत्तर में सब कुछ पायथन 3 के लिए अनन्य है, इसलिए यह उन्नयन के लिए एक और कारण प्रदान करता है।


8
यह दिसंबर 2015 की तरह सबसे अधिक पायथोनिक तरीका है। हालांकि अजगर विकसित हो रहा है।
मयंक जायसवाल

2
मुझे पैथलॉन के लिए कोई हटाने () की विधि नहीं मिली। पाइथन 3.6 पर ऑब्जेक्ट्स
ब्रायनएचवीबी

1
@ जैफ़्फ़िर्बन्स: मुझे लगता है कि पायथन के ज़ेन का उल्लंघन होगा: "एक होना चाहिए - और अधिमानतः इसे करने के लिए केवल एक - स्पष्ट तरीका।" यदि आपके पास दो विधियाँ हैं जो एक ही काम करती हैं, तो आप चल रहे स्रोत कोड में उनके मिश्रण के साथ समाप्त हो जाएंगे, जो पाठक के लिए अनुसरण करना कठिन होगा। मुझे संदेह है कि वे निरंतरता चाहते थे unlink(2), जो अब तक का सबसे पुराना प्रासंगिक इंटरफेस है।
केविन

1
@nivk: यदि आपको एक exceptक्लॉज़ की आवश्यकता है , तो आपको try/ का उपयोग करना चाहिए except। इसे सार्थक रूप से छोटा नहीं किया जा सकता है, क्योंकि आपके पास पहले ब्लॉक को शुरू करने के लिए एक पंक्ति होनी चाहिए, स्वयं ब्लॉक, दूसरे ब्लॉक को शुरू करने के लिए एक पंक्ति और फिर उस ब्लॉक को, इसलिए try/ exceptपहले से ही यथासंभव जटिल है।
केविन

1
यह इंगित करने के लायक है कि एक कोशिश के अलावा / ब्लॉक को छोड़कर, इस समाधान का मतलब है कि आपको यह सुनिश्चित करने के लिए गड़बड़ करने की आवश्यकता नहीं है कि परीक्षण कवरेज मैट्रिक्स प्रासंगिक हैं।
थ्रार्क

50

os.path.existsTrueफ़ोल्डर्स के साथ-साथ फ़ाइलों के लिए रिटर्न । os.path.isfileइसके बजाय यह जाँचने के लिए उपयोग करें कि फ़ाइल मौजूद है या नहीं।


4
किसी भी समय हम अस्तित्व के लिए परीक्षण करते हैं और फिर उस परीक्षण के आधार पर हटा देते हैं, हम खुद को एक दौड़ की स्थिति तक खोल रहे हैं। (क्या होगा अगर फ़ाइल बीच में गायब हो जाती है?)
एलेक्स एल

34

एंडी जोन्स के जवाब की भावना में, कैसे एक प्रामाणिक टर्नरी ऑपरेशन के बारे में:

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

41
गुच्छों का बदसूरत दुरुपयोग।
bgusach

19
@BrianHVB क्योंकि एक शर्त के आधार पर दो मूल्यों के बीच चयन करने के लिए ternaries हैं, ब्रांचिंग करने के लिए नहीं।
बजकर १६ मिनट

1
मैं प्रवाह नियंत्रण के लिए अपवादों का उपयोग करना पसंद नहीं करता। वे कोड को समझना मुश्किल बना देते हैं और अधिक महत्वपूर्ण बात यह है कि कुछ अन्य त्रुटि उत्पन्न हो सकती है (जैसे एक फ़ाइल को अवरुद्ध करने की अनुमति समस्या) जो एक मौन विफल हो जाएगी।
एड किंग

11
यह परमाणु नहीं है। मौजूद होने और हटाने के लिए कॉल के बीच फ़ाइल को हटाया जा सकता है। यह ऑपरेशन का प्रयास करने और इसे विफल होने के लिए सुरक्षित है।
कॉनरवगर्वाई

1
@ nam-g-vu जस्ट FYI, मैंने आपका संपादन वापस कर दिया है क्योंकि आपने मूल रूप से मूल प्रश्नकर्ता के सिंटैक्स को विकल्प के रूप में जोड़ा है। चूंकि वे इससे अलग कुछ खोज रहे थे, इसलिए मुझे नहीं लगता कि एडिट इस विशेष उत्तर के लिए जर्मन है।
टिम कीटिंग

11

पायथन 3.8 के अनुसार, उपयोग करें missing_ok=Trueऔर pathlib.Path.unlink( डॉक्स यहां )

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

9

यह जानने का एक और तरीका है कि क्या फ़ाइल (या फ़ाइलें) मौजूद हैं, और इसे हटाने के लिए, मॉड्यूल ग्लोब का उपयोग कर रहा है।

from glob import glob
import os

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

ग्लोब उन सभी फाइलों को ढूंढता है जो पैटर्न का चयन * निक्स वाइल्डकार्ड के साथ कर सकते हैं और सूची को लूप कर सकते हैं।


7

मैट का उत्तर पुराने पायथन के लिए सही है और केविन नए लोगों के लिए सही उत्तर है।

यदि आप फ़ंक्शन की प्रतिलिपि नहीं बनाना चाहते हैं silentremove, तो यह कार्यप्रणाली path_pod के रूप में remove_p के रूप में सामने आती है :

from path import Path
Path(filename).remove_p()

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

एक लाइनर है।

आप में से कई असहमत हो सकते हैं - संभवतः ऐसे कारणों के लिए जो टर्नरीज़ के प्रस्तावित उपयोग को "बदसूरत" मानते हैं - लेकिन यह इस सवाल का जवाब देता है कि जब हम कुछ गैर-मानक "बदसूरत" कहते हैं तो हम लोगों को बदसूरत मानकों का उपयोग करना चाहिए।


3
यह साफ है - मुझे प्रवाह नियंत्रण के लिए अपवादों का उपयोग करना पसंद नहीं है। वे कोड को समझना मुश्किल बना देते हैं और अधिक महत्वपूर्ण बात यह है कि कुछ अन्य त्रुटि उत्पन्न हो सकती है (जैसे एक फ़ाइल को अवरुद्ध करने की अनुमति समस्या) जो एक मौन विफल हो जाएगी।
एड किंग

2
यह सुंदर नहीं है क्योंकि यह मानता है कि केवल एक प्रक्रिया है जो फ़ाइल नाम को संशोधित करेगी। यह परमाणु नहीं है। यह सुरक्षित है और ऑपरेशन का प्रयास करने और इनायत करने में विफल है। यह कष्टप्रद है कि पायथन मानकीकरण नहीं कर सकता है। यदि हमारे पास एक निर्देशिका थी, तो हम शटील का उपयोग करेंगे और यह ठीक उसी तरह का समर्थन करेगा जैसा हम चाहते हैं।
कॉनरवरगेयर


1

कुछ इस तरह? शॉर्ट-सर्किट मूल्यांकन का लाभ उठाता है। यदि फ़ाइल मौजूद नहीं है, तो पूरी स्थिति सही नहीं हो सकती है, इसलिए अजगर दूसरे भाग के मूल्यांकन को परेशान नहीं करेगा।

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

25
यह निश्चित रूप से "अधिक पायथोनिक" नहीं है - वास्तव में, यह कुछ ऐसा है जो गुइडो विशेष रूप से इसके बारे में चेतावनी देता है, और बूलियन ऑपरेटरों के "दुरुपयोग" के रूप में संदर्भित करता है।
abarnert

1
ओह, मैं सहमत हूं - एक लाइन के लिए पूछे गए सवाल का हिस्सा और यह पहली चीज थी जो मेरे सिर में आ गई थी
एंडी जोन्स

4
ठीक है, आप इसे बृहदान्त्र के बाद नई लाइन को हटाकर इसे वन-लाइनर भी बना सकते हैं ... या, इससे भी बेहतर, गाइड ने स्पष्ट रूप से "बूलियन ऑपरेटरों को गाली देने" से लोगों को रोकने के लिए अगर अभिव्यक्ति को जोड़ा, और साबित करने का एक बड़ा अवसर है कि किसी भी चीज़ का दुरुपयोग किया जा सकता है: os.remove ("gogogo.php") यदि os.path.exists ("gogogo.php") और कोई नहीं। :)
19

0

एक चुंबन की पेशकश:

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

और तब:

remove_if_exists("my.file")

1
यदि आपको एक पूरा कार्य लिखना है तो यह एक-लाइनर्स की बात को याद करता है
आयन लेसन

@ इयान लेसन द ओपी इस समस्या को हल करने के "सबसे अच्छे" तरीके के बाद है। एक लाइनर एक बेहतर तरीका कभी नहीं है अगर यह पठनीयता को खतरे में डालता है।
बाज़

"सर्वश्रेष्ठ" की अंतर्निहित व्यापक परिभाषा को देखते हुए, मैं इस अर्थ में बहस नहीं करने जा रहा हूं, हालांकि यह TOCTOU द्वारा स्पष्ट रूप से प्रभावित है। और निश्चित रूप से नहीं एक KISS समाधान।
इयॉन लेसन

@ माट सही है, लेकिन यहां दिए गए कई समाधान इस समस्या से ग्रस्त नहीं हैं?
बाज

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

हम सुरक्षित-आरएम ( sudo apt-get install safe-rm) का भी उपयोग कर सकते हैं

सेफ़-आरएम एक सुरक्षा उपकरण है जिसका उद्देश्य महत्वपूर्ण फाइलों के आकस्मिक विलोपन को रोकने के लिए है / रैपर के साथ बिन / आरएम को हटाकर, जो फ़ाइलों और निर्देशिकाओं के एक विन्यास ब्लैकलिस्ट के खिलाफ दिए गए तर्कों की जांच करता है जिन्हें कभी भी हटाया नहीं जाना चाहिए।

पहले मैं जांचता हूं कि फ़ोल्डर / फ़ाइल पथ मौजूद है या नहीं। यह वैरिएबल फ़ाइल को सेट करने से रोकेगा TTRRove /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
कुछ के लिए एक शेल का उपयोग करना यह तुच्छ है और यह दृष्टिकोण क्रॉस-प्लेटफॉर्म (यानी विंडोज) पर भी काम नहीं करेगा।
नबला

4
मानक पुस्तकालय (उदाहरण के लिए os.remove) के बजाय एक शेल का उपयोग करना हमेशा कुछ करने के कम से कम पायथोनिक / स्वच्छ तरीकों में से एक होता है। उदाहरण के लिए आपको मैन्युअल रूप से शेल द्वारा दी गई त्रुटियों को संभालना होगा।
नबला

1
मैंने rmसुरक्षित रूप से उपयोग करने और रोकने के लिए अपना उत्तर जोड़ा rm -r /। @JonBrave
alper

1
rm -f --preserve-rootपर्याप्त अच्छा नहीं है ( --preserve-rootशायद वैसे भी डिफ़ॉल्ट है)। मैंने -r / एक उदाहरण के रूप में दिया , क्या होगा अगर यह -r /homeया जो भी हो? आप शायद चाहते हैं rm -f -- $fileToRemove, लेकिन वह बात नहीं है।
जॉनब्रवे

3
जिस तरह से आपने इसका उपयोग किया है, वैरिएबल नाम (एनवायरनमेंट वेरिएबल) के साथ, और कोई उद्धरण नहीं, और कोई सुरक्षा नहीं। और इस सवाल के लिए नहीं, नहीं। अपरिपक्व को उजागर os.system('rm ...')करना बेहद खतरनाक है, क्षमा करें।
जॉनब्रवे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.