পাথের টার্গেটে কোনও ফাইল তৈরি না করে পাইথনে কোনও পাথটি বৈধ কিনা তা পরীক্ষা করে দেখুন


98

আমার একটি পথ রয়েছে (ডিরেক্টরি এবং ফাইলের নাম সহ)।
ফাইল-নামটি বৈধ কিনা আমার পরীক্ষা করা দরকার, উদাহরণস্বরূপ যদি ফাইল-সিস্টেম আমাকে এই জাতীয় নামের সাথে একটি ফাইল তৈরি করতে দেয়।
ফাইল- নামটিতে কিছু ইউনিকোড অক্ষর রয়েছে।

পথের ডিরেক্টরি বিভাগটি বৈধ এবং অ্যাক্সেসযোগ্য (এটি আমি প্রশ্নটি আরও জেনারিকভাবে প্রযোজ্য করার চেষ্টা করছিলাম এবং দৃশ্যত আমি খুব দূরে গিয়েছিলাম ) ধরে নেওয়া নিরাপদ ।

আমি খুব কিছু অব্যাহতি যদি না আমি আছে চাই না আছে আছে।

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


এখানে ধরা আছে। ইতিমধ্যে পাথের লক্ষ্যবস্তুতে কোনও ফাইল থাকতে পারে (বা নাও)। আমার যদি ফাইলটি বিদ্যমান থাকে তবে তা রাখা দরকার এবং যদি এটি না থাকে তবে একটি ফাইল তৈরি করতে পারি না।

মূলত আমি যাচাই করতে চাই যে আমি লেখার জন্য পথটি না খোলার পরে (এবং সাধারণত স্বয়ংক্রিয়ভাবে ফাইল স্বয়ংক্রিয়ভাবে ফাইল তৈরি / ফাইল ক্লোবার্বিং যা লিখতে পারে) না লিখতে পারি ।

যেমন:

try:
    open(filename, 'w')
except OSError:
    # handle error here

এখান থেকে

গ্রহণযোগ্য নয়, কারণ এটি বিদ্যমান ফাইলটি ওভাররাইট করে দেবে, যা আমি স্পর্শ করতে চাই না (যদি এটি সেখানে থাকে), বা না থাকলে বলা ফাইলটি তৈরি করতে চাই।

আমি জানি আমি করতে পারি:

if not os.access(filePath, os.W_OK):
    try:
        open(filePath, 'w').close()
        os.unlink(filePath)
    except OSError:
        # handle error here

কিন্তু এটি ফাইলটি তৈরি করবে filePath, যা আমার তখন করতে হবে os.unlink

শেষ পর্যন্ত, দেখে মনে হচ্ছে এটি এমন কিছু করতে 6 বা 7 লাইন ব্যয় করছে যা সহজ os.isvalidpath(filePath)বা অনুরূপ হওয়া উচিত ।


একদিকে যেমন আমার উইন্ডোজ এবং ম্যাকোএসে চালিত হওয়া দরকার, তাই আমি প্ল্যাটফর্ম-নির্দিষ্ট জিনিস এড়াতে চাই।

``


যদি আপনি পরীক্ষাটি করতে চান যে পথটি বিদ্যমান এবং আপনি এটিতে লিখতে পারেন তবে কেবল অন্য কোনও ফাইল তৈরি এবং মুছুন। মাল্টি ইউজার / মাল্টি থ্রেড ইস্যু এড়ানোর জন্য এটিকে একটি অনন্য নাম দিন (বা যতটা সম্ভব অনন্য) unique অন্যথায় আপনি অনুমতিগুলি পরীক্ষা করে দেখছেন যা আপনাকে সরাসরি ওএস নির্দিষ্ট জঞ্জালের মধ্যে ফেলে দেবে।
টনি হপকিনসন

4
@Tony Hopkinson - মূলত আমি চেক করতে চান পারে একটি পাথ লিখতে আসলে কিছু না লিখেই
ভুয়া নাম

আপনার কাছে যদি ফাইলটিতে লেখার মতো কিছু না থাকে, তবে আপনি সক্ষম হচ্ছেন কিনা তা কেন আপনার জানতে হবে?
কার্ল নচেটেল

@ কার্ল নচেটেল - আমি যদি এটি লিখি, এবং সেখানে ইতিমধ্যে একটি ফাইল রয়েছে, তবে এটি বিদ্যমান ফাইলটিকে ক্ষতিগ্রস্থ করবে।
ভুয়ো নাম

4
@ ফেকনাম - আপনার এখানে সর্বদা একটি সূক্ষ্ম রেসের শর্ত থাকবে। ফাইলটি বিদ্যমান নেই তবে এটি তৈরি হতে পারে এবং তারপরে ফাইলটি তৈরি করার সময়, অন্য কোনও প্রক্রিয়া এটি তৈরি করতে পারে এবং আপনি যেভাবে ফাইলটি ক্লোবার করবেন। অবশ্যই এটি আপনার ব্যবহারের উপর নির্ভর করে যে এটি বাস্তবসম্মত সমস্যা কিনা বা না ...
অবশ্যই

