सवाल मैं पाइथन में सुरक्षित रूप से नेस्टेड निर्देशिका कैसे बना सकता हूं?


यह जांचने का सबसे शानदार तरीका क्या है कि निर्देशिका में मौजूद एक निर्देशिका मौजूद है या नहीं, और यदि नहीं, तो Python का उपयोग कर निर्देशिका बनाएं? मैंने जो कोशिश की है वह यहां है:

import os

file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)

try:
    os.stat(directory)
except:
    os.mkdir(directory)       

f = file(filename)

किसी भी तरह, मैं चूक गया os.path.exists (धन्यवाद कन्जा, ब्लेयर, और डगलस)। मेरे पास अब यही है:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

क्या "खुला" के लिए कोई झंडा है, जो यह स्वचालित रूप से होता है?


2989
2017-11-07 18:56


मूल


आम तौर पर आपको उस मामले के लिए खाते की आवश्यकता हो सकती है जहां फ़ाइल नाम में कोई निर्देशिका नहीं है। मेरी मशीन dirname ('foo.txt') पर '' देता है, जो अस्तित्व में नहीं है और makedirs () विफल होने का कारण बनता है। - Brian Hawkins
पायथन 2.7 में os.path.mkdir अस्तित्व में नहीं है आईटी इस os.mkdir। - drevicko
यदि पथ मौजूद है, तो न केवल यह जांचने के लिए है कि यह एक निर्देशिका है या नहीं, नियमित फाइल या कोई अन्य वस्तु नहीं है (कई उत्तरों इसे जांचें) यह जांचना भी आवश्यक है कि यह लिखने योग्य है (मुझे यह पता नहीं आया कि यह चेक किया गया है) - miracle173
यदि आप फ़ाइल पथ स्ट्रिंग की मूल निर्देशिका बनाने के लिए यहां आए हैं p, मेरा कोड स्निपेट है: os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True) - Thamme Gowda
इस प्रश्न में उत्तर के मेटा चर्चा - gnat


जवाब:


मैं अच्छे गुणों के साथ दो उत्तरों देखता हूं, प्रत्येक एक छोटी सी खामियों के साथ, इसलिए मैं इसे अपना ले जाऊंगा:

प्रयत्न os.path.exists, और विचार करें os.makedirs सृजन के लिए।

import os
if not os.path.exists(directory):
    os.makedirs(directory)

जैसा कि टिप्पणियों और अन्य जगहों में उल्लेख किया गया है, वहां दौड़ की स्थिति है - यदि निर्देशिका के बीच बनाई गई है os.path.exists और यह os.makedirs कॉल, द os.makedirs एक के साथ असफल हो जाएगा OSError। दुर्भाग्य से, कंबल पकड़ने OSError और निरंतर मूर्खतापूर्ण नहीं है, क्योंकि यह अन्य कारकों के कारण निर्देशिका बनाने में विफलता को अनदेखा कर देगा, जैसे अपर्याप्त अनुमतियां, पूर्ण डिस्क इत्यादि।

एक विकल्प जाल करना होगा OSError और एम्बेडेड त्रुटि कोड की जांच करें (देखें क्या Python के OSError से जानकारी प्राप्त करने का एक क्रॉस-प्लेटफार्म तरीका है):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

वैकल्पिक रूप से, एक सेकंड हो सकता है os.path.exists, लेकिन मान लें कि किसी ने पहली जांच के बाद निर्देशिका बनाई है, फिर इसे दूसरे से पहले हटा दिया - हम अभी भी बेवकूफ हो सकते हैं।

आवेदन के आधार पर, समवर्ती संचालन का खतरा फ़ाइल अनुमतियों जैसे अन्य कारकों द्वारा उत्पन्न खतरे से कम या कम हो सकता है। डेवलपर को कार्यान्वयन चुनने से पहले विकसित होने वाले विशेष आवेदन और इसके अपेक्षित माहौल के बारे में और जानना होगा।


3691
2017-11-07 19:06



