পাইথন "উইথ" স্টেটমেন্টটি কীসের জন্য ডিজাইন করা হয়েছে?


418

আমি withআজ প্রথমবারের জন্য পাইথন স্টেটমেন্ট জুড়ে এসেছি। আমি বেশ কয়েক মাস ধরে পাইথনকে হালকাভাবে ব্যবহার করছি এবং এর অস্তিত্ব সম্পর্কেও জানতাম না! এর কিছুটা অস্পষ্ট স্থিতি দেওয়া, আমি ভেবেছিলাম এটি জিজ্ঞাসা করার উপযুক্ত হবে:

  1. পাইথন withবিবৃতিটি ব্যবহারের জন্য ডিজাইন করা কী ?
  2. আপনি উত্তর দিবেন না আপনি উত্তর দিবেন না?
  3. আমার কি সচেতন হওয়া দরকার, বা এর ব্যবহারের সাথে সম্পর্কিত সাধারণ অ্যান্টি-প্যাটার্নগুলি আছে? এটির try..finallyচেয়ে ভাল ব্যবহারের ক্ষেত্রে কোন ক্ষেত্রে with?
  4. কেন এটি আরও ব্যাপকভাবে ব্যবহৃত হয় না?
  5. কোন স্ট্যান্ডার্ড গ্রন্থাগার ক্লাস এটির সাথে সামঞ্জস্যপূর্ণ?

5
কেবল রেকর্ডের জন্য, এখানেwith পাইথন 3 ডকুমেন্টেশন রয়েছে।
আলেক্সি

জাভা ব্যাকগ্রাউন্ড থেকে আগত, এটি জাভাতে সম্পর্কিত " সংস্থানসমূহের সাথে চেষ্টা" হিসাবে মনে রাখতে আমাকে সহায়তা করে , এমনকি যদি এটি সম্পূর্ণ সঠিক নাও হয়।
vefthym

উত্তর:


