ডিরেক্টরিটি লেখার যোগ্য কিনা তা নির্ধারণ করা হচ্ছে


102

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

উত্তর:


190

যদিও ক্রিস্টোফের পরামর্শ যা আরও পাইথোনিক সমাধান, ওস মডিউলে অ্যাসেস চেক করার জন্য os.access ফাংশন রয়েছে :

os.access('/path/to/folder', os.W_OK) # ডাব্লু_ওকে লেখার জন্য, আর_ওকে পড়ার জন্য ইত্যাদি is


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

57
আপনি যদি ডিরেক্টরিতে ফাইল লিখতে চান তবে কেবল রাইট বিটের জন্য ডিরেক্টরি পরীক্ষা করা যথেষ্ট নয়। আপনি যদি ডিরেক্টরিতে লিখতে চান তবে আপনাকে এক্সিকিউট বিটটিরও পরীক্ষা করতে হবে। os.access ('/ पथ / to / ফোল্ডার', os.W_OK | os.X_OK) নিজেই os.W_OK দিয়ে আপনি কেবল ডিরেক্টরি মুছতে পারেন (এবং কেবল ডিরেক্টরিটি ফাঁকা থাকলে)
fthinker

4
এর অন্য gotcha os.access()এটি ব্যবহার চেক হয় বাস্তব ইউআইডি ও gid না কার্যকর বেশী। এটি SID / SGID পরিবেশে অদ্ভুততার কারণ হতে পারে। ('তবে স্ক্রিপ্টটি নির্ধারিত মূলটি চালায়, কেন এটি ফাইলটিতে লিখতে পারে না?')
অ্যালেক্সিয়াস

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

4
একটি উইন্ডোজ নেটওয়ার্ক শেয়ারে সবেমাত্র পরীক্ষিত tested os.access(dirpath, os.W_OK | os.X_OK)আমার লেখার অ্যাক্সেস না থাকলেও সত্য ফিরে আসে।
iamanigeeit

70

এটির পরামর্শ দেওয়া অদ্ভুত মনে হতে পারে তবে একটি সাধারণ পাইথন আইডিয়াম

অনুমতি চেয়ে ক্ষমা চাইতে আরও সহজ

এই মূর্তি অনুসরণ করে, কেউ বলতে পারে:

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


7
+1 পাইথন বা না, অ্যাক্সেসের জন্য এটি পরীক্ষার সবচেয়ে নির্ভরযোগ্য উপায়।
জন ননলারের

5
এটি ডিস্কে লেখার সময় ঘটতে পারে এমন অন্যান্য ত্রুটিগুলিরও যত্ন নেয় - উদাহরণস্বরূপ কোনও ডিস্কস্পেস অবশিষ্ট নেই। এটাই চেষ্টা করার শক্তি wrong আপনার যা ভুল হতে পারে তা মনে রাখার দরকার নেই ;-)
জোচেন রিটেল

4
ধন্যবাদ বন্ধুরা. আমি এখানে যা করছি তার জন্য গতি হ'ল ওস.অ্যাক্সেসের সাথে যাওয়ার সিদ্ধান্ত নেওয়া যদিও আমি অবশ্যই যোগ্যতার বিষয়টি বুঝতে পারি "অনুমতি চেয়ে ক্ষমা চাওয়া সহজ" " ;)
আলোকিত করুন

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

5
সম্ভবত একটি প্রোগ্রাম কেবল লেখার প্রয়োজন ছাড়াই কেবল জানতে চায়। এটি কেবল সম্পত্তি অনুযায়ী কোনও GUI এর চেহারা এবং / অথবা আচরণ পরিবর্তন করতে চাইতে পারে। সেক্ষেত্রে আমি কোনও ফাইলকে পরীক্ষা হিসাবে মুছে ফেলা এবং মুছে ফেলা অজগরটিকে বিবেচনা করব না।
বাচসৌ

20

tempfileমডিউলটি ব্যবহার করে আমার সমাধান :

import tempfile
import errno

def isWritable(path):
    try:
        testfile = tempfile.TemporaryFile(dir = path)
        testfile.close()
    except OSError as e:
        if e.errno == errno.EACCES:  # 13
            return False
        e.filename = path
        raise
    return True

