मैं पायथन में "ओपन के साथ" का उपयोग करके कई फाइलें कैसे खोल सकता हूं?


671

मैं एक बार में एक दो फाइलें बदलना चाहता हूं, अगर मैं उन सभी को लिख सकता हूं। मैं सोच रहा था कि क्या मैं किसी तरह withबयान के साथ कई खुली कॉल को जोड़ सकता हूं :

try:
  with open('a', 'w') as a and open('b', 'w') as b:
    do_something()
except IOError as e:
  print 'Operation failed: %s' % e.strerror

यदि यह संभव नहीं है, तो इस समस्या का एक सुरुचिपूर्ण समाधान कैसा दिखेगा?

जवाबों:


1051

पायथन 2.7 (या क्रमशः 3.1) के रूप में आप लिख सकते हैं

with open('a', 'w') as a, open('b', 'w') as b:
    do_something()

पायथन के पुराने संस्करणों में, आप कभी-कभी contextlib.nested()घोंसले के संदर्भ प्रबंधकों का उपयोग कर सकते हैं । यह कई गुना फ़ाइलों को खोलने के लिए अपेक्षित के रूप में काम नहीं करेगा, हालांकि - विवरण के लिए लिंक किए गए दस्तावेज़ देखें।


दुर्लभ मामले में जिसे आप एक ही समय में सभी फ़ाइलों की एक चर संख्या खोलना चाहते हैं, आप contextlib.ExitStackपायथन संस्करण 3.3 से शुरू कर सकते हैं :

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # Do something with "files"

अधिकांश समय आपके पास फ़ाइलों का एक चर सेट होता है, आप संभवतः उन्हें एक के बाद एक खोलना चाहते हैं, हालांकि।


5
दुर्भाग्य से, Referencelib.nested डॉक्स के अनुसार, आपको इसे फ़ाइल खोलने के लिए उपयोग नहीं करना चाहिए: "दो फ़ाइलों को खोलने के लिए नेस्टेड () का उपयोग करना एक प्रोग्रामिंग त्रुटि है क्योंकि पहली फ़ाइल को तुरंत बंद नहीं किया जाएगा यदि खोलने के दौरान कोई अपवाद फेंक दिया जाता है। दूसरी फाइल। "
वेरोनिका

41
withफ़ाइलों की एक चर सूची को खोलने के लिए उपयोग करने का एक तरीका है ?
मोनकूट

23
@monkut: बहुत अच्छा प्रश्न (आप वास्तव में इसे एक अलग प्रश्न के रूप में पूछ सकते हैं)। संक्षिप्त उत्तर: हां, ExitStackपायथन 3.3 है। पायथन के किसी भी पुराने संस्करण में ऐसा करने का कोई आसान तरीका नहीं है।
स्वेन मार्नाच

12
क्या इस वाक्यविन्यास अवधि को कई पंक्तियों में रखना संभव है?
tommy.carstensen 14

9
@ tommy.carstensen: आप सामान्य लाइन निरंतरता तंत्र का उपयोग कर सकते हैं । आपको संभवतः अल्पविराम पर ब्रेक लगाने के लिए बैकस्लैश लाइन निरंतरता का उपयोग करना चाहिए, जैसा कि पीईपी 9 द्वारा अनुशंसित है
स्वेन मार्नाच

99

बस के andसाथ बदलें ,और आप कर रहे हैं:

try:
    with open('a', 'w') as a, open('b', 'w') as b:
        do_something()
except IOError as e:
    print 'Operation failed: %s' % e.strerror

3
आपको निर्दिष्ट करना चाहिए कि पायथन के कौन से संस्करण इस वाक्य रचना का समर्थन करते हैं।
क्रेग मैकक्वीन

58

एक बार में या लंबे फ़ाइल पथों के लिए कई फ़ाइलें खोलने के लिए, यह कई लाइनों पर चीजों को तोड़ने के लिए उपयोगी हो सकता है। से अजगर स्टाइल गाइड के रूप में एक और जवाब देने के लिए टिप्पणी में @Sven Marnach ने सुझाव दिया:

with open('/path/to/InFile.ext', 'r') as file_1, \
     open('/path/to/OutFile.ext', 'w') as file_2:
    file_2.write(file_1.read())

1
इस इंडेंटेशन के साथ मुझे मिलता है: "फ्लेक 8: कंटीन्यूअस लाइन ओवर-इंडेंट फॉर विजुअल इंडेंट"
लुईस एम।

@LouisM ऐसा लगता है जैसे आपके संपादक या परिवेश से कुछ आ रहा है, बजाय बेस पायथन के। यदि यह आपके लिए एक समस्या बनी हुई है, तो मैं इससे संबंधित एक नया प्रश्न बनाने और आपके संपादक और पर्यावरण पर अधिक विवरण देने की सलाह दूंगा।
माइकल ओहलोग जूल