कोशिश / सहमत समाधान समाधान सहमत है - Corey Goldberg
याद रखें कि os.path.exists () मुफ़्त नहीं है। यदि सामान्य मामला यह है कि निर्देशिका वहां होगी, तो वह मामला जहां इसे अपवाद के रूप में नहीं माना जाना चाहिए। दूसरे शब्दों में, अपनी फ़ाइल को खोलने और लिखने का प्रयास करें, ओएसईआरआर अपवाद को पकड़ें और, इरनो के आधार पर, अपना makedir () करें और पुनः प्रयास करें या फिर से उठाएं। यह तब तक कोड का डुप्लिकेशंस बनाता है जब तक कि आप स्थानीय विधि में लेखन को लपेट नहीं लेते। - Andrew
os.path.exists भी रिटर्न True एक फाइल के लिए। मैंने इसे संबोधित करने के लिए एक उत्तर पोस्ट किया है। - A-B-B
os.mkdirs() यदि पथ विभाजक गलती से छोड़ा गया है, तो अनचाहे फ़ोल्डर्स बना सकते हैं, वर्तमान फ़ोल्डर अपेक्षित नहीं है, पथ तत्व में पथ विभाजक शामिल है। यदि तुम प्रयोग करते हो os.mkdir() ये बग अपवाद उठाएंगे, जो आपको उनके अस्तित्व में सतर्क करेंगे। - drevicko
तो वास्तविक जवाब होना चाहिए stackoverflow.com/questions/273192/... - user3885927


पायथन 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib.Path.mkdir जैसा उपर्युक्त प्रयोग किया जाता है, निर्देशिका को बनाता है और यदि निर्देशिका पहले से मौजूद है तो अपवाद नहीं उठाता है। यदि आपको माता-पिता की आवश्यकता नहीं है या नहीं चाहते हैं, तो छोड़ दें parents तर्क।

पायथन 3.2+:

का उपयोग करते हुए pathlib:

यदि आप कर सकते हैं, तो वर्तमान स्थापित करें pathlib बैकपोर्ट नामित pathlib2। नामित पुराने अनियंत्रित बैकपोर्ट को इंस्टॉल न करें pathlib। इसके बाद, ऊपर पाइथन 3.5+ अनुभाग देखें और इसका उपयोग करें।

यदि पाइथन 3.4 का उपयोग करना है, भले ही यह आता है pathlib, यह उपयोगी गायब है exist_ok विकल्प। बैकपोर्ट का उद्देश्य एक नया और बेहतर कार्यान्वयन प्रदान करना है mkdir जिसमें यह अनुपलब्ध विकल्प शामिल है।

का उपयोग करते हुए os:

import os
os.makedirs(path, exist_ok=True)

os.makedirs जैसा उपर्युक्त प्रयोग किया जाता है, निर्देशिका को बनाता है और यदि निर्देशिका पहले से मौजूद है तो अपवाद नहीं उठाता है। यह वैकल्पिक है exist_ok केवल डिफ़ॉल्ट तर्क के साथ पायथन 3.2+ का उपयोग करते समय तर्क False। यह तर्क Python 2.x तक 2.7 तक मौजूद नहीं है। इस प्रकार, पाइथन 2.7 के साथ मैन्युअल अपवाद हैंडलिंग की कोई आवश्यकता नहीं है।

पायथन 2.7+:

का उपयोग करते हुए pathlib:

यदि आप कर सकते हैं, तो वर्तमान स्थापित करें pathlib बैकपोर्ट नामित pathlib2। नामित पुराने अनियंत्रित बैकपोर्ट को इंस्टॉल न करें pathlib। इसके बाद, ऊपर पाइथन 3.5+ अनुभाग देखें और इसका उपयोग करें।

का उपयोग करते हुए os:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

जबकि एक बेवकूफ समाधान पहले उपयोग कर सकते हैं os.path.isdir के बाद os.makedirs, उपरोक्त समाधान दो परिचालनों के क्रम को उलट देता है। ऐसा करने में, यह निर्देशिका बनाने के लिए एक डुप्लीकेट प्रयास के साथ एक सामान्य रेस स्थिति को रोकता है, और निर्देशिकाओं से फ़ाइलों को भी असंबद्ध करता है।

