পাইথনে বস্তুটি ফাইলের মতো কিনা তা পরীক্ষা করুন


94

ফাইল-জাতীয় বস্তু হ'ল পাইথনের বস্তু যা প্রকৃত ফাইলের মতো আচরণ করে, যেমন একটি পঠন () এবং একটি লেখার পদ্ধতি () থাকতে পারে তবে এর আলাদা প্রয়োগ রয়েছে। এটি এবং হাঁসের টাইপিং ধারণার উপলব্ধি ।

যেখানেই ফাইল প্রত্যাশিত যেখানেই ফাইল-অনুরূপ অবজেক্টটিকে মঞ্জুরি দেওয়া ভাল অভ্যাস হিসাবে বিবেচিত হয় যাতে উদাহরণস্বরূপ একটি স্ট্রিংআইও বা সকেট অবজেক্টটি সত্যিকারের ফাইলের পরিবর্তে ব্যবহার করা যায়। সুতরাং এটির মতো চেক করা খারাপ:

if not isinstance(fp, file):
   raise something

কোনও বস্তু (যেমন কোনও পদ্ধতির একটি প্যারামিটার) "ফাইলের মতো" কিনা তা যাচাই করার সর্বোত্তম উপায় কী?

উত্তর:


44

আপনার বিশেষ প্রয়োজনীয়তা না থাকলে আপনার কোডে এ জাতীয় চেক রাখা মোটেই ভাল অনুশীলন নয়।

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

আপনি যে যা যা পরীক্ষা করতে পারেন তা রানটাইমের সময় যেভাবেই ঘটতে চলেছে তাই এরূপ কিছু করা if not hasattr(fp, 'read')এবং কিছু ব্যতিক্রম বাড়াতে কেবল কল করা fp.read()এবং পদ্ধতিটি উপস্থিত না থাকলে ফলাফল বিশিষ্ট ত্রুটিটি পরিচালনা করার চেয়ে কিছুটা বেশি উপযোগীতা সরবরাহ করে।


whyকি অপারেটার পছন্দ সম্পর্কে __add__, __lshift__অথবা __or__কাস্টম ক্লাসের? (ফাইল অবজেক্ট এবং এপিআই: docs.python.org/glossary.html#term-file-object )
n611x007

@ নেক্সা: তাহলে ঠিক সেই অপারেটরদের কী হবে?
মার্টিনিউ

34
প্রায়শই এটি চেষ্টা করে কাজ করে তবে আমি পাইথোনিক ম্যাক্সিম কিনি না যে পাইথনে এটি করা যদি কঠিন হয় তবে এটি ভুল। কল্পনা করুন যে আপনি কোনও বস্তু পাস করেছেন এবং সেখানে 10 টি বিভিন্ন জিনিস রয়েছে যা আপনি তার বস্তুর ধরণের উপর নির্ভর করে করতে পারেন। আপনি প্রতিটি সম্ভাবনা চেষ্টা করে যাচ্ছেন না এবং অবশেষে এটি সঠিক না হওয়া পর্যন্ত ত্রুটিটি পরিচালনা করবেন না। এটি সম্পূর্ণ অকার্যকর হবে। আপনার প্রয়োজনীয়ভাবে জিজ্ঞাসা করার দরকার নেই, এটি কী ধরণের, তবে আপনাকে জিজ্ঞাসা করতে সক্ষম হতে হবে যে এই অবজেক্টটি ইন্টারফেস
এক্সটি

33
পাইথন সংগ্রহের পাঠাগারটি "ইন্টারফেস প্রকারগুলি" (উদাহরণস্বরূপ, সিকোয়েন্স) বলা যেতে পারে যে এটি প্রায়শই পাইথনের মধ্যেও দরকারী। সাধারণভাবে, যখন কেউ "কিভাবে ফাঁকি দিতে হয়" জিজ্ঞাসা করে, "ডু ফু না" খুব সন্তোষজনক উত্তর নয়।
অ্যাডামসি

4
সমস্ত ধরণের কারণে অ্যাট্রিবিউটআরার উত্থাপিত হতে পারে যা আপনার প্রয়োজনীয় ইন্টারফেসটির সাথে বস্তুটি সমর্থন করে কিনা তার সাথে কিছুই করার নেই। আইওব্যাস থেকে প্রাপ্ত ফাইললিঙ্কগুলির জন্য হ্যাশট্রের প্রয়োজনীয়তা রয়েছে
এরিক অ্যারোনস্টি

77

3.1+ এর জন্য, নিম্নলিখিতগুলির মধ্যে একটি:

isinstance(something, io.TextIOBase)
isinstance(something, io.BufferedIOBase)
isinstance(something, io.RawIOBase)
isinstance(something, io.IOBase)

২.x এর জন্য, "ফাইল-এর মতো অবজেক্ট" চেক করার মতো বিষয় খুব অস্পষ্ট, তবে আপনি যে ফাংশন (গুলি) নিয়ে কাজ করছেন তার ডকুমেন্টেশন আশা করি আপনাকে তাদের আসলে কী প্রয়োজন তা বলবে; যদি না হয় তবে কোডটি পড়ুন।


অন্যান্য উত্তরগুলি নির্দেশ করে, প্রথমত আপনাকে জিজ্ঞাসা করতে হবে যে আপনি ঠিক কী পরীক্ষা করছেন। সাধারণত, ইএএফপি যথেষ্ট, এবং আরও মূর্তিমান।

শব্দকোষ বলছেন "ফাইল মত বস্তু" যা পরিণামে তিন এক একটি দৃষ্টান্ত মানে "ফাইল বস্তুর", জন্য একটি প্রতিশব্দ হয় বিমূর্ত বেস ক্লাস সংজ্ঞায়িত মডিউল যা নিজেদের সব উপশ্রেণী হয়, । সুতরাং, চেক করার উপায়টি ঠিক উপরে দেখানো মত।ioIOBase

(তবে, চেক IOBaseকরা খুব কার্যকর নয় text আপনি এমন একটি ক্ষেত্রে কী কল্পনা করতে পারেন যেখানে আপনাকে read(size)এমন কোনও এক-আর্গুমেন্ট ফাংশন readযা ফাইল-জাতীয় নয়, টেক্সট ফাইল এবং কাঁচা মধ্যেও পার্থক্য না করেই আলাদা করতে হবে) বাইনারি ফাইল? সুতরাং, আপনি প্রায় সবসময় পরীক্ষা করতে চান, যেমন, "একটি পাঠ্য ফাইল অবজেক্ট", "কোনও ফাইলের মতো বস্তু নয়"।)