উত্তর:


155

tl; ডা

is_path_exists_or_creatable()নীচে সংজ্ঞায়িত ফাংশন কল করুন ।

কঠোরভাবে পাইথন ৩. ঠিক এভাবেই আমরা রোল করি।

দুটি গল্পের টেল

"আমি কীভাবে পথের নামের বৈধতা পরীক্ষা করব এবং, বৈধ পথের নামের জন্য, সেই পাথগুলির অস্তিত্ব বা লিখনযোগ্যতা?" স্পষ্টতই দুটি পৃথক প্রশ্ন। উভয়ই আকর্ষণীয়, এবং উভয়ই এখানে সত্যিকারের সন্তোষজনক উত্তর পেয়েছে না ... বা, ভাল, আমি যে কোনও জায়গায় গ্রেপ করতে পারি।

vikki এর উত্তর সম্ভবত নিকটতম hews কিন্তু এর অসাধারণ অসুবিধেও আছে:

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

আমরা সব ঠিক করব।

প্রশ্ন # 0: আবার পথের বৈধতা কী?

আমাদের ভঙ্গুর মাংসের বেদনার অজগর-ছাঁদযুক্ত মশপিটগুলিতে ফেলে দেওয়ার আগে আমাদের সম্ভবত "পথের নাম বৈধতা" বলতে কী বোঝানো উচিত। বৈধতা ঠিক কি সংজ্ঞা দেয়?

"পথের নাম বৈধতা" দ্বারা আমরা বর্তমান সিস্টেমের মূল ফাইল সিস্টেমের সাথে সম্মত একটি পাথনামের সিনট্যাকটিক যথার্থতা বলতে পারি - সে পথ বা তার পিতামাত ডিরেক্টরিগুলি শারীরিকভাবে বিদ্যমান কিনা তা নির্বিশেষে। কোনও সংজ্ঞা এই সংজ্ঞা অনুসারে সিন্থেটিকভাবে সঠিক হয় যদি এটি মূল ফাইল সিস্টেমের সমস্ত সিনট্যাকটিক প্রয়োজনীয়তা মেনে চলে।

"রুট ফাইল সিস্টেম," দ্বারা আমাদের অর্থ:

  • পসিক্স-সামঞ্জস্যপূর্ণ সিস্টেমে ফাইল সিস্টেমটি রুট ডিরেক্টরিতে মাউন্ট করে ( /)।
  • উইন্ডোজে, ফাইল সিস্টেমে মাউন্ট করা হয়েছে %HOMEDRIVE%, বর্তমান উইন্ডোজ ইনস্টলেশন (সাধারণত তবে প্রয়োজনীয়ভাবে নয়C: ) সহ কোলন-প্রত্যয়যুক্ত ড্রাইভ লেটার ।

পরিবর্তে "সিনট্যাকটিক যথার্থতা" এর অর্থ মূল ফাইল সিস্টেমের ধরণের উপর নির্ভর করে। জন্য ext4(এবং সবচেয়ে কিন্তু না সব POSIX সামঞ্জস্যপূর্ণ) ফাইল সিস্টেম, একটি পথনাম চিহ্নগুলি সিন্টেক্সের সঠিক যদি এবং কেবল যে পথনাম যদি:

  • কোনও নাল বাইট নেই (অর্থাত্ \x00পাইথনে)। এটি সমস্ত পসিক্স-সামঞ্জস্যপূর্ণ ফাইল সিস্টেমগুলির জন্য একটি কঠোর প্রয়োজনীয়তা।
  • 255 বাইটের চেয়ে বেশি কোনও পথের উপাদান নেই (যেমন, 'a'*256পাইথনে)। একটি পাথ উপাদান একটি পথনাম কোন ধারণকারী একটি দীর্ঘতম সাবস্ট্রিং হয় /অক্ষর (যেমন, bergtatt, ind, i, এবং fjeldkamreneপথনাম মধ্যে /bergtatt/ind/i/fjeldkamrene)।

সিনট্যাকটিক নির্ভুলতা। রুট ফাইল সিস্টেম। এটাই.

প্রশ্ন # 1: এখন আমরা কীভাবে পথের নাম বৈধতা করব?

পাইথনে প্যাথনামগুলির বৈধকরণ আশ্চর্যজনকভাবে অ-স্বজ্ঞাত। আমি এখানে নকল নামের সাথে দৃ agreement় চুক্তিতে রয়েছি : অফিসিয়াল os.pathপ্যাকেজটির উচিত এটির জন্য একটি বাইরের সমাধান সমাধান সরবরাহ করা। অজানা (এবং সম্ভবত উদ্বেগহীন) কারণে, এটি হয় না। ভাগ্যক্রমে, আপনার নিজস্ব অ্যাডহক সমাধানটি আনرول করা সেই অন্ত্রের রেঞ্চিং নয় ...