আপডেট: উইন্ডোজে আবার কোডটি পরীক্ষা করার পরে আমি দেখতে পাচ্ছি যে সেখানে টেম্পাইল ব্যবহার করার সময় আসলেই একটি সমস্যা আছে, ইস্যু 22107 দেখুন : টেম্পাইল মডিউলটি উইন্ডোজটিতে অ্যাক্সেস প্রত্যাখ্যান ত্রুটির ভুল ব্যাখ্যা করে । অ-লিখনযোগ্য ডিরেক্টরির ক্ষেত্রে, কোডটি বেশ কয়েক সেকেন্ডের জন্য স্তব্ধ হয়ে থাকে এবং অবশেষে একটি নিক্ষেপ করে IOError: [Errno 17] No usable temporary file name found। সম্ভবত এটি ব্যবহারকারী 2171842 পর্যবেক্ষণ করছিল? দুর্ভাগ্যক্রমে সমস্যাটি আপাতত সমাধান করা হয়নি সুতরাং এটি পরিচালনা করতে ত্রুটিটিও ধরা দরকার:

    except (OSError, IOError) as e:
        if e.errno == errno.EACCES or e.errno == errno.EEXIST:  # 13, 17

বিলম্ব অবশ্যই এখনও এই ক্ষেত্রে উপস্থিত।


4
আমি মনে করি যে টেম্পাইল ব্যবহার করে সে পরিষ্কার হয় কারণ এটি নিশ্চিতভাবে অবশিষ্টাংশ ছেড়ে যায় না।
ঘাসফড়িং

4
এই পদ্ধতিটি ব্যবহার করে কাজ করছে না tempfile। এটি তখনই কাজ করে যখন এর কোনও OSErrorঅর্থ নেই যেখানে এটি লেখার / মুছার অনুমতি রয়েছে। অন্যথায় এটি return Falseত্রুটি ফিরে না পাওয়ার কারণ হবে না এবং স্ক্রিপ্টটি চালানো বা প্রস্থান করা চালিয়ে যাবে না। কিছুই ফিরিয়ে দেওয়া হয় না। এটা ঠিক যে লাইনে আটকে আছে। যাইহোক, খাত্তমের উত্তর হিসাবে অস্থায়ী ফাইল তৈরি করা যখন অনুমতি অনুমোদিত বা অস্বীকৃত হয় উভয়ই কার্যকর হয়। সাহায্য?

এটি ছুঁড়ে OSError: [Errno 30] Read-only file system
ফেলতেও

10

কারও জন্য উদাহরণ অনুসন্ধান করে এই থ্রেড জুড়ে হোঁচট খেয়েছে। গুগলে প্রথম ফলাফল, সম্মিলিত!

লোকেরা এই থ্রেডে পাইথনিক পদ্ধতিতে কাজ করার বিষয়ে কথা বলে, তবে কোনও সাধারণ কোড উদাহরণ নেই? অন্য যে কেউ হোঁচট খায় তার জন্য আপনি এখানে যান:

import sys

filepath = 'C:\\path\\to\\your\\file.txt'

try:
    filehandle = open( filepath, 'w' )
except IOError:
    sys.exit( 'Unable to write to file ' + filepath )

filehandle.write("I am writing this text to the file\n")

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


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

... এবং প্রকৃতপক্ষে আমি এটিকে ভোট দিয়েছি, যা এখন আমি মনে করি এটি একটি ভুল ছিল। রোহাক বর্ণিত শর্ত সহ যেমন উল্লেখ করেছেন তেমন সমস্যা আছে। বিভিন্ন প্ল্যাটফর্মগুলিতে অন্যান্য সমস্যা রয়েছে যেখানে আপনি ডিরেক্টরিটি পরীক্ষা করতে পারেন এবং এটি লিখনযোগ্য মনে হয় তবে এটি আসলে তা নয়। ক্রস-প্ল্যাটফর্ম ডিরেক্টরি লিখনযোগ্য চেকগুলি সম্পাদন করা দেখতে তত বেশি শক্ত। সুতরাং যতক্ষণ আপনি সমস্যাগুলি সম্পর্কে অবগত আছেন, এটি একটি দুর্দান্ত কৌশল হতে পারে। আমি এটি খুব ইউনিক্স-ওয়াই দৃষ্টিকোণ থেকে দেখছিলাম, যা আমার ভুল। কেউ এই উত্তরটি সম্পাদনা করুন যাতে আমি আমার -1 সরাতে পারি।
মাইক এস