২.x এর জন্য, ioমডিউলটি যখন ২.6++ থেকেই রয়েছে, তখন অন্তর্নির্মিত ফাইল অবজেক্টগুলি ioক্লাসের উদাহরণ নয়, স্টার্টলিবের কোনও ফাইল-জাতীয় বস্তু নয় এবং তৃতীয় পক্ষের ফাইল-জাতীয় বস্তুও আপনি নন 'মুখোমুখি হওয়ার সম্ভাবনা আছে। "ফাইল-জাতীয় বস্তু" এর অর্থের কোনও আনুষ্ঠানিক সংজ্ঞা ছিল না; এটি কেবল "বিল্টিন ফাইল অবজেক্টের মতো কিছু " এবং বিভিন্ন ফাংশনগুলির অর্থ "লাইক" দ্বারা ভিন্ন জিনিস। এই ধরনের ফাংশনগুলির অর্থ কী তা ডকুমেন্ট করা উচিত; যদি তারা না করে তবে আপনাকে কোডটি দেখতে হবে।

তবে সর্বাধিক সাধারণ অর্থ হ'ল read(size)"," আছে read()", বা" স্ট্রিংগুলির একটি পুনরাবৃত্তিযোগ্য ", তবে কিছু পুরানো গ্রন্থাগারগুলির readlineমধ্যে একটির পরিবর্তে আশা করা যেতে পারে , কিছু লাইব্রেরি আপনার দেওয়া close()ফাইলগুলি পছন্দ করে, কিছু আশা করে যে যদি filenoউপস্থিত থাকে তবে অন্যান্য কার্যকারিতা উপলভ্য হয় ইত্যাদি ইত্যাদি এবং একইভাবে write(buf)(যদিও সেদিকে অনেক কম বিকল্প রয়েছে)।


4
অবশেষে, কেউ এটি বাস্তব রাখা হয়।
অ্যান্টনি রটলেজ