ঠিক আছে, এটা আসলে। এটি লোমশ; এটা খারাপ; এটি জ্বলন্তভাবে বোরবাক হয়ে ওঠে এবং ঝাঁকুনির সাথে সাথে এটি গিরিযুক্ত হয়। তবে তুমি কি করবে? নুথিন '।

আমরা শীঘ্রই নিম্ন-স্তরের কোডের তেজস্ক্রিয় অতলগুলিতে নামব। তবে প্রথমে, উচ্চ স্তরের দোকানে কথা বলা যাক। অবৈধ পথের নামগুলি পাস করার সময় মান os.stat()এবং os.lstat()ফাংশনগুলি নিম্নলিখিত ব্যতিক্রমগুলি উত্থাপন করে:

  • অস্তিত্বহীন ডিরেক্টরিতে থাকা পথের নামগুলির উদাহরণ FileNotFoundError
  • বিদ্যমান ডিরেক্টরিতে থাকা পথের নামগুলির জন্য:
    • উইন্ডোজ এর অধীনে, দৃষ্টান্ত WindowsErrorযার winerrorঅ্যাট্রিবিউট 123(অর্থাত, ERROR_INVALID_NAME)।
    • অন্যান্য সমস্ত ওএসের অধীনে:
    • নাল বাইট ( '\x00'উদাহরণস্বরূপ) সহ পথনামগুলির উদাহরণস্বরূপ TypeError
    • 255 বাইট চেয়ে দীর্ঘতর পাথ উপাদান ধারণকারী pathnames জন্য দৃষ্টান্ত OSErrorযার errcodeঅ্যাট্রিবিউট হল:
      • সুনোস এবং ওএসের বিএসডি পরিবারের অধীনে errno.ERANGE,। (এটি কোনও ওএস-স্তরের বাগ হিসাবে প্রতীয়মান হয়েছে, অন্যথায় পসিক্স স্ট্যান্ডার্ডের "নির্বাচনী ব্যাখ্যা" হিসাবে উল্লেখ করা হয়েছে))
      • অন্যান্য সমস্ত ওএসের আওতায় errno.ENAMETOOLONG,।

গুরুতরভাবে, এর দ্বারা বোঝা যায় যে বিদ্যমান ডিরেক্টরিতে থাকা কেবলমাত্র পঠনাম বৈধতাযোগ্য। os.stat()এবং os.lstat()ফাংশন জেনেরিক বাড়াতে FileNotFoundErrorব্যতিক্রম যখন পাশ pathnames অ বিদ্যমান ডিরেক্টরিগুলি থেকে বসবাসরত নির্বিশেষে ঐ pathnames অবৈধ বা না কিনা। ডিরেক্টরি অস্তিত্ব পথের নামটি বৈধতার চেয়ে অগ্রাধিকার নেয়।

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

এই প্রশ্নের উত্তর দেওয়ার জন্য, উপরে থেকে স্মরণ করুন যে ext4ফাইল সিস্টেমে সিন্টেক্সিকভাবে সঠিক প্যাথনামগুলিতে নাল বাইট বা (বি) 255 বাইটের বেশি দৈর্ঘ্যের কোনও পাথ উপাদান (ক) থাকে না । অতএব, কোনও পথের নাম বৈধ হয় এবং কেবল যদি সেই পথের নামগুলির সমস্ত পথ উপাদান বৈধ হয়। এটি বেশিরভাগ রিয়েল-ওয়ার্ল্ডের আগ্রহের ফাইল সিস্টেমগুলির ক্ষেত্রে সত্য ।ext4

সেই পেডেন্টিক অন্তর্দৃষ্টি কি আসলে আমাদের সহায়তা করে? হ্যাঁ. এটি পুরো পথের নামটি একের মধ্যে যাচাই করার বৃহত্তর সমস্যাটিকে হ্রাস করে কেবলমাত্র সেই পথের নামের সমস্ত পাথ উপাদানকে বৈধতা দেওয়ার ছোট্ট সমস্যায় পড়ে। নিম্নোক্ত অ্যালগরিদম অনুসরণ করে ক্রস-প্ল্যাটফর্ম পদ্ধতিতে যেকোন স্বেচ্ছাকৃত পাথের নামটি বৈধতাযোগ্য (সেই পথের নামটি বিদ্যমান ডিরেক্টরিতে থাকে কিনা তা নির্বিশেষে) less

  1. সেই পথের নামটি পাথের উপাদানগুলিতে বিভক্ত করুন (উদাহরণস্বরূপ, /troldskog/faren/vildতালিকায় পাথের নাম ['', 'troldskog', 'faren', 'vild'])।
  2. এই জাতীয় প্রতিটি উপাদান জন্য:
    1. একটি নতুন অস্থায়ী পথের নাম (যেমন, /troldskog) এর সাথে সেই উপাদানটির সাথে গ্যারান্টিযুক্ত ডিরেক্টরিটির পাথের নামটিতে যোগদান করুন ।
    2. যে পথের নামটি পাস করুন os.stat()বা os.lstat()। যদি সেই পথের নাম এবং সেইজন্য সেই উপাদানটি অবৈধ হয়, তবে এই কলটি জেনেরিক FileNotFoundErrorব্যতিক্রমের চেয়ে অবৈধতার ধরণকে প্রকাশ করে একটি ব্যতিক্রম বাড়ানোর গ্যারান্টিযুক্ত । কেন? কারণ সেই পথের নামটি একটি বিদ্যমান ডিরেক্টরিতে থাকে। (বিজ্ঞপ্তি যুক্তি বিজ্ঞপ্তি হয়।)