আপনি এটি সম্পাদনা করেছেন, আপনি যদি -1 অপসারণ করতে চান :) এবং হ্যাঁ, ক্রস-প্ল্যাটফর্ম ডিরেক্টরি চেকগুলি আরও জটিল হয়ে উঠতে পারে, তবে সাধারণত আপনি সেই ডিরেক্টরিতে একটি ফাইল তৈরি / লিখতে চাইছেন - যে ক্ষেত্রে আমি যে উদাহরণ দিয়েছি তা এখনও প্রয়োগ করা উচিত। যদি কিছু ডিরেক্টরি অনুমতি সম্পর্কিত সমস্যা আসে তবে ফাইল হ্যান্ডেলটি খোলার চেষ্টা করার সময় এটি আইওআরর ফেলে দেওয়া উচিত।
রোহাক

আমি আমার ডাউনটোট সরিয়েছি সে সম্পর্কে দুঃখিত, এবং আপনার অবদানের জন্য ধন্যবাদ।
মাইক এস 16

কোনও উদ্বেগ নেই, লোকেরা উত্তর জিজ্ঞাসা সবসময় স্বাগত জানানো হয়!
রোহাক

9

যদি আপনি কেবল ফাইল পারমস সম্পর্কে যত্নশীল হন তবে os.access(path, os.W_OK)আপনার যা চান তা করা উচিত। আপনি যদি এর পরিবর্তে জানেন যে কিনা আপনি যদি চান করতে পারেন , ডিরেক্টরি লিখতে open()(এটা পূর্বেই উপস্থিত হওয়া উচিত নয়) লেখার জন্য একটি পরীক্ষা ফাইল, ধরা ও কোনো পরীক্ষা IOError, এবং পরে পরীক্ষা ফাইল পরিষ্কার।

আরও সাধারণভাবে, টেকটিউ আক্রমণগুলি এড়াতে (কেবলমাত্র যদি আপনার স্ক্রিপ্টটি উন্নত সুবিধাগুলি - মামলা বা সিজি বা তাই নিয়ে চালিত হয়) তবে আপনার সত্যিকারের এই পরীক্ষাগুলি সত্যই বিশ্বাস করা উচিত নয়, তবে প্রাইভেস ড্রপ করুন open(), করুন এবং আশা করুন IOError


7

মোড বিট পরীক্ষা করুন:

def isWritable(name):
  uid = os.geteuid()
  gid = os.getegid()
  s = os.stat(dirname)
  mode = s[stat.ST_MODE]
  return (
     ((s[stat.ST_UID] == uid) and (mode & stat.S_IWUSR)) or
     ((s[stat.ST_GID] == gid) and (mode & stat.S_IWGRP)) or
     (mode & stat.S_IWOTH)
     )

4
এই সমাধানটি কেবল ইউনিক্স।
বিজন লিন্ডকভিস্ট

4

ক্রিস্টোফিডের উত্তরের ভিত্তিতে আমি এখানে কিছু তৈরি করেছি:

import os

def isWritable(directory):
    try:
        tmp_prefix = "write_tester";
        count = 0
        filename = os.path.join(directory, tmp_prefix)
        while(os.path.exists(filename)):
            filename = "{}.{}".format(os.path.join(directory, tmp_prefix),count)
            count = count + 1
        f = open(filename,"w")
        f.close()
        os.remove(filename)
        return True
    except Exception as e:
        #print "{}".format(e)
        return False

directory = "c:\\"
if (isWritable(directory)):
    print "directory is writable"
else:
    print "directory is not writable"

3
 if os.access(path_to_folder, os.W_OK) is not True:
            print("Folder not writable")
 else :
            print("Folder writable")

অ্যাক্সেস সম্পর্কে আরও তথ্য এটি এখানে খুঁজে পেতে পারেন


4
এটি মূলত চারপাশে কিছুটা মোড়ক সহ ম্যাক্স শবাবাকের উত্তরের একটি অনুলিপি। এটিকে একটি দ্রুত অনুলিপি পেস্ট করে তোলে তবে ম্যাক্সের মূল পোস্টে এটি যুক্ত করা আরও ভাল ধারণা।
জোরিক স্লিজস্টার

1