ध्यान दें कि अपवाद को कैप्चर करना और उपयोग करना errno सीमित उपयोगिता है क्योंकि OSError: [Errno 17] File exists, अर्थात। errno.EEXIST, दोनों फाइलों और निर्देशिकाओं के लिए उठाया गया है। यह जांचने के लिए कि यह निर्देशिका मौजूद है या नहीं, यह अधिक विश्वसनीय है।

वैकल्पिक:

mkpath नेस्टेड निर्देशिका बनाता है, और निर्देशिका पहले से मौजूद होने पर कुछ भी नहीं करता है। यह पायथन 2 और 3 दोनों में काम करता है।

import distutils.dir_util
distutils.dir_util.mkpath(path)

प्रति बग 10948, इस विकल्प की एक गंभीर सीमा यह है कि यह किसी दिए गए पथ के लिए प्रति पाइथन प्रक्रिया में केवल एक बार काम करता है। दूसरे शब्दों में, यदि आप निर्देशिका बनाने के लिए इसका उपयोग करते हैं, तो पाइथन के अंदर या बाहर से निर्देशिका हटाएं, फिर उपयोग करें mkpath फिर एक ही निर्देशिका को फिर से बनाने के लिए, mkpath पहले ही निर्देशिका को बनाने की अपनी अमान्य कैश की गई जानकारी का चुपचाप उपयोग करेगा, और वास्तव में निर्देशिका को फिर से नहीं बनाएगा। इसके विपरीत, os.makedirs इस तरह के किसी भी कैश पर भरोसा नहीं करता है। कुछ सीमाओं के लिए यह सीमा ठीक हो सकती है।


निर्देशिका के संबंध में मोडयदि आप इसके बारे में परवाह करते हैं, तो कृपया प्रलेखन देखें।


815
2018-01-16 17:31



जहां तक ​​मैं बता सकता हूं कि यह उत्तर हर विशेष मामले में काफी अधिक शामिल है। मैं इसे "अगर नहीं os.path.isdir ()" में लपेटने की योजना बना रहा हूं, हालांकि मुझे लगता है कि निर्देशिका लगभग हर समय मौजूद है और मैं इस तरह के अपवाद से बच सकता हूं। - Charles L.
@CharlesL। यदि आपका कारण प्रदर्शन है, तो डिस्क के डिस्क IO से शायद एक अपवाद सस्ता है। - jpmc26
@ jpmc26 लेकिन निर्माता, अतिरिक्त स्टेटस, उमास्क, lstat करता है जब केवल ओएसईआरओआर फेंकने की जांच करता है। - kwarunek
यह गलत जवाब है, क्योंकि यह एक संभावित एफएस रेस कंड पेश करता है। हारून हॉल से जवाब देखें। - sleepycal
जैसा कि @ स्लीपिकल ने कहा है, यह स्वीकार्य उत्तर के समान दौड़ की स्थिति से ग्रस्त है। अगर त्रुटि और जांच को बढ़ाने के बीच os.path.isdirकोई और फ़ोल्डर को हटा देता है, आप गलत, पुरानी और भ्रमित त्रुटि को बढ़ाएंगे जो फ़ोल्डर मौजूद है। - farmir


कोशिश करने का प्रयास करना और इरनो मॉड्यूल से सही त्रुटि कोड दौड़ की स्थिति से छुटकारा पाता है और क्रॉस-प्लेटफार्म है:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

दूसरे शब्दों में, हम निर्देशिका बनाने की कोशिश करते हैं, लेकिन यदि वे पहले से मौजूद हैं तो हम त्रुटि को अनदेखा करते हैं। दूसरी ओर, किसी भी अन्य त्रुटि की सूचना मिली है। उदाहरण के लिए, यदि आप पहले से ही 'ए' बनाते हैं और इससे सभी अनुमतियां हटाते हैं, तो आपको एक मिल जाएगा OSError के साथ उठाया errno.EACCES (अनुमति अस्वीकार, त्रुटि 13)।