একটি ডিরেক্টরি আছে কি গ্যারান্টিযুক্ত আছে? হ্যাঁ, তবে সাধারণত একটিমাত্র: মূল ফাইল সিস্টেমের শীর্ষস্থানীয় ডিরেক্টরি (উপরে বর্ণিত হিসাবে)।

অন্য কোনও ডিরেক্টরিতে থাকা পথের নামগুলি পাস করা (এবং যার ফলে এটির নিশ্চয়তা নেই) রেস শর্তগুলিতে আমন্ত্রণ জানায় os.stat()বা os.lstat()আমন্ত্রণ জানায়, এমনকি যদি সেই ডিরেক্টরিটি আগে থেকেই পরীক্ষা করা হয়েছিল। কেন? কারণ বাহ্যিক প্রক্রিয়াগুলি পরীক্ষা চালানোর পরে কিন্তু সেই পথের নামটি পাস করার আগেos.stat() বা একযোগে সেই ডিরেক্টরিটি সরাতে বাধা দেওয়া যায় না os.lstat()। উন্মাদনা কুকুর অবমুক্ত!

উপরোক্ত পদ্ধতির পাশাপাশি রয়েছে সুরক্ষা side (নয় যে বিশেষভাবে চমৎকার?):

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

উপরের পন্থাটি কেবল রুট ফাইল সিস্টেমের রুট ডিরেক্টরিটির বিপরীতে কোনও পাথের নামের পাথ উপাদানগুলিকে বৈধতা দিয়ে এটিকে বাধ্য করে ob (এমনকি যদি এটি বাসি, ধীর বা অ্যাক্সেসযোগ্যও না হয় তবে আপনি পথের নাম বৈধতার চেয়ে বড় সমস্যা পেয়েছেন))

নিখোঁজ? দুর্দান্ত চল শুরু করি. (পাইথন 3 ধরে নেওয়া হয়েছে। দেখুন "300 এর জন্য কী ফ্রেজিলেস হোপ, লেইসেক ?")

import errno, os

# Sadly, Python fails to provide the following magic number for us.
ERROR_INVALID_NAME = 123
'''
Windows-specific error code indicating an invalid pathname.

See Also
----------
https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
    Official listing of all such codes.
'''

def is_pathname_valid(pathname: str) -> bool:
    '''
    `True` if the passed pathname is a valid pathname for the current OS;
    `False` otherwise.
    '''
    # If this pathname is either not a string or is but is empty, this pathname
    # is invalid.
    try:
        if not isinstance(pathname, str) or not pathname:
            return False

        # Strip this pathname's Windows-specific drive specifier (e.g., `C:\`)
        # if any. Since Windows prohibits path components from containing `:`
        # characters, failing to strip this `:`-suffixed prefix would
        # erroneously invalidate all valid absolute Windows pathnames.
        _, pathname = os.path.splitdrive(pathname)

        # Directory guaranteed to exist. If the current OS is Windows, this is
        # the drive to which Windows was installed (e.g., the "%HOMEDRIVE%"
        # environment variable); else, the typical root directory.
        root_dirname = os.environ.get('HOMEDRIVE', 'C:') \
            if sys.platform == 'win32' else os.path.sep
        assert os.path.isdir(root_dirname)   # ...Murphy and her ironclad Law

        # Append a path separator to this directory if needed.
        root_dirname = root_dirname.rstrip(os.path.sep) + os.path.sep

        # Test whether each path component split from this pathname is valid or
        # not, ignoring non-existent and non-readable path components.
        for pathname_part in pathname.split(os.path.sep):
            try:
                os.lstat(root_dirname + pathname_part)
            # If an OS-specific exception is raised, its error code
            # indicates whether this pathname is valid or not. Unless this
            # is the case, this exception implies an ignorable kernel or
            # filesystem complaint (e.g., path not found or inaccessible).
            #
            # Only the following exceptions indicate invalid pathnames:
            #
            # * Instances of the Windows-specific "WindowsError" class
            #   defining the "winerror" attribute whose value is
            #   "ERROR_INVALID_NAME". Under Windows, "winerror" is more
            #   fine-grained and hence useful than the generic "errno"
            #   attribute. When a too-long pathname is passed, for example,
            #   "errno" is "ENOENT" (i.e., no such file or directory) rather
            #   than "ENAMETOOLONG" (i.e., file name too long).
            # * Instances of the cross-platform "OSError" class defining the
            #   generic "errno" attribute whose value is either:
            #   * Under most POSIX-compatible OSes, "ENAMETOOLONG".
            #   * Under some edge-case OSes (e.g., SunOS, *BSD), "ERANGE".
            except OSError as exc:
                if hasattr(exc, 'winerror'):
                    if exc.winerror == ERROR_INVALID_NAME:
                        return False
                elif exc.errno in {errno.ENAMETOOLONG, errno.ERANGE}:
                    return False
    # If a "TypeError" exception was raised, it almost certainly has the
    # error message "embedded NUL character" indicating an invalid pathname.
    except TypeError as exc:
        return False
    # If no exception was raised, all path components and hence this
    # pathname itself are valid. (Praise be to the curmudgeonly python.)
    else:
        return True
    # If any other exception was raised, this is an unrelated fatal issue
    # (e.g., a bug). Permit this exception to unwind the call stack.
    #
    # Did we mention this should be shipped with Python already?