18
একমাত্র দরকারী উত্তর। স্ট্যাকওভারফ্লাওয়াররা কেন "আপনি যা করতে চাইছেন তা করা বন্ধ করুন, কারণ আমি আরও ভাল জানি ... এবং পিইপি 8, ইএএফপি এবং স্টাফ!" পোস্টগুলি আমার ভঙ্গুর বোধগম্য beyond ( সম্ভবত চথুলহু জানেন? )
সিসিল কারি

4
কারণ আমরা এমন লোকদের দ্বারা লিখিত প্রচুর কোডটি চালিয়ে গিয়েছি যারা আগে চিন্তা করে না, এবং আপনি এটি পাস করার সময় এটি ভেঙে যায় যা প্রায় হয় তবে একটি ফাইল নয় কারণ তারা স্পষ্টভাবে পরীক্ষা করে দেখে। পুরো ইএএফপি, হাঁসের টাইপিং জিনিসটি কোনও বুলশিট বিশুদ্ধতা পরীক্ষা নয়। এটি একটি আসল দৃষ্টিনন্দন সিদ্ধান্ত,
drxzcl

4
এটিকে আরও ভাল ইঞ্জিনিয়ারিং হিসাবে দেখা যেতে পারে এবং আমি ব্যক্তিগতভাবে এটিকে পছন্দ করব তবে কার্যকর হতে পারে না। সাধারণত ফাইল-জাতীয় বস্তুগুলির উত্তরাধিকার সূত্রগুলির প্রয়োজন হয় নাIOBase । উদাহরণস্বরূপ পাইটেষ্ট ফিক্সচারগুলি আপনাকে দেয় _pytest.capture.EncodedFileযা কোনও কিছুর উত্তরাধিকার সূত্রে আসে না।
টমো গ্যাভেনিয়াক

46

অন্যরা যেমন বলেছে আপনার সাধারণত এ জাতীয় চেক এড়ানো উচিত। একটি ব্যতিক্রম হ'ল যখন বস্তুটি বৈধভাবে বিভিন্ন ধরণের হতে পারে এবং আপনি ধরণের উপর নির্ভর করে ভিন্ন আচরণ চান। ইএএফপি পদ্ধতিটি এখানে সর্বদা কাজ করে না কারণ কোনও বস্তু একাধিক ধরণের হাঁসের মতো দেখতে পারে!

উদাহরণস্বরূপ কোনও প্রাথমিককরণকারী নিজের শ্রেণীর ফাইল, স্ট্রিং বা উদাহরণ নিতে পারে। আপনার তখন কোড থাকতে পারে:

class A(object):
    def __init__(self, f):
        if isinstance(f, A):
            # Just make a copy.
        elif isinstance(f, file):
            # initialise from the file
        else:
            # treat f as a string

এখানে ইএএফপি ব্যবহার করে সমস্ত প্রকারের সূক্ষ্ম সমস্যা দেখা দিতে পারে কারণ ব্যতিক্রম ছোঁড়ার আগে প্রতিটি সূচনা পথ আংশিকভাবে চালিত হয়। মূলত এই নির্মাণটি ওভারলোডিং ফাংশনটি নকল করে এবং এটি খুব পাইথোনিক নয়, তবে যত্ন সহ ব্যবহার করা গেলে এটি কার্যকর হতে পারে।

পার্শ্ব নোট হিসাবে, আপনি পাইথন 3 তে একইভাবে ফাইল চেকটি করতে পারবেন না You isinstance(f, io.IOBase)পরিবর্তে আপনার মতো কিছু দরকার হবে।


28

এখানে প্রভাবশালী দৃষ্টান্তটি হল ইএএফপি: অনুমতি চেয়ে ক্ষমা চাইতে আরও সহজ। এগিয়ে যান এবং ফাইল ইন্টারফেস ব্যবহার করুন, তারপরে ফলাফল ব্যতিক্রম হ্যান্ডেল করুন, বা তাদের কলারে প্রচার করতে দিন।


9
+1: যদি xফাইলের মতো না হয় তবে x.read()তার নিজস্ব ব্যতিক্রম বাড়িয়ে তুলবে। অতিরিক্ত ইফ-স্টেটমেন্ট কেন লিখবেন? শুধু অবজেক্টটি ব্যবহার করুন। এটি হয় কাজ বা বিরতি হবে।
এসলট

4
এমনকি ব্যতিক্রম পরিচালনা করবেন না। যদি কেউ এমন কোনও কিছুতে পাস করেন যা আপনার প্রত্যাশিত এপিআইয়ের সাথে মেলে না, তবে এটি আপনার সমস্যা নয়।
হাবিবনেবিট