আরগপার্সের মাধ্যমে যুক্তি যুক্ত করার সময় আমি একই প্রয়োজনে ছুটে এসেছি। বিল্ট ইন type=FileType('w')আমার পক্ষে কাজ করবে না কারণ আমি একটি ডিরেক্টরি খুঁজছিলাম। আমার সমস্যাটি সমাধান করার জন্য আমি নিজের পদ্ধতিটি লিখে শেষ করেছি। এখানে আরগপার্স স্নিপেটের ফলাফল।

#! /usr/bin/env python
import os
import argparse

def writable_dir(dir):
    if os.access(dir, os.W_OK) and os.path.isdir(dir):
        return os.path.abspath(dir)
    else:
        raise argparse.ArgumentTypeError(dir + " is not writable or does not exist.")

parser = argparse.ArgumentParser()
parser.add_argument("-d","--dir", type=writable_dir(), default='/tmp/',
    help="Directory to use. Default: /tmp")
opts = parser.parse_args()

নিম্নলিখিত ফলাফল:

$ python dir-test.py -h
usage: dir-test.py [-h] [-d DIR]

optional arguments:
  -h, --help         show this help message and exit
  -d DIR, --dir DIR  Directory to use. Default: /tmp

$ python dir-test.py -d /not/real
usage: dir-test.py [-h] [-d DIR]
dir-test.py: error: argument -d/--dir: /not/real is not writable or does not exist.

$ python dir-test.py -d ~

আমি ফিরে গিয়ে প্রিন্ট opts.dir প্রান্তে যুক্ত করেছি এবং সমস্ত কিছু পছন্দসই হিসাবে কাজ করছে বলে মনে হচ্ছে।


0

আপনার যদি অন্য ব্যবহারকারীর অনুমতি পরীক্ষা করতে হয় (হ্যাঁ, আমি বুঝতে পারি যে এটি প্রশ্নের বিপরীতমুখী, তবে কারও পক্ষে কার্যকর হতে পারে), আপনি এটি pwdমডিউল এবং ডিরেক্টরিটির মোড বিটের মাধ্যমে করতে পারেন ।

দাবি অস্বীকার - উইন্ডোজে কাজ করে না, কারণ এটি পসিক্স অনুমতিগুলির মডেল ব্যবহার করে না (এবং pwdমডিউলটি সেখানে উপলব্ধ নেই), যেমন - সমাধান কেবল * নিক্স সিস্টেমের জন্য।

মনে রাখবেন যে একটি ডিরেক্টরিতে 3 টি বিট সেট থাকতে হবে - পড়ুন, লিখুন এবং এক্সেক্সট করুন।
ঠিক আছে, আর একটি নিখুঁত আবশ্যক নয়, তবে ডাব্লু / ও এটি আপনি ডিরেক্টরিতে প্রবেশের তালিকাটি তালিকাভুক্ত করতে পারবেন না (যাতে আপনার নামগুলি জানতে হবে)। অন্যদিকে এক্সিকিউট করা একেবারে প্রয়োজন - ডাব্লু / ও এটি ব্যবহারকারী ফাইলের ইনোডগুলি পড়তে পারে না; সুতরাং, এক্স ফাইল ছাড়াই ডাব্লু থাকাও তৈরি বা সংশোধন করা যায় না। এই লিঙ্কে আরও বিস্তারিত ব্যাখ্যা।

অবশেষে, মোডগুলিতে statমডিউল পাওয়া যায় , তাদের বিবরণগুলি ইনোড (7) ম্যানে রয়েছে

নমুনা কোড কীভাবে চেক করবেন:

import pwd
import stat
import os

def check_user_dir(user, directory):
    dir_stat = os.stat(directory)

    user_id, group_id = pwd.getpwnam(user).pw_uid, pwd.getpwnam(user).pw_gid
    directory_mode = dir_stat[stat.ST_MODE]

    # use directory_mode as mask 
    if user_id == dir_stat[stat.ST_UID] and stat.S_IRWXU & directory_mode == stat.S_IRWXU:     # owner and has RWX
        return True
    elif group_id == dir_stat[stat.ST_GID] and stat.S_IRWXG & directory_mode == stat.S_IRWXG:  # in group & it has RWX
        return True
    elif stat.S_IRWXO & directory_mode == stat.S_IRWXO:                                        # everyone has RWX
        return True

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