সম্পন্ন. এই কোডে স্কুইন্ট করবেন না। ( এটি কামড়ায়। )

প্রশ্ন # 2: সম্ভবত অবৈধ পথের নাম বা ক্রিয়েটিবিলিটি, এহ?

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

def is_path_creatable(pathname: str) -> bool:
    '''
    `True` if the current user has sufficient permissions to create the passed
    pathname; `False` otherwise.
    '''
    # Parent directory of the passed path. If empty, we substitute the current
    # working directory (CWD) instead.
    dirname = os.path.dirname(pathname) or os.getcwd()
    return os.access(dirname, os.W_OK)

def is_path_exists_or_creatable(pathname: str) -> bool:
    '''
    `True` if the passed pathname is a valid pathname for the current OS _and_
    either currently exists or is hypothetically creatable; `False` otherwise.

    This function is guaranteed to _never_ raise exceptions.
    '''
    try:
        # To prevent "os" module calls from raising undesirable exceptions on
        # invalid pathnames, is_pathname_valid() is explicitly called first.
        return is_pathname_valid(pathname) and (
            os.path.exists(pathname) or is_path_creatable(pathname))
    # Report failure on non-fatal filesystem complaints (e.g., connection
    # timeouts, permissions issues) implying this path to be inaccessible. All
    # other exceptions are unrelated fatal issues and should not be caught here.
    except OSError:
        return False

হয়ে গেছে এবং হয়ে গেছে। বেশ না বাদে

প্রশ্ন # 3: সম্ভবত উইন্ডোজটিতে অবৈধ পথের নাম বা লেখার যোগ্যতা

একটি সতর্কতা অবলম্বন আছে। অবশ্যই আছে।

সরকারী os.access()ডকুমেন্টেশন হিসাবে স্বীকার:

দ্রষ্টব্য: I / O ক্রিয়াকলাপগুলি ব্যর্থ হতে পারে এমনকি যখন os.access()ইঙ্গিত দেয় যে তারা সফল হবে, বিশেষত নেটওয়ার্ক ফাইল সিস্টেমে ক্রিয়াকলাপগুলির জন্য যেখানে সাধারণ পসিক্স অনুমতি-বিট মডেলের বাইরে পার্থক্য থাকতে পারে mant

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

এটি যদি আপনি হয় তবে আরও শক্তিশালী বিকল্পের সন্ধান করা হবে। যদি পাস করা পথটি না থাকে তবে আমরা পরিবর্তে সেই পথের পিতামহিত ডিরেক্টরিতে অবিলম্বে মুছে ফেলার গ্যারান্টিযুক্ত একটি অস্থায়ী ফাইল তৈরি করার চেষ্টা করি - সৃজনশীলতার আরও একটি বহনযোগ্য (ব্যয়বহুল) পরীক্ষা:

import os, tempfile

def is_path_sibling_creatable(pathname: str) -> bool:
    '''
    `True` if the current user has sufficient permissions to create **siblings**
    (i.e., arbitrary files in the parent directory) of the passed pathname;
    `False` otherwise.
    '''
    # Parent directory of the passed path. If empty, we substitute the current
    # working directory (CWD) instead.
    dirname = os.path.dirname(pathname) or os.getcwd()

    try:
        # For safety, explicitly close and hence delete this temporary file
        # immediately after creating it in the passed path's parent directory.
        with tempfile.TemporaryFile(dir=dirname): pass
        return True
    # While the exact type of exception raised by the above function depends on
    # the current version of the Python interpreter, all such types subclass the
    # following exception superclass.
    except EnvironmentError:
        return False