399
  1. আমার বিশ্বাস আমি এর আগে অন্য ব্যবহারকারীদের দ্বারা এর জবাব ইতিমধ্যে দেওয়া হয়েছে, সুতরাং আমি কেবল এটি সম্পূর্ণতার জন্য যুক্ত করেছি: withবিবৃতিটি তথাকথিত প্রসঙ্গ পরিচালকদের সাধারণ প্রস্তুতি এবং ক্লিনআপ কার্যগুলি আবশ্যক করে ব্যতিক্রম হ্যান্ডলিংকে সহজ করে তোলে । আরও বিস্তারিত পিইপি 343 পাওয়া যাবে । উদাহরণস্বরূপ, openবিবৃতিটি একটি প্রবন্ধ পরিচালক নিজেই, যা আপনাকে একটি ফাইল খুলতে দেয়, যতক্ষণ না withআপনি যেখানে এটি ব্যবহার করেছেন সেই বিবৃতিটির প্রসঙ্গে কার্যকর হওয়া অবধি এটি চালিয়ে যেতে দেয় এবং আপনি প্রসঙ্গটি ছাড়ার সাথে সাথেই এটি বন্ধ করে দেন, কোনও ব্যতিক্রমের কারণে বা নিয়মিত নিয়ন্ত্রণ প্রবাহের সময় আপনি এটিকে রেখে গেছেন তা বিবেচ্য নয়। withবিবৃতি এইভাবে উপায় একই রকম ব্যবহার করা যেতে পারে RAII প্যাটার্ন C ++: কিছু রিসোর্স দ্বারা অর্জিত হয়withবিবৃতি এবং প্রকাশিত হলে আপনি withপ্রসঙ্গটি ছেড়ে যান ।

  2. কয়েকটি উদাহরণ হ'ল : ফাইল ব্যবহার করে ফাইল with open(filename) as fp:খুলুন, লক ব্যবহার করে with lock:(যেখানে এর lockউদাহরণ রয়েছে threading.Lock) অর্জন করা। এছাড়াও আপনি ব্যবহার করে আপনার নিজস্ব প্রসঙ্গের পরিচালকদের গঠন করা যেতে পারে contextmanagerথেকে প্রসাধক contextlib। উদাহরণস্বরূপ, আমি প্রায়শই এটি ব্যবহার করি যখন আমাকে বর্তমান ডিরেক্টরিটি অস্থায়ীভাবে পরিবর্তন করতে হবে এবং তারপরে আমি যেখানে ছিলাম সেখানে ফিরে আসতে হবে:

    from contextlib import contextmanager
    import os
    
    @contextmanager
    def working_directory(path):
        current_dir = os.getcwd()
        os.chdir(path)
        try:
            yield
        finally:
            os.chdir(current_dir)
    
    with working_directory("data/stuff"):
        # do something within data/stuff
    # here I am back again in the original working directory

    এখানে আরেকটি উদাহরণ সাময়িকভাবে পুননির্দেশনা এর sys.stdin, sys.stdoutএবং sys.stderrঅন্য কোনো ফাইল হ্যান্ডেল এবং তাদের পুনরুদ্ধার পরে:

    from contextlib import contextmanager
    import sys
    
    @contextmanager
    def redirected(**kwds):
        stream_names = ["stdin", "stdout", "stderr"]
        old_streams = {}
        try:
            for sname in stream_names:
                stream = kwds.get(sname, None)
                if stream is not None and stream != getattr(sys, sname):
                    old_streams[sname] = getattr(sys, sname)
                    setattr(sys, sname, stream)
            yield
        finally:
            for sname, stream in old_streams.iteritems():
                setattr(sys, sname, stream)
    
    with redirected(stdout=open("/tmp/log.txt", "w")):
         # these print statements will go to /tmp/log.txt
         print "Test entry 1"
         print "Test entry 2"
    # back to the normal stdout
    print "Back to normal stdout again"

    এবং পরিশেষে, অন্য একটি উদাহরণ যা একটি অস্থায়ী ফোল্ডার তৈরি করে এবং প্রসঙ্গটি রেখে যাওয়ার সময় এটি পরিষ্কার করে:

    from tempfile import mkdtemp
    from shutil import rmtree
    
    @contextmanager
    def temporary_dir(*args, **kwds):
        name = mkdtemp(*args, **kwds)
        try:
            yield name
        finally:
            shutil.rmtree(name)
    
    with temporary_dir() as dirname:
        # do whatever you want

20
RAII এর সাথে তুলনা যুক্ত করার জন্য ধন্যবাদ। একজন সি ++ প্রোগ্রামার হিসাবে আমাকে যা জানার দরকার ছিল সব বলেছে।
ফ্রেড থমসন

ঠিক আছে তাই আমাকে এই পরিষ্কার করা যাক। আপনি বলছেন যে withবিবৃতিটি এর নীচের নির্দেশাবলী সম্পূর্ণ না হওয়া অবধি ডেটা সহ একটি ভেরিয়েবল পূরণ করার জন্য ডিজাইন করা হয়েছে, এবং তারপরে ভেরিয়েবলটি মুক্ত করবেন?
Musixauce3000

কারণ আমি এটি একটি পাই স্ক্রিপ্ট খোলার জন্য ব্যবহার করেছি। with open('myScript.py', 'r') as f: pass। আমি পরিবর্তনশীল কল করতে পারবেন হবে বলে আশা করা f, ডকুমেন্ট লেখা সামগ্রী দেখতে হিসাবে এই যদি ডকুমেন্ট নির্ধারিত হয় কি প্রদর্শিত হবে fএকটি নিয়মিত মাধ্যমে openবিবৃতি: f = open('myScript.py').read()। কিন্তু এর পরিবর্তে আমি নিম্নলিখিত করেছেন: <_io.TextIOWrapper name='myScript.py' mode='r' encoding='cp1252'>। এর মানে কী?
Musixauce3000

