পাইথনে "উইথ ওপেন" ব্যবহার করে কীভাবে আমি একাধিক ফাইল খুলতে পারি?


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

পাইথন ২.7 (যথাক্রমে ৩.১) আপনি লিখতে পারেন

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
দুর্ভাগ্যক্রমে, কনটেক্সলিব.নেস্টড ডক্স অনুসারে আপনার ফাইলটি খোলার জন্য ব্যবহার করা উচিত নয়: "দুটি ফাইল খোলার জন্য নেস্টেড () ব্যবহার করা একটি প্রোগ্রামিং ত্রুটি কারণ প্রথম ফাইলটি তাত্ক্ষণিকভাবে বন্ধ করা হবে না যদি খোলার সময় কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় দ্বিতীয় ফাইল। "
ওয়ারোনিকা

41
withফাইলগুলির একটি পরিবর্তনশীল তালিকা খোলার জন্য কি কোনও উপায় আছে ?
monkut

23
@ মোমকুট: খুব ভাল প্রশ্ন (আপনি আসলে এটি আলাদা প্রশ্ন হিসাবে জিজ্ঞাসা করতে পারেন)। সংক্ষিপ্ত উত্তর: হ্যাঁ, ExitStackপাইথন ৩.৩ রয়েছে। পাইথনের আগের কোনও সংস্করণে এটি করার সহজ কোনও উপায় নেই।
সোভেন মারনাচ

12
এই সিনট্যাক্স স্প্যান একাধিক লাইন থাকা সম্ভব?
tommy.carstensen

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

একবারে বা দীর্ঘ ফাইল পাথের জন্য অনেকগুলি ফাইল খোলার জন্য, একাধিক লাইনে জিনিস ভাঙ্গা কার্যকর হতে পারে। পাইথন স্টাইল গাইড থেকে @ সাভেন মার্নাচের পরামর্শ অনুসারে অন্য উত্তরে মন্তব্য করুন:

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
এই ইন্ডেন্টেশনটির সাথে আমি পেয়েছি: "flake8: ভিজ্যুয়াল ইনডেন্টের জন্য ধারাবাহিকতা লাইন ওভার-ইনডেন্টেড"
লুই এম

@ লুইসম এটি বেজ পাইথনের পরিবর্তে আপনার সম্পাদক বা পরিবেশ থেকে আসা কিছু বলে মনে হচ্ছে। যদি এটি আপনার পক্ষে সমস্যা অব্যাহত থাকে তবে আমি এটি সম্পর্কিত একটি নতুন প্রশ্ন তৈরি করার এবং আপনার সম্পাদক এবং পরিবেশ সম্পর্কে আরও বিশদ দেওয়ার পরামর্শ দেব।
মাইকেল অহল্রোগ

3
হ্যাঁ এটি অবশ্যই আমার সম্পাদক, এবং এটি কেবল একটি সতর্কতা। আমি যা জোর দিতে চেয়েছি তা হ'ল আপনার ইন্ডেন্টেশনটি PEP8 মেনে চলে না। প্রথমটি দিয়ে সারিবদ্ধ না করে আপনার 8 টি স্পেস দিয়ে দ্বিতীয় খোলা () ইনডেন্ট করা উচিত।
লুই এম

2
@ লুইস পিইপি 8 হ'ল একটি গাইডলাইন , নিয়ম নয় এবং এই ক্ষেত্রে আমি অবশ্যই এটিকে উপেক্ষা করব
নিক

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
হতে পারে আপনি পাইথন> ২.6 এ বোকোজকে নিম্নচূড়িত করেছেন আপনি আরও পাইথোনিক কোড লিখতে পারেন - gist.github.com/IaroslavR/3d8692e2a11e1ef902d2d8277eb88cb8 (কেন আমি মন্তব্যগুলিতে কোড টুকরোটি sertোকাতে পারছি না ?!) আমরা 2018 এ রয়েছি তাই প্রাচীন সংস্করণে অতীত
এল রুসো

2
সেই পু-পোহিং অজগর ২.6: সেন্টোস ((যা নভেম্বর ২০২০ পর্যন্ত ইওএল হয় না) এর একটি বন্ধুত্বপূর্ণ অনুস্মারক, এখনও ডিফল্টরূপে পাইপ .6..6 ব্যবহার করে। সুতরাং এই উত্তরটি এখনই (এখনও হিসাবে) সেরা সামগ্রিকভাবে একটি আইএমও।
বিজে ব্ল্যাক

11

পাইথন ৩.৩ থেকে আপনি মডিউল 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

পাইথন ২.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
...
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.