पायथन में वास्तविक फ़ाइल बनाए बिना अस्थायी फ़ाइल नाम उत्पन्न करें


98

स्टैकओवरफ्लो में प्रश्न संख्या , 10501247 , पायथन में अस्थायी फ़ाइल बनाने का उत्तर देता है।
मुझे केवल अपने मामले में अस्थायी फ़ाइल नाम की आवश्यकता है।
Tempfile.NamedTemporaryFile () रिटर्न फाइल हैंडल वास्तविक फ़ाइल निर्माण के बाद।
क्या केवल फ़ाइल नाम प्राप्त करने का कोई तरीका है?

# Trying to get temp file path
tf = tempfile.NamedTemporaryFile()
temp_file_name = tf.name
tf.close()
# Here is my real purpose to get the temp_file_name
f = gzip.open(temp_file_name ,'wb')
...

7
NamedTemporaryFileएक अद्वितीय नाम की गारंटी देता है (शायद) इसे आज़माकर और मौजूद होने पर पुनः प्रयास करके। सिर्फ एक नाम प्राप्त करने की गारंटी नहीं होगी कि आप वास्तव में बाद में फ़ाइल बना सकते हैं, आप अपने नाम से पहले उसी नाम का उपयोग करके किसी और की दौड़ की स्थिति के लिए खोल रहे हैं।
जोआचिम इस्कसन

5
@ जोशिम सच, यहां एक दौड़ की स्थिति है और इससे बचने के लिए प्राथमिकता दी जाएगी। हालांकि, कभी-कभी आपको एक अस्थायी फ़ाइल नाम को एक फ़ंक्शन (आंतरिक रूप से खुली हो रही फ़ाइल) पास करना पड़ता है। एक अच्छा यादृच्छिक नाम होने से यह बेहतर संभावना है कि दौड़ की स्थिति एक गैर-मुद्दा होगी। मुझे लगता है कि दौड़ की स्थिति की विफलता की संभावना को कम करने के लिए एक अच्छा अस्थायी नाम प्रदान करने की वैध आवश्यकता है। बेशक, चल रही प्रक्रिया और कार्य के आधार पर एक अच्छा उपसर्ग और प्रत्यय जोड़ना एक टकराव की कम संभावना प्रदान करेगा।
पॉलीमेश

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

टैरिफाइल का उपयोग करें और इसे फाइलबज पास करें
विर्मवुड

जवाबों:


67

यदि आप एक अस्थायी फ़ाइल नाम चाहते हैं, तो आप केवल आंतरिक अस्थायी फ़ंक्शन कह सकते हैं _get_candidate_names():

import tempfile

temp_name = next(tempfile._get_candidate_names())
% e.g. px9cp65s

nextफिर से कॉल करना, एक और नाम वापस करेगा, आदि। यह आपको अस्थायी फ़ोल्डर का रास्ता नहीं देता है। डिफ़ॉल्ट 'tmp' निर्देशिका प्राप्त करने के लिए, का उपयोग करें:

defult_tmp_dir = tempfile._get_default_tempdir()
% results in: /tmp 

3
एक अस्थायी निर्देशिका बनाने का बेहतर तरीका है temp_dir = tempfile.mkdtemp(prefix='some-prefix_')जो सुरक्षित रूप से एक अस्थायी निर्देशिका बनाएगा और पूर्ण पथ के साथ एक स्ट्रिंग लौटाएगा।
इमानुएल आई सेप

3
यह इंगित करना महत्वपूर्ण है कि next(tempfile._get_candidate_names())जरूरी नहीं कि एक गैर-मौजूद पथ पर वापस लौटा जाए, यही कारण है कि उपयोगकर्ता-स्तर के अस्थायी इंटरफ़ेस कई नामों की कोशिश कर सकते हैं जब तक कि अप्रयुक्त एक नहीं मिलता है :
एली कोरविगो

1
कोई tempfile.gettempdir()निजी के बजाय सार्वजनिक उपयोग कर सकता है tempfile._get_default_tempdir()
flank

@EmanuelEy यह याद रखना महत्वपूर्ण है tempfile.mkdtempकि उपयोगकर्ता का उपयोग करते समय अस्थायी निर्देशिका और इसकी सामग्री को हटाने के लिए जिम्मेदार है जब इसके साथ किया जाता है।
डेनियल ब्रौन

46

मुझे लगता है कि ऐसा करने का सबसे आसान, सबसे सुरक्षित तरीका कुछ इस तरह है:

path = os.path.join(tempfile.mkdtemp(), 'something')