3
@ Musixauce3000 - ব্যবহার withকরে readআসল ফাইলের প্রয়োজনীয়তা মুছে না । withকল open- এটা আপনি এটি দিয়ে যা করতে হবে তা জানে না - আপনি একটি উদাহরণস্বরূপ চাইতে কাজ করতে চান করতে পারেন।
টনি সাফলক 66

@ Musixauce3000 withবিবৃতিটি ডেটা সহ একটি ভেরিয়েবল পূরণ করতে পারে বা এর অধীন নির্দেশাবলী সম্পূর্ণ না হওয়া অবধি পরিবেশে কিছু অন্য পরিবর্তন করতে পারে এবং তারপরে যে কোনও ধরণের ক্লিনআপ প্রয়োজন হয়। যে ধরণের ক্লিনআপ করা যায় সেগুলি হ'ল খোলা ফাইল বন্ধ করা বা @ টমাসের উদাহরণ হিসাবে যেমন আপনি আগে যেখানে ছিলেন ডিরেক্টরিগুলি পরিবর্তন করা ইত্যাদি Py যেহেতু পাইথনের আবর্জনা সংগ্রহ রয়েছে তাই ভেরিয়েবলকে মুক্ত করা গুরুত্বপূর্ণ নয় ব্যবহারের ক্ষেত্রে. withসাধারণত পরিষ্কার ধরণের অন্যান্য ধরণের জন্য ব্যবহৃত হয়।
বব স্টেইনক

89

আমি দুটি আকর্ষণীয় বক্তৃতা পরামর্শ করব:

1.with বক্তব্য প্রসঙ্গে পরিচালক দ্বারা সংজ্ঞায়িত পদ্ধতি একটি ব্লক সঞ্চালনের মোড়ানো করতে ব্যবহৃত হয়। এটি try...except...finallyসুবিধাজনক পুনরায় ব্যবহারের জন্য সাধারণ ব্যবহারের নিদর্শনগুলিকে এনক্যাপসুলেটেড করার অনুমতি দেয় ।

২. আপনি কিছু করতে পারেন:

with open("foo.txt") as foo_file:
    data = foo_file.read()

অথবা

from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
   do_something()

বা (পাইথন ৩.১)

with open('data') as input_file, open('result', 'w') as output_file:
   for line in input_file:
     output_file.write(parse(line))

অথবা

lock = threading.Lock()
with lock:
    # Critical section of code

৩. আমি এখানে কোনও অ্যান্টিপ্যাটার্ন দেখি না। পাইথনে ডুব
উদ্ধৃত :

চেষ্টা..ফিনালি ভাল। সঙ্গে ভাল।

৪. আমি অনুমান করি যে এটি try..catch..finallyঅন্যান্য ভাষা থেকে বিবৃতি ব্যবহারের জন্য প্রোগ্রামারদের অভ্যাসের সাথে সম্পর্কিত ।


4
থ্রেডিং সিঙ্ক্রোনাইজেশন অবজেক্টের সাথে আপনি যখন ডিল করছেন তখন এটি সত্যই নিজের মধ্যে আসে। পাইথনে তুলনামূলকভাবে বিরল, তবে যখন আপনার এগুলি প্রয়োজন হয় তখন আপনার সত্যই প্রয়োজন হয় with
অবশেষে

1
diveintopython.org ডাউন (স্থায়ীভাবে?)। এ মিরর diveintopython.net
snuggles

একটি উত্তরের উত্তরের উদাহরণ, ওপেন ফাইলটি এমন একটি প্রধান উদাহরণ যা খোলার পর্দার আড়ালে দেখায়, io, ফাইল অপারেশনগুলি বন্ধ করে একটি কাস্টম রেফারেন্স নাম দিয়ে পরিষ্কারভাবে লুকানো থাকে
Angry 84

40

পাইথন withস্টেটমেন্টটি Resource Acquisition Is Initializationসাধারণভাবে C ++ এ ব্যবহৃত আইডিয়ামটির ভাষা সমর্থন করে । অপারেটিং সিস্টেমের রিসোর্সগুলি নিরাপদ অধিগ্রহণ এবং মুক্তির অনুমতি দেওয়ার উদ্দেশ্যে এটি করা হয়েছে।