def is_path_exists_or_creatable_portable(pathname: str) -> bool:
    '''
    `True` if the passed pathname is a valid pathname on the current OS _and_
    either currently exists or is hypothetically creatable in a cross-platform
    manner optimized for POSIX-unfriendly filesystems; `False` otherwise.

    This function is guaranteed to _never_ raise exceptions.
    '''
    try:
        # To prevent "os" module calls from raising undesirable exceptions on
        # invalid pathnames, is_pathname_valid() is explicitly called first.
        return is_pathname_valid(pathname) and (
            os.path.exists(pathname) or is_path_sibling_creatable(pathname))
    # Report failure on non-fatal filesystem complaints (e.g., connection
    # timeouts, permissions issues) implying this path to be inaccessible. All
    # other exceptions are unrelated fatal issues and should not be caught here.
    except OSError:
        return False

উল্লেখ্য, যে এমনকি এই না যথেষ্ট হতে পারে।

ইউজার অ্যাক্সেস কন্ট্রোল (ইউএসি), সর্বদা অনিবার্য উইন্ডোজ ভিস্তা এবং এর পরবর্তী সমস্ত পুনরাবৃত্তি সিস্টেমকে ডিরেক্টরি ডিরেক্টরি সম্পর্কিত অনুমতি সম্পর্কে স্পষ্টতই মিথ্যা বলে ধন্যবাদ জানায়। অ প্রশাসক ব্যবহারকারীদের পারেন ক্যানোনিকাল ফাইল তৈরি করার প্রচেষ্টা চালাবেন যখন C:\Windowsবা C:\Windows\system32ডিরেক্টরি, UAC কৃত্রিম যখন তা করার ব্যবহারকারী অনুমতি দেয় আসলে একটি "ভার্চুয়াল স্টোর" যে ব্যবহারকারীর প্রোফাইলে সব নির্মিত ফাইল আলাদা। (কে সম্ভবত কল্পনা করতে পারে যে প্রতারণাকারীদের ক্ষতির দীর্ঘমেয়াদী পরিণতি হবে?)

এটা পাগলামি. এটি উইন্ডোজ।

প্রমান কর

আমাদের সাহস? উপরের পরীক্ষাগুলি চালানোর সময় হয়েছে time

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

>>> print('"foo.bar" valid? ' + str(is_pathname_valid('foo.bar')))
"foo.bar" valid? True
>>> print('Null byte valid? ' + str(is_pathname_valid('\x00')))
Null byte valid? False
>>> print('Long path valid? ' + str(is_pathname_valid('a' * 256)))
Long path valid? False
>>> print('"/dev" exists or creatable? ' + str(is_path_exists_or_creatable('/dev')))
"/dev" exists or creatable? True
>>> print('"/dev/foo.bar" exists or creatable? ' + str(is_path_exists_or_creatable('/dev/foo.bar')))
"/dev/foo.bar" exists or creatable? False
>>> print('Null byte exists or creatable? ' + str(is_path_exists_or_creatable('\x00')))
Null byte exists or creatable? False

বিচক্ষণতার বাইরে। ব্যথা ছাড়াই। আপনি পাইথন বহনযোগ্যতা উদ্বেগ পাবেন।


4
হ্যাঁ, এটা আমার ছিল! ক্রস-পোর্টেবল পাথনাম-যাচাইকরণ রেজেক্স একসাথে ক্লেজ করার চেষ্টা নিরর্থকতার একটি অনুশীলন এবং সাধারণ প্রান্তের ক্ষেত্রে ব্যর্থ হওয়ার গ্যারান্টিযুক্ত। উইন্ডোজে পাথের নাম দৈর্ঘ্যের কথা বিবেচনা করুন, উদাহরণস্বরূপ: "32,767 অক্ষরের সর্বাধিক পাথ আনুমানিক, কারণ রান time " এটি দেওয়া হয়েছে, এটি কেবল বৈধ পথের নামের সাথে মিলে একটি রেজেেক্স তৈরি করা প্রযুক্তিগতভাবে অক্ষম । এর পরিবর্তে পাইথনকে স্থগিত করা আরও অনেক বেশি যুক্তিসঙ্গত।
সিসিল কারি

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