573
2018-02-17 17:17



स्वीकार्य उत्तर वास्तव में खतरनाक है क्योंकि इसमें दौड़ की स्थिति है। हालांकि, यह आसान है, इसलिए यदि आप दौड़ की स्थिति से अनजान हैं, या सोचें कि यह आपके लिए लागू नहीं होगा, तो यह आपका पहला पहला चयन होगा। - Heikki Toivonen
केवल अपवाद उठाते समय exception.errno != errno.EEXIST पथ मौजूद होने पर अनजाने में मामले को अनदेखा कर देगा लेकिन एक गैर-निर्देशिका वस्तु है जैसे फ़ाइल। यदि पथ एक गैर-निर्देशिका वस्तु है तो अपवाद आदर्श रूप से उठाया जाना चाहिए। - A-B-B
ध्यान दें कि उपर्युक्त कोड बराबर है os.makedirs(path,exist_ok=True) - Navin
@ नविन द exist_ok पाइथन 3.2 में पैरामीटर पेश किया गया था। यह पायथन 2.x में मौजूद नहीं है। मैं इसे अपने उत्तर में शामिल कर दूंगा। - A-B-B
@HeikkiToivonen तकनीकी रूप से बोलते हुए, यदि कोई अन्य प्रोग्राम निर्देशिकाओं और फ़ाइलों को एक ही समय में संशोधित कर रहा है, तो आपका प्रोग्राम है, आपका पूरा कार्यक्रम एक विशाल दौड़ की स्थिति है। कोड बनाने के बाद और वास्तव में इसमें फ़ाइलों को रखने से पहले इस निर्देशिका को हटाने से दूसरे प्रोग्राम को रोकने के लिए क्या करना है? - jpmc26


मैं व्यक्तिगत रूप से अनुशंसा करता हूं कि आप इसका उपयोग करें os.path.isdir() के बजाय परीक्षण करने के लिए os.path.exists()

>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False

यदि आपके पास है:

>>> dir = raw_input(":: ")

और एक मूर्ख उपयोगकर्ता इनपुट:

:: /tmp/dirname/filename.etc

... आप नाम की एक निर्देशिका के साथ खत्म होने जा रहे हैं filename.etc जब आप उस तर्क को पास करते हैं os.makedirs() यदि आप के साथ परीक्षण करते हैं os.path.exists()


85
2018-01-14 17:57



यदि आप केवल 'isdir' का उपयोग करते हैं, तो क्या आपको निर्देशिका बनाने का प्रयास करने पर अभी भी कोई समस्या नहीं होगी और एक ही नाम वाली फ़ाइल पहले से मौजूद है? - MrWonderful
@MrWonderful मौजूदा फ़ाइल पर निर्देशिका बनाने के दौरान परिणामस्वरूप अपवाद कॉलर को वापस समस्या को सही ढंग से प्रतिबिंबित करेगा। - Damian Yerrick
यह बुरी सलाह है। देख stackoverflow.com/a/5032238/763269। - Chris Johnson


चेक os.makedirs: (यह सुनिश्चित करता है कि पूरा पथ मौजूद है।)
 इस तथ्य को संभालने के लिए निर्देशिका मौजूद हो सकती है, ओएसईआरआर पकड़ो। (यदि मौजूद है_ओक गलत है (डिफ़ॉल्ट), तो लक्ष्य निर्देशिका पहले से मौजूद है तो एक ओएसईआरआरआर उठाया जाता है।)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass

56
2017-11-07 19:01



कोशिश / छोड़कर, आप निर्देशिका निर्माण में त्रुटियों को मुखौटा करेंगे, उस स्थिति में जब निर्देशिका मौजूद नहीं थी लेकिन किसी कारण से आप इसे नहीं बना सकते - Blair Conrad
यह एकमात्र सुरक्षित तरीका है। - Ali Afshar
OSError यदि पथ एक मौजूदा फ़ाइल या निर्देशिका है तो यहां उठाया जाएगा। मैंने इसे संबोधित करने के लिए एक उत्तर पोस्ट किया है। - A-B-B
यह आधा रास्ते है। आपको उप-त्रुटि स्थिति की जांच करने की आवश्यकता है OSError इसे अनदेखा करने का फैसला करने से पहले। देख stackoverflow.com/a/5032238/763269। - Chris Johnson