एक अस्थायी निर्देशिका बनाई जाती है जिसे केवल आप ही एक्सेस कर सकते हैं, इसलिए कोई सुरक्षा समस्याएँ नहीं होनी चाहिए, लेकिन इसमें कोई फ़ाइल नहीं बनाई जाएगी, इसलिए आप केवल उस निर्देशिका में कोई फ़ाइल नाम चुन सकते हैं जिसे आप बनाना चाहते हैं।

संपादित करें: पायथन 3 में आप अब tempfile.TemporaryDirectory()आपके लिए विलोपन को संभालने के लिए एक संदर्भ प्रबंधक के रूप में उपयोग कर सकते हैं :

with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, 'something')
  # use path

1
जैसा कि डैनियल ब्रौन ने ऊपर उल्लेख किया है: tempfile.mkdtempउपयोगकर्ता का उपयोग करते समय यह याद रखना महत्वपूर्ण है कि अस्थायी निर्देशिका और इसकी सामग्री को हटाने के लिए जब इसके साथ किया जाता है।
बिटकॉइनर

4
यदि आप tempfile.TemporaryDirectory()एक संदर्भ प्रबंधक के रूप में उपयोग करते हैं , तो यह आपके लिए हटा दिया जाएगा।
गेरिट

17

इसमें थोड़ी देर हो सकती है, लेकिन क्या इसमें कुछ गलत है?

import tempfile
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as tmpfile:
    temp_file_name = tmpfile.name
f = gzip.open(temp_file_name ,'wb')

37
यह कोड वास्तव में अपना नाम पाने के लिए अस्थायी फ़ाइल बनाएगा, जबकि सवाल में यह कहता है without creating actual file in Python
जैकब कुकुल

यह इस सवाल का जवाब नहीं देता है
herve

8

tempfile.mktemp() यह करो।

लेकिन ध्यान दें कि यह पदावनत है। हालाँकि, यह फ़ाइल नहीं बनाएगा और इसका उपयोग करने की तुलना में यह एक सार्वजनिक कार्य है _get_candidate_names()

इसका कारण यह बताया गया है कि यह कॉल करने और वास्तव में फ़ाइल बनाने की कोशिश के बीच के समय के अंतराल के कारण है। हालांकि मेरे मामले में उस की संभावना इतनी पतली है और भले ही वह विफल हो जाए जो स्वीकार्य होगा। लेकिन अपने usecase के लिए मूल्यांकन करना आपके ऊपर है।


1
"भले ही यह असफल हो कि स्वीकार्य होगा"; दौड़ की स्थिति केवल विफलता का जोखिम नहीं है, यह एक सुरक्षा जोखिम है ( tempfile.mktempप्रलेखन देखें )। ताकि इसे स्वीकार्य न समझा जाए।
bignose

4
@bignose यह एक संभावित सुरक्षा मुद्दा है। यह इस बात पर निर्भर करता है कि आप क्या करना चाहते हैं, आप जिस निष्पादन वातावरण में हैं, आदि। उसने कहा: यह कुछ करने के लिए अधिक सुरक्षित हो सकता है जैसे os.path.join(tempfile.mkdtemp(), 'something')कि कम से कम निर्देशिका बनाई गई है (और आपके द्वारा स्वामित्व, मैं अनुमान लगाता हूं)।
एलेक

5

पिछले उत्तरों को मिलाकर मेरा हल है:

def get_tempfile_name(some_id):
    return os.path.join(tempfile.gettempdir(), next(tempfile._get_candidate_names()) + "_" + some_id)

some_idयदि आपके लिए आवश्यक न हो तो वैकल्पिक बनाएं ।


फिर, उम्मीदवार के नाम वास्तव में उपलब्ध नहीं हो सकते हैं। यह सही उत्तर है: stackoverflow.com/a/45803022/6387880
j4hangir

1
हालांकि, संभावना है कि किसी को यादृच्छिक नाम बनाने की आवश्यकता है। फिर भी, यह सुनिश्चित करने के लिए, यदि _get_candidate_names()मौजूद नहीं है , तो कुछ अर्ध-यादृच्छिक स्ट्रिंग जनरेटर के लिए डिफ़ॉल्ट हो सकता है। उदाहरण के लिए कुछ uuid।
जुआनमीरोक्स

4

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

तो इस स्थिति में करने के लिए सुरक्षित चीज पूर्ण GzipFile () कंस्ट्रक्टर का उपयोग करना है, जिस पर हस्ताक्षर हैं GzipFile( [filename[, mode[, compresslevel[, fileobj]]]])। तो यदि आप चाहें तो आप इसे ओपन फाइलोबज, और एक फ़ाइलनाम भी पास कर सकते हैं। विवरण के लिए gzip डॉक्स देखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.