3
हाँ, यह निश्चित रूप से मेरा संपादक है, और यह केवल एक चेतावनी है। मैं जो जोर देना चाहता था वह यह है कि आपका इंडेंटेशन PEP8 का अनुपालन नहीं करता है। आपको पहले के साथ संरेखित करने के बजाय 8 रिक्त स्थान के साथ दूसरे खुले () को इंडेंट करना चाहिए।
लुई एम।

2
@LouisM PEP8 एक दिशानिर्देश है , नियम नहीं है, और इस मामले में मैं सबसे निश्चित रूप से इसे अनदेखा करूंगा
Nick

2
हां इसके साथ कोई समस्या नहीं है, यह स्वचालित लिंटर के साथ अन्य लोगों के लिए उपयोगी हो सकता है, हालांकि :)
लुई एम

15

बयानों के साथ नेस्टेड वही काम करेगा, और मेरी राय में, इससे निपटने के लिए अधिक सीधे हैं।

मान लें कि आपके पास inFile.txt है, और इसे दो आउटफाइल में एक साथ लिखना चाहते हैं।

with open("inFile.txt", 'r') as fr:
    with open("outFile1.txt", 'w') as fw1:
        with open("outFile2.txt", 'w') as fw2:
            for line in fr.readlines():
                fw1.writelines(line)
                fw2.writelines(line)

संपादित करें:

मैं नीच का कारण नहीं समझता। मैंने अपना उत्तर प्रकाशित करने से पहले अपने कोड का परीक्षण किया, और यह वांछित के रूप में काम करता है: यह आउटफिल के सभी को लिखता है, जैसे सवाल पूछता है। कोई डुप्लिकेट लेखन या लिखने में विफल। इसलिए मुझे यह जानने के लिए वास्तव में उत्सुकता है कि मेरे उत्तर को गलत, उप-अपनाने या ऐसा कुछ भी क्यों माना जाता है।


1
मैं नहीं जानता कि किसी और ने आपको क्या उकसाया है, लेकिन मैंने आपको अपडेट किया है क्योंकि यह एकमात्र उदाहरण है जिसमें तीन फाइलें (एक इनपुट, दो आउटपुट) थीं, जो कि मेरी जरूरत के अनुसार हुआ।
एडम माइकल वुड

2
हो सकता है कि आप पायथन में नीचे की ओर bcoz हैं। 2.6 आप अधिक पाइथोनिक कोड लिख सकते हैं - gist.github.com/IaroslavR/3d8692e2a11e1ef902d2d8272b88cb8 (क्यों मैं टिप्पणियों में कोड टुकड़ा नहीं डाल सकता?) हम 2018 में बहुत प्राचीन संस्करण हैं;) अतीत
एल रुसो

2
उन पू-पूहिंग पायथन 2.6: सेंटोस 6 (जो कि नवंबर 2020 तक ईओएल नहीं करता है) के लिए एक अनुकूल अनुस्मारक, अभी भी डिफ़ॉल्ट रूप से py2.6 का उपयोग करता है। तो यह उत्तर है (अभी के अनुसार) अभी भी सबसे अच्छा एक आईएमओ है।
बीजे ब्लैक ब्लैक

11

पायथन 3.3 के बाद से, आप सुरक्षित रूप से फ़ाइलों की एक मनमानी संख्या को खोलने केExitStack लिए contextlibमॉड्यूल से वर्ग का उपयोग कर सकते हैं ।

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

वास्तव में, प्रलेखन में उल्लिखित विहित उपयोग-मामला फाइलों की एक गतिशील संख्या का प्रबंधन कर रहा है।

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

यदि आप विवरण में रुचि रखते हैं, तो यह बताने के लिए यहां एक सामान्य उदाहरण दिया गया है कि यह कैसे ExitStackसंचालित होता है:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(len(stack._exit_callbacks)) # number of callbacks called on exit
    nums = [stack.enter_context(x) for x in xs]
    print(len(stack._exit_callbacks))

print(len(stack._exit_callbacks))
print(nums)

आउटपुट:

0
enter X1
enter X2
enter X3
3
exit X3
exit X2
exit X1
0
[1, 2, 3]

3

अजगर 2.6 के साथ यह काम नहीं करेगा, हमें कई फाइलें खोलने के लिए नीचे दिए गए तरीके का उपयोग करना होगा:

with open('a', 'w') as a:
    with open('b', 'w') as b:

1

देर से जवाब (8 साल), लेकिन किसी को एक में कई फ़ाइलों में शामिल होने की तलाश में , निम्नलिखित फ़ंक्शन मदद कर सकता है:

def multi_open(_list):
    out=""
    for x in _list:
        try:
            with open(x) as f:
                out+=f.read()
        except:
            pass
            # print(f"Cannot open file {x}")
    return(out)

fl = ["C:/bdlog.txt", "C:/Jts/tws.vmoptions", "C:/not.exist"]
print(multi_open(fl))

2018-10-23 19:18:11.361 PROFILE  [Stop Drivers] [1ms]
2018-10-23 19:18:11.361 PROFILE  [Parental uninit] [0ms]
...
# This file contains VM parameters for Trader Workstation.
# Each parameter should be defined in a separate line and the
...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.