withবক্তব্য সুযোগ / অবরুদ্ধ মধ্যে সম্পদ সৃষ্টি করে। আপনি ব্লকের মধ্যে থাকা সংস্থানগুলি ব্যবহার করে আপনার কোডটি লিখেছেন। যখন ব্লকটি প্রস্থান করে তখন ব্লকের কোডের ফলাফল নির্বিশেষে সংস্থানগুলি পরিষ্কারভাবে প্রকাশ করা হয় (তা হ'ল ব্লকটি সাধারণত ব্যতিক্রম হয় বা ব্যতিক্রমের কারণে)।

পাইথন লাইব্রেরির অনেক সংস্থান যা withবিবৃতিতে প্রয়োজনীয় প্রোটোকল মেনে চলে এবং তাই এটি বাইরের বাইরে ব্যবহার করতে পারে। তবে যে কেউ রিসোর্সগুলি তৈরি করতে পারেন যা সঠিকভাবে নথিভুক্ত প্রোটোকল: পিইপি 0343 প্রয়োগ করে বিবৃতি দিয়ে ব্যবহার করা যেতে পারে

যখনই আপনি আপনার অ্যাপ্লিকেশনটিতে এমন সংস্থানগুলি অর্জন করবেন যা ফাইল, নেটওয়ার্ক সংযোগ, লক এবং এর মতো স্পষ্টভাবে ত্যাগ করা উচিত।


27

আবার সম্পূর্ণতার জন্য আমি withবিবৃতিগুলির জন্য আমার সবচেয়ে দরকারী ব্যবহারের কেস যুক্ত করব ।

আমি প্রচুর বৈজ্ঞানিক কম্পিউটিং করি এবং কিছু ক্রিয়াকলাপের জন্য আমার Decimalস্বেচ্ছাসেবী নির্ভুল গণনার জন্য লাইব্রেরিটি প্রয়োজন । আমার কোডের কিছু অংশে আমার উচ্চ নির্ভুলতা প্রয়োজন এবং বেশিরভাগ অংশের জন্য আমার কম নির্ভুলতা প্রয়োজন।

আমি আমার ডিফল্ট নির্ভুলতা কম সংখ্যায় সেট করেছি এবং তারপরে withকয়েকটি বিভাগের আরও সুনির্দিষ্ট উত্তর পেতে ব্যবহার করব :

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision

আমি হাইপারজোমেট্রিক টেস্টের সাথে এটি প্রচুর ব্যবহার করি যার ফলে ফ্যাক্টরিয়ালগুলি তৈরির ফলে বৃহত সংখ্যার বিভাজন প্রয়োজন। আপনি জিনোমিক স্কেল গণনা করার সময় আপনাকে রাউন্ড-অফ এবং ওভারফ্লো ত্রুটি সম্পর্কে সতর্ক থাকতে হবে।


26

একটি antipattern একটি উদাহরণ ব্যবহার করতে হতে পারে withএকটি লুপ ভিতরে যখন এটি আরও দক্ষ হবে আছে withবাহিরে লুপ

উদাহরণ স্বরূপ

for row in lines:
    with open("outfile","a") as f:
        f.write(row)

বনাম

with open("outfile","a") as f:
    for row in lines:
        f.write(row)

প্রথম উপায়টি প্রতিটিটির জন্য ফাইলটি খোলার এবং বন্ধ করা rowযা দ্বিতীয় উপায়ে তুলনায় পারফরম্যান্স সমস্যার কারণ হতে পারে এবং একবারে ফাইলটি বন্ধ করে দেয়।


10

পিইপি 343 দেখুন - 'উইথ' স্টেটমেন্টটির শেষে একটি উদাহরণ বিভাগ রয়েছে।

... পাইথন ভাষার সাথে "নতুন" বিবৃতিটি চেষ্টা / অবশেষে বিবৃতিগুলির স্ট্যান্ডার্ড ব্যবহারগুলি তৈরি করা সম্ভব করার জন্য with


5

পয়েন্ট 1, 2, এবং 3 যুক্তিসঙ্গতভাবে ভালভাবে কভার করা হচ্ছে:

4: এটি তুলনামূলকভাবে নতুন, কেবল পাইথন 2.6 + (অথবা পাইথন 2.5 ব্যবহার করে from __future__ import with_statement) এ উপলব্ধ


4

বিবৃতি সহ তথাকথিত প্রসঙ্গ পরিচালকদের সাথে কাজ করে:

http://docs.python.org/release/2.5.2/lib/typecontextmanager.html

ধারণাটি হ'ল 'সাথে' ব্লক রেখে যাওয়ার পরে প্রয়োজনীয় পরিচ্ছন্নতার মাধ্যমে ব্যতিক্রম হ্যান্ডলিংটিকে সহজতর করা। পাইথনের কিছু বিল্ট-ইন ইতিমধ্যে প্রসঙ্গ পরিচালক হিসাবে কাজ করে।


3

আউট-অফ-বক্স সমর্থনের জন্য আরেকটি উদাহরণ, এবং যে প্রথমে একটি বিট বিভ্রান্তিকর যখন আপনি বিল্ট-ইন ভাবে ব্যবহার করা হয় হতে পারে open()আচরণ করবে হয় connectionযেমন জনপ্রিয় ডাটাবেসের মডিউল অবজেক্ট:

connectionবস্তু প্রসঙ্গ পরিচালকদের এবং যেমন আউট-অফ-বক্স ব্যবহার করা যেতে পারে একটি with-statementঅবশ্য উপরে দয়া করে মনে রাখবেন ব্যবহার যখন:

যখন with-blockসম্পূর্ণ হয়, হয় ব্যতিক্রম বা ছাড়াই, সংযোগটি বন্ধ হয় না । যদি with-blockকোনও ব্যতিক্রম সমাপ্ত হয় তবে লেনদেনটি আবার ঘুরিয়ে দেওয়া হয়, অন্যথায় লেনদেনটি কমিট হয়।

এর অর্থ হ'ল প্রোগ্রামারকে নিজেরাই এই সংযোগটি বন্ধ করার জন্য যত্ন নিতে হবে, তবে একটি সংযোগ অর্জন করতে এবং একাধিকটিতে এটি ব্যবহার করতে দেয় with-statements, যেমন সাইকোপজিডক্সে দেখানো হয়েছে :

conn = psycopg2.connect(DSN)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL1)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL2)