इस स्थिति के विनिर्देशों पर अंतर्दृष्टि

आप एक निश्चित फ़ाइल पर एक निश्चित फ़ाइल देते हैं और आप निर्देशिका को फ़ाइल पथ से खींचते हैं। फिर यह सुनिश्चित करने के बाद कि आपके पास निर्देशिका है, आप पढ़ने के लिए फ़ाइल खोलने का प्रयास करते हैं। इस कोड पर टिप्पणी करने के लिए:

filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)

हम बिल्टिन फ़ंक्शन को ओवरराइट करने से बचना चाहते हैं, dir। इसके अलावा, filepath या शायद fullfilepath शायद तुलना में एक बेहतर अर्थपूर्ण नाम है filename तो यह बेहतर लिखा जाएगा:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

आपका अंतिम लक्ष्य इस फ़ाइल को खोलना है, आरंभ में आप लिखने के लिए कहते हैं, लेकिन आप अनिवार्य रूप से इस लक्ष्य (आपके कोड के आधार पर) के पास आ रहे हैं, जो फ़ाइल खोलता है पढ़ना:

if not os.path.exists(directory):
    os.makedirs(directory)
f = file(filename)

पढ़ने के लिए खोलने का मानना

आप उस फाइल के लिए निर्देशिका क्यों बनायेंगे जहां आप वहां रहने की उम्मीद करते हैं और पढ़ सकते हैं?

बस फ़ाइल खोलने का प्रयास करें।

with open(filepath) as my_file:
    do_stuff(my_file)

यदि निर्देशिका या फ़ाइल नहीं है, तो आपको एक मिल जाएगा IOError एक संबंधित त्रुटि संख्या के साथ: errno.ENOENT आपके प्लेटफॉर्म पर ध्यान दिए बिना सही त्रुटि संख्या को इंगित करेगा। यदि आप चाहें तो आप इसे पकड़ सकते हैं, उदाहरण के लिए:

import errno
try:
    with open(filepath) as my_file:
        do_stuff(my_file)
except IOError as error:
    if error.errno == errno.ENOENT:
        print 'ignoring error because directory or file is not there'
    else:
        raise

मान लीजिए कि हम लेखन के लिए खुल रहे हैं

ये है शायद आप क्या चाहते हैं

इस मामले में, हम शायद किसी भी दौड़ की स्थिति का सामना नहीं कर रहे हैं। तो बस जैसे ही आप थे, लेकिन ध्यान दें कि लेखन के लिए, आपको इसके साथ खोलने की जरूरत है w मोड (या a जोड़ने के लिए)। फ़ाइलों को खोलने के लिए संदर्भ प्रबंधक का उपयोग करने के लिए यह एक पायथन सर्वोत्तम अभ्यास भी है।

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

हालांकि, कहें कि हमारे पास कई पायथन प्रक्रियाएं हैं जो अपने सभी डेटा को एक ही निर्देशिका में रखने का प्रयास करती हैं। फिर हम निर्देशिका के निर्माण पर विवाद हो सकता है। उस स्थिति में लपेटना सबसे अच्छा है makedirs ब्लॉक को छोड़कर एक कोशिश में कॉल करें।

import os
import errno
if not os.path.exists(directory):
    try:
        os.makedirs(directory)
    except OSError as error:
        if error.errno != errno.EEXIST:
            raise
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

29
2018-01-22 23:49





पायथन 3.5 से शुरू, pathlib.Path.mkdir एक है exist_ok झंडा:

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

यह निर्देशिका को फिर से बनाता है और यदि निर्देशिका पहले से मौजूद है तो अपवाद नहीं उठाता है।

(बस के रूप में os.makedirs एक मिल गया exists_ok चित्रा 3.2 से शुरू झंडा)।


28
2017-12-14 16:06