একটি সম্পূর্ণ ফাইল পড়া ফাইল হ্যান্ডেল খোলা ছেড়ে দেয়?


372

আপনি যদি একটি পুরো ফাইলটি পড়েন content = open('Path/to/file', 'r').read()তবে স্ক্রিপ্টটি বের না হওয়া অবধি ফাইল হ্যান্ডেলটি কী খোলা থাকবে? পুরো ফাইলটি পড়ার জন্য আরও কি সংক্ষিপ্ত পদ্ধতি আছে?

উত্তর:


585

এই প্রশ্নের উত্তর কিছুটা নির্দিষ্ট পাইথন প্রয়োগের উপর নির্ভর করে।

এগুলি কী, তা বোঝার জন্য প্রকৃত fileঅবজেক্টের দিকে বিশেষ মনোযোগ দিন । আপনার কোডে object বস্তুটি কেবল একবার, একটি অভিব্যক্তিতে উল্লেখ করা হয়েছিল এবং read()কল ফিরে আসার সাথে সাথেই অ্যাক্সেসযোগ্য হয় ।

এর অর্থ এই যে ফাইল ফাইলটি আবর্জনা। কেবলমাত্র অবশিষ্ট প্রশ্ন "আবর্জনা সংগ্রহকারী কখন ফাইলটি সংগ্রহ করবেন?"

সিপিথনে, যা রেফারেন্স কাউন্টার ব্যবহার করে, এই ধরণের আবর্জনা তাত্ক্ষণিকভাবে লক্ষ্য করা যায়, এবং তাই এটি অবিলম্বে সংগ্রহ করা হবে। এটি অন্যান্য অজগর বাস্তবায়নের ক্ষেত্রে সাধারণত সত্য নয়।

ফাইলটি বন্ধ রয়েছে কিনা তা নিশ্চিত করার জন্য একটি আরও ভাল সমাধান, এই প্যাটার্নটি:

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

যা ব্লক শেষ হওয়ার সাথে সাথেই ফাইলটি সর্বদা বন্ধ করে দেবে; এমনকি যদি একটি ব্যতিক্রম ঘটে।

সম্পাদনা করুন: এটিতে একটি সূক্ষ্ম বিন্দু রাখার জন্য:

অন্য চেয়ে file.__exit__(), যা "স্বয়ংক্রিয়ভাবে" একটি ডেকে withপ্রসঙ্গ ম্যানেজার সেটিং শুধুমাত্র অন্যান্য উপায় যে file.close()স্বয়ংক্রিয়ভাবে বলা হয় (স্পষ্টভাবে নিজেকে এটি আহ্বান ছাড়া অন্য যে) মাধ্যমে হল file.__del__()। এটি আমাদের কখন __del__()ডাকা হয় এমন প্রশ্নের দিকে নিয়ে যায় ?

একটি সঠিকভাবে লিখিত প্রোগ্রাম ধরে নিতে পারে না যে ফাইনালাইজারগুলি প্রোগ্রামের সমাপ্তির আগে যে কোনও পর্যায়ে চলে।

- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203

নির্দিষ্টভাবে:

বস্তু কখনই স্পষ্টভাবে ধ্বংস হয় না; যাইহোক, যখন তারা অ্যাক্সেসযোগ্য হয় তখন তারা আবর্জনা সংগ্রহ করা হতে পারে। কোনও প্রয়োগকে আবর্জনা সংগ্রহ স্থগিত করার বা এটি সম্পূর্ণরূপে বাদ দেওয়ার মঞ্জুরি দেওয়া হয় - যতক্ষণ না এখনও অ্যাক্সেসযোগ্য এমন কোনও বস্তু সংগ্রহ করা হয় না, ততক্ষণ আবর্জনা সংগ্রহ কীভাবে কার্যকর করা হয় তা বাস্তবায়নের মানের বিষয়।

[...]

সিপিথন বর্তমানে চক্রাকারে সংযুক্ত আবর্জনা সনাক্ত করতে (alচ্ছিক) বিলম্ব সনাক্তকরণের সাথে একটি রেফারেন্স-কাউন্টিং স্কিম ব্যবহার করে, যা বেশিরভাগ অবজেক্টগুলি অ্যাক্সেসযোগ্য হওয়ার সাথে সাথে সংগ্রহ করে, তবে বিজ্ঞপ্তিযুক্ত রেফারেন্সযুক্ত আবর্জনা সংগ্রহের গ্যারান্টিযুক্ত নয়।

- https://docs.python.org/3.5/references/datamodel.html#objects-values-and-types

(জোর আমার)

তবে এটি যেমনটি বোঝায়, অন্যান্য বাস্তবায়নের অন্যান্য আচরণ থাকতে পারে। উদাহরণস্বরূপ, PyPy হয়েছে 6 বিভিন্ন গার্বেজ কালেকশন বাস্তবায়নের !


24
কিছুক্ষণের জন্য, সত্যই অন্য পাইথন বাস্তবায়ন হয়নি; তবে বাস্তবায়নের বিশদগুলির উপর নির্ভর করা আসলে পাইথোনিক নয়।
কার্ল নচেটেল

এটি এখনও বাস্তবায়ন-নির্দিষ্ট, বা এটি ইতিমধ্যে মানক করা হয়েছিল? এই __exit__()জাতীয় ক্ষেত্রে কল না করা কোনও ডিজাইনের ত্রুটির মতো শোনায়।
rr-

2
@jgmjgm ঠিক এই 3 টি সমস্যার কারণে এটি হ'ল, জিসি অনাকাঙ্ক্ষিত , try/ finallyবেআইনীভাবে হওয়া এবং ক্লিনআপ হ্যান্ডলারের সমাধানকারীদের পক্ষে অত্যন্ত সাধারণ উপকারী with। "স্পষ্টত বন্ধ হওয়া" এবং "পরিচালনা সহ with" এর মধ্যে পার্থক্য হ'ল একটি ব্যতিক্রম ছুঁড়ে ফেলা হলেও প্রস্থান হ্যান্ডলারকে ডাকা হয়। আপনি এটিকে close()একটি finallyধারাটিতে রাখতে পারেন, তবে এটি withপরিবর্তে ব্যবহার করা থেকে কিছুটা পৃথক নয় , কিছুটা বার্তাবাহক (1 এর পরিবর্তে 3 টি অতিরিক্ত লাইন) এবং ঠিক সঠিকভাবে পেতে কিছুটা শক্ত।
সিঙ্গেলাইজেশন ইলিমিনেশন

1
আমি এটি সম্পর্কে যা পাই না সে কারণেই 'সহ' আরও নির্ভরযোগ্য হবে কারণ এটিও স্পষ্ট নয়। এটা কি কারণ কারণ অনুমানস বলে যে এটি করতে হবে যে এটি সর্বদা এর মতো কার্যকর হয়?
jgmjgm

3
@jgmjgm এটি আরো নির্ভরযোগ্য কারণ with foo() as f: [...]মূলত হিসাবে একই f = foo(), f.__enter__(), [...] এবং f.__exit__() ঘাঁটা ব্যতিক্রমসহ , যাতে __exit__সবসময় বলা হয়। সুতরাং ফাইলটি সর্বদা বন্ধ হয়ে যায়।
নবজাতক

104

আপনি পাথলিব ব্যবহার করতে পারেন ।

পাইথন 3.5 এবং তারপরের জন্য:

from pathlib import Path
contents = Path(file_path).read_text()

পাইথনের পুরানো সংস্করণগুলির জন্য প্যাথলিব 2 ব্যবহার করুন :

$ pip install pathlib2

তারপর:

from pathlib2 import Path
contents = Path(file_path).read_text()

এটিই বাস্তব read_text বাস্তবায়ন :

def read_text(self, encoding=None, errors=None):
    """
    Open the file in text mode, read it, and close the file.
    """
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
        return f.read()

2

ঠিক আছে, প্রতিটি লাইনের সাথে কাজ করতে যদি আপনাকে লাইন দিয়ে ফাইল লাইন পড়তে হয় তবে আপনি এটি ব্যবহার করতে পারেন

with open('Path/to/file', 'r') as f:
    s = f.readline()
    while s:
        # do whatever you want to
        s = f.readline()

বা আরও ভাল উপায়:

with open('Path/to/file') as f:
    for line in f:
        # do whatever you want to

0

একক স্ট্রিং হিসাবে ফাইলের সামগ্রী পুনরুদ্ধার করার পরিবর্তে, ফাইলটি অন্তর্ভুক্ত সমস্ত লাইনের একটি তালিকা হিসাবে সামগ্রীটি সংরক্ষণ করা সহজ হতে পারে :

with open('Path/to/file', 'r') as content_file:
    content_list = content_file.read().strip().split("\n")

যেমন দেখা যায়, এই থ্রেডের মূল উত্তরে একটিকে সংক্ষিপ্ত পদ্ধতি যুক্ত .strip().split("\n")করা দরকার ।

এখানে .strip()কেবল পুরো ফাইল স্ট্রিংয়ের শেষে হোয়াইটস্পেস এবং নিউলাইন অক্ষরগুলি সরিয়ে দেয় এবং .split("\n")প্রতিটি ফাইলের নতুন অক্ষরে পুরো ফাইল স্ট্রিংকে বিভক্ত করার মাধ্যমে প্রকৃত তালিকা তৈরি করে \ n

তদ্ব্যতীত, এইভাবে পুরো ফাইল সামগ্রীটি একটি ভেরিয়েবলে সংরক্ষণ করা যেতে পারে, যা পূর্ববর্তী উত্তরে নির্দেশিত হিসাবে ফাইল লাইনের উপর দিয়ে লুপের পরিবর্তে কিছু ক্ষেত্রে পছন্দসই হতে পারে ।

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