4
ফাইল সিস্টেম-নির্দিষ্ট সীমাবদ্ধতা অবশ্যই একটি বৈধ উদ্বেগ - তবে এটি উভয় উপায়েই কেটে দেয়। অবিশ্বস্ত উত্স থেকে স্বেচ্ছাসেবক পথের নাম গ্রাহক সম্মুখ মুখোমুখি অ্যাপ্লিকেশনগুলির জন্য, অন্ধভাবে পড়া সম্পাদন করা সর্বোপরি একটি দ্বৈত প্রস্তাব; এই ক্ষেত্রে, রুট ফাইল সিস্টেমের ব্যবহারকে বাধ্য করা কেবল বুদ্ধিমান নয় তবে বুদ্ধিমান। অন্য অ্যাপ্লিকেশনগুলির জন্য, তবে ইউজারবেইস নিষিদ্ধ ফাইল সিস্টেম অ্যাক্সেসের পক্ষে যথেষ্ট বিশ্বাসযোগ্য হতে পারে। এটি মোটামুটি প্রাসঙ্গিক-নির্ভর, আমি বলব। এটিকে লক্ষ্য করার জন্য ধন্যবাদ, কেউ না ! আমি উপরে একটি ক্যাভিয়েট যুক্ত করব।
সিসিল কারি

4
নামকরণ হিসাবে, আমি দ্বারা পরীক্ষক নাম উপসর্গ একটি পেডেন্টিক ভক্ত is_। এটি আমার চরিত্রের ত্রুটি। তবুও, যথাযথভাবে উল্লেখ করেছেন: আপনি সবাইকে খুশি করতে পারবেন না, এবং কখনও কখনও আপনি কাউকে খুশি করতে পারেন না। ;)
সিসিল কারি

4
ফেডোরা 24-তে, অজগর 3.5.3 এ এমবেডড নাল অক্ষর সহ একটি পাথের নাম: ভ্যালুআরআর: এম্বেড করা নাল বাইট… যুক্ত করা দরকার: টাইপ-এরর ট্র্যাপের আগে বা পরে মিথ্যা `` return প্রত্যাবর্তন করুন।
এমমার্লিন 23'18

47
if os.path.exists(filePath):
    #the file is there
elif os.access(os.path.dirname(filePath), os.W_OK):
    #the file does not exists but write privileges are given
else:
    #can not write there

দ্রষ্টব্য যে path.existsআরও বেশি কারণে ব্যর্থ the file is not thereহতে পারে কেবল তাই আপনাকে পরীক্ষার মতো সূক্ষ্ম পরীক্ষাও করতে হতে পারে যদি ডিরেক্টরিটি উপস্থিত থাকে এবং অন্য কিছু থাকে তবে।


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

দুঃখের বিষয় আমি এর জন্য কোনও ভাল সমাধান জানি না। তবে সিসিল কারির উত্তরটি সমস্যাটি সনাক্ত করতে ঘনিষ্ঠভাবে নজর রাখে।


না। যদি পথে ফাইলটি উপস্থিত থাকে বা তৈরি করা যায় তবে সত্য হিসাবে ফিরে আসতে হবে । যদি অবৈধ (উইন্ডোজগুলিতে অবৈধ অক্ষর থাকার কারণে) থাকে তবে আমাকে মিথ্যা ফিরতে হবে।
ভুয়া নাম

or can be createdআপনার প্রশ্ন থেকে আমি তা পড়িনি। অনুমতিগুলি পড়া কিছুটা হলেও প্ল্যাটফর্ম নির্ভর dependent
এসই

4
@ ভুয়া নাম: হ্যাঁ এটি প্ল্যাটফর্ম নির্ভরতাগুলির কিছু সরিয়ে ফেলবে তবে এখনও কিছু প্ল্যাটফর্ম এমন জিনিস দেয় যা অন্যরা করে না এবং তাদের সকলের জন্য মোড়ানোর কোনও সহজ উপায় নেই। আমি আমার উত্তর আপডেট করেছি, এখানে একবার দেখুন।
কেউ 11 ই

4
কেন এই উত্তরটি upvated ছিল আমার কোন ধারণা নেই। এটি মূল প্রশ্নের সমাধানের সাথে দূরবর্তী সংলগ্ন হয় না - যা সংক্ষেপে: "পথের নামগুলি কার্যকর করুন, দয়া করে?" অনুমোদনের পথ অনুমোদনের বিষয়টি একটি আনুষঙ্গিক (এবং বেশিরভাগ ক্ষেত্রে অজ্ঞ) question কলটি কল করার জন্য os.path.exists(filePath)প্রযুক্তিগতভাবে অবৈধ পথের নামগুলিতে ব্যাতিক্রম বাড়িয়ে তুলবে, তবে এই ব্যতিক্রমগুলি স্পষ্টভাবে ধরা ও অন্যান্য সম্পর্কযুক্ত ব্যতিক্রম থেকে পৃথক হওয়া দরকার। অধিকন্তু, একই কলে আয় Falseবিদ্যমান পাথ উপর যা বর্তমান ব্যবহারকারীর নেই না অনুমতি পড়েছেন। সংক্ষেপে, খারাপ।
সিসিল কারি

4
@ সিসিলকারি: আপনার প্রশ্নের উত্তর দিতে: প্রশ্নের সম্পাদনার ইতিহাসটি একবার দেখুন। বেশিরভাগ প্রশ্নের মতো এটি প্রথমদিকে যেমন পরিষ্কার কাটেনি তবে এখনই কেবল শিরোনামের শব্দটি বোঝানো অন্যথায় বোঝা যেতে পারে যা আপনি বলেছেন তার চেয়ে বেশি।
কেউই এসই