4
অ্যারন গালাগের: আমি নিশ্চিত নই। ধারাবাহিক অবস্থা রক্ষা করা আমার পক্ষে কঠিন হলেও আপনার বক্তব্যটি কি সত্য?
dmeister

4
একটি সামঞ্জস্যপূর্ণ রাষ্ট্র সংরক্ষণ করতে আপনি "চেষ্টা / অবশেষে" (তবে ব্যতীত!) বা নতুন "সহ" বিবৃতি ব্যবহার করতে পারেন।
drxzcl

এটি "দ্রুত ব্যর্থ এবং উচ্চস্বরে ব্যর্থ" দৃষ্টান্তের সাথে সামঞ্জস্যপূর্ণ। আপনি যদি সাবধানী না হন তবে সুস্পষ্ট তাত্ক্ষণিক (...) চেকগুলি মাঝে মধ্যে কোনও ক্রিয়াকলাপ / পদ্ধতিটিকে তার উদ্দেশ্যযুক্ত ক্রিয়া সম্পাদন না করে সাধারণত ফিরে আসতে পারে।
বেন বার্নস

11

শর্তটি পরীক্ষা করে ত্রুটি বাড়াতে প্রায়শই কার্যকর হয়, যখন সেই ত্রুটিটি সাধারণত পরে দেখা যায় না। এটি 'ব্যবহারকারী-ভূমি' এবং 'এপিআই' কোডের মধ্যে সীমানার জন্য বিশেষত সত্য।

আপনি প্রস্থান দরজার একটি থানায় একটি ধাতব ডিটেক্টর রাখবেন না, আপনি প্রবেশদ্বারে এটি স্থাপন করবেন! যদি শর্তটি পরীক্ষা না করা মানে এমন একটি ত্রুটি ঘটতে পারে যা আগে ১০০ লাইন ধরেছে বা সাবক্লাসে উঠার পরিবর্তে একটি সুপার-ক্লাসে থাকতে পারে তবে আমি বলছি চেক করার ক্ষেত্রে কোনও ভুল নেই।

আপনি একাধিক প্রকারকে গ্রহণ করার সময় যথাযথ প্রকারের জন্য পরীক্ষা করাও বোধগম্য হয়। একটি ব্যতিক্রম বাড়ানো আরও ভাল বলে যে "আমার বেসস্ট্রিংয়ের একটি সাবক্লাস প্রয়োজন, বা ফাইল" কেবল একটি ব্যতিক্রম বাড়াতে না কেননা কিছু ভেরিয়েবলের 'সিক' পদ্ধতি নেই ...

এর অর্থ এই নয় যে আপনি পাগল হয়ে যান এবং সর্বত্র এটি করেন, বেশিরভাগ ক্ষেত্রে আমি ব্যতিক্রমগুলি নিজেদের উত্থাপনের ধারণার সাথে একমত, তবে আপনি যদি আপনার এপিআইকে অত্যন্ত পরিষ্কার করতে পারেন বা অপ্রয়োজনীয় কোড কার্যকর করতে এড়াতে পারেন কারণ একটি সাধারণ শর্ত পূরণ হয়নি been তাই করো!


4
আমি সম্মত, তবে সর্বত্র এটির সাথে পাগল না হওয়ার প্রান্তে - পরীক্ষার সময় এই উদ্বেগগুলির অনেকটা ঝাঁকুনি দেওয়া উচিত এবং কিছু "কীভাবে এটি ব্যবহার করতে হবে / কীভাবে ব্যবহারকারীদের কাছে প্রদর্শিত হবে" প্রশ্নগুলির উত্তর ব্যবহারের প্রয়োজনীয়তা দ্বারা দেওয়া হবে।
বেন বার্নস

7

আপনি পদ্ধতিটি কল করে কল করতে পারেন তারপরে ব্যতিক্রমটি ধরুন:

try:
    fp.read()
except AttributeError:
    raise something

আপনি যদি কেবল একটি পঠন এবং একটি লেখার পদ্ধতি চান তবে আপনি এটি করতে পারেন:

if not (hasattr(fp, 'read') and hasattr(fp, 'write')):
   raise something

আমি যদি আপনি থাকতাম আমি চেষ্টা করে / পদ্ধতি ব্যতীত যাব।