conn.close()

উপরের উদাহরণে, আপনি নোট করুন যে এর cursorবস্তুগুলি psycopg2প্রসঙ্গ পরিচালকও রয়েছে। আচরণ সম্পর্কিত প্রাসঙ্গিক ডকুমেন্টেশন থেকে:

যখন কোনও cursorপ্রস্থান বের হয় with-blockএটি বন্ধ হয়ে যায়, অবশেষে এর সাথে যুক্ত কোনও সংস্থান প্রকাশ করে। লেনদেনের অবস্থা প্রভাবিত হয় না।


3

পাইথনে সাধারণত " উইথ " স্টেটমেন্টটি একটি ফাইল খোলার জন্য, ফাইলটিতে উপস্থিত ডেটা প্রক্রিয়াজাতকরণ এবং ক্লোজ () পদ্ধতিটি কল না করে ফাইলটি বন্ধ করতে ব্যবহৃত হয়। "সহ" বিবৃতিটি ক্লিনআপ ক্রিয়াকলাপ সরবরাহ করে ব্যতিক্রমটিকে পরিচালনা সহজতর করে তোলে।

এর সাথে সাধারণ ফর্ম:

with open(“file name”, mode”) as file-var:
    processing statements

দ্রষ্টব্য: ফাইল- var.close () উপর ক্লোজ () কল করে ফাইলটি বন্ধ করার দরকার নেই)

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