9

পাইথন 3 সহ, কীভাবে:

try:
    with open(filename, 'x') as tempfile: # OSError if file exists or is invalid
        pass
except OSError:
    # handle error here

'এক্স' বিকল্পের সাথে আমাদেরও রেসের অবস্থার বিষয়ে চিন্তা করতে হবে না। ডকুমেন্টেশন এখানে দেখুন ।

নামটি অবৈধ না হলে এখন, এই খুব শীঘ্রই অস্থায়ী ফাইল তৈরি করবে it আপনি যদি এটির সাথে থাকতে পারেন তবে এটি জিনিসগুলিকে অনেক সহজ করে তোলে l


4
এই মুহুর্তে, যে প্রকল্পটির এটির প্রয়োজন ছিল সেই অবস্থানটি এতদূর এগিয়ে গেছে যেখানে একটি উত্তর এমনকি প্রাসঙ্গিক যে আমি সত্যই কোনও উত্তর গ্রহণ করতে পারি না।
ভুয়া নাম

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

5
open(filename,'r')   #2nd argument is r and not w

ফাইলটি খুলবে বা উপস্থিত না থাকলে একটি ত্রুটি দেবে। যদি কোনও ত্রুটি থাকে, তবে আপনি সেই পথে লেখার চেষ্টা করতে পারেন, যদি না পারেন তবে আপনি দ্বিতীয় ত্রুটি পান

try:
    open(filename,'r')
    return True
except IOError:
    try:
        open(filename, 'w')
        return True
    except IOError:
        return False

উইন্ডোতে অনুমতি সম্পর্কে এখানে একবার দেখুন


4
পরীক্ষার ফাইলটি স্পষ্টতই লিঙ্কযুক্ত () লিঙ্ক করার প্রয়োজন এড়াতে, আপনি ব্যবহার করতে পারেন tempfile.TemporaryFile()যা সুযোগের বাইরে চলে গেলে টেম্পাইলটি স্বয়ংক্রিয়ভাবে ধ্বংস করে দেয়।
ডি_বাই

@ ফেকনাম কোডটি আলাদা, আমি দ্বিতীয় অংশে ওস.একসেস ব্যবহার করতে পারতাম তবে আপনি যে লিঙ্কটি দিয়েছিলেন তা যদি আপনি অনুসরণ করেন তবে আপনি দেখতে পেলেন যে এটি একটি ভাল ধারণা নয়, এটি আপনাকে সত্যিকার অর্থেই খোলার চেষ্টা করার বিকল্পটি ছাড়বে লেখার পথ
ভিকি 12

আমি আমার পথগুলি তৈরি করছি os.path.join, সুতরাং আমার কাছে পালানোর সমস্যা নেই। তদুপরি, আমি সত্যিই ডিরেক্টরি অনুমতি সমস্যা নেই। আমার ডিরেক্টরি (এবং ফাইলের নাম) নামের সমস্যা আছে।
ভুয়ো নাম

@ ফেকনাম সেক্ষেত্রে আপনাকে কেবল এটি চেষ্টা করে খুলতে হবে (আপনার লেখার দরকার নেই), পাইথন যদি একটি filenameঅবৈধ অক্ষর থাকে তবে একটি ত্রুটি দেয় । আমি উত্তরটি সম্পাদনা করেছি
ভিকি

4
@ হেলগা ইলিয়াশেনকো লেখার জন্য খোলার ফলে একটি বিদ্যমান ফাইল ওভাররাইট হবে (এটিকে খালি করুন) এমনকি যদি আপনি এটি না লিখেই তাৎক্ষণিকভাবে বন্ধ করে দেন। এই কারণেই আমি প্রথমে পড়ার জন্য খুলছিলাম কারণ এইভাবে, যদি আপনি কোনও ত্রুটি না পান তবে আপনি জানেন যে একটি বিদ্যমান ফাইল রয়েছে।
ভিকি

-7

চেষ্টা করুন os.path.existsএটি পথটি যাচাই করে এবং Trueযদি উপস্থিত থাকে এবং Falseযদি না থাকে তবে ফিরে আসবে ।


4
না, যদি পথে পথে ফাইলটি উপস্থিত থাকে তবে আমার সত্যটি ফিরিয়ে আনতে হবে, বা তৈরি করা হবে । যদি অবৈধ (উইন্ডোজগুলিতে অবৈধ অক্ষর থাকার কারণে) থাকে তবে আমাকে মিথ্যা ফিরতে হবে।
ভুয়া নাম

কোন ধরণের অবৈধ চরিত্র?
নিলেশ

ডুনো - এটি প্ল্যাটফর্ম নির্দিষ্ট specific
ভুয়া নাম

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