আমি উদাহরণগুলির ক্রম পরিবর্তন করার পরামর্শ দেব। tryসর্বদা প্রথম পছন্দ। hasattrচেক শুধুমাত্র - কিছু সত্যিই অস্পষ্ট কারণে - আপনি কেবল ব্যবহার করতে পারবেন না try
এসলট

4
আপনি যদি পরবর্তীকালে থেকে ডেটা প্রক্রিয়া করতে চান তবে ব্লকের মধ্যে সমস্ত কোডটি এড়ানোর জন্য fp.read(0)পরিবর্তে আমি ব্যবহার করার পরামর্শ দিচ্ছি । fp.read()tryfp
মায়ো

4
নোট করুন যে fp.read()বড় ফাইল সহ তাত্ক্ষণিক মেমরির ব্যবহার বাড়িয়ে তুলবে।
কিরিলো পেরেভোজিচিকভ

আমি পাই পাই এটি পাইথোনিক, তবে তারপরে আমাদের অন্যান্য সমস্যাগুলির মধ্যে দুবার ফাইলটি পড়তে হবে। উদাহরণস্বরূপ, Flaskআমি এটি করেছি এবং অন্তর্নিহিত FileStorageঅবজেক্টটি বুঝতে পেরেছি এটি পড়ার পরে পয়েন্টার পুনরায় সেট করা দরকার।
অ্যাডাম হিউজেস

2

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

কমপক্ষে একটি কেস রয়েছে যেখানে আপনি এই ধরণের চেক করতে চাইতে পারেন, এবং এটি যখন তখন অবজেক্টটি আপনি যা দিয়ে গেছেন তা অবিলম্বে ব্যবহার করা হচ্ছে না, উদাহরণস্বরূপ যদি এটি কোনও শ্রেণীর কনস্ট্রাক্টরে সেট করা থাকে। সেক্ষেত্রে আমি ভাবব যে ইএএফপি নীতিটি "দ্রুত ব্যর্থ হওয়া" নীতির দ্বারা তুচ্ছ। আমার ক্লাসের যে পদ্ধতিগুলি প্রয়োজন (এবং সেগুলি পদ্ধতি) এটি কার্যকর করেছে তা নিশ্চিত করার জন্য আমি বিষয়টিটি পরীক্ষা করে দেখি, যেমন:

class C():
    def __init__(self, file):
        if type(getattr(file, 'read')) != type(self.__init__):
            raise AttributeError
        self.file = file

4
কেন কেবল ন্যায়বিচারের getattr(file, 'read')পরিবর্তে file.read? এটি ঠিক একই জিনিস করে।
17:39

4
আরও গুরুত্বপূর্ণ, এই চেকটি ভুল। এটি উত্থাপিত হবে যখন বলুন, একটি প্রকৃত fileউদাহরণ। (বিল্টিন / সি-এক্সটেনশন প্রকারের উদাহরণগুলির ধরনগুলি প্রকারের builtin_function_or_method, তবে পুরানো-শৈলীর শ্রেণীর পাঠ্যক্রমগুলি instancemethod)। এটি একটি পুরানো ধাঁচের শ্রেণি এবং এটি ==পরিবর্তে প্রকারভেদে ব্যবহার করেininstance বা এরissubclass তা আরও সমস্যা, তবে মূল ধারণাটি যদি কাজ করে না, তবে বিষয়টি খুব কমই গুরুত্বপূর্ণ।
17:44

2

আমি যখন লিখছিলাম তখন আমি আপনার প্রশ্নটি শেষ করেছিলাম open মতামত নিয়ে মতো ফাংশন যা কোনও ফাইলের নাম, ফাইল বর্ণনাকারী বা প্রাক-খোলা ফাইল-জাতীয় অবজেক্ট গ্রহণ করতে পারে।

readঅন্য উত্তরগুলির মতো, কোনও পদ্ধতির জন্য পরীক্ষার পরিবর্তে , আমি অবজেক্টটি খুলতে পারি কিনা তা পরীক্ষা করে শেষ করেছি। যদি এটি পারে তবে এটি একটি স্ট্রিং বা বর্ণনাকারী এবং ফলাফল থেকে আমার হাতে একটি বৈধ ফাইল-জাতীয় বস্তু রয়েছে। যদি openএকটি উত্থাপন করে TypeError, তবে বস্তুটি ইতিমধ্যে একটি ফাইল।

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