এই ক্ষেত্রে কেন os.path.join () কাজ করে না?


325

নীচের কোডটি যুক্ত হবে না, যখন ডিবাগ করা হবে তখন কমান্ডটি পুরো পথটি সংরক্ষণ করে না কিন্তু কেবল সর্বশেষ এন্ট্রি।

os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')

যখন আমি এটি পরীক্ষা করি এটি কেবল /new_sandbox/কোডের অংশটি সঞ্চয় করে ।

উত্তর:


426

পরবর্তী স্ট্রিংগুলি স্ল্যাশ দিয়ে শুরু করা উচিত নয়। যদি তারা কোনও স্ল্যাশ দিয়ে শুরু করে তবে তাদেরকে একটি "পরম পথ" হিসাবে বিবেচনা করা হয় এবং তাদের আগে সমস্ত কিছু ফেলে দেওয়া হয়।

পাইথন ডক্সের জন্যos.path.join উদ্ধৃতি :

যদি কোনও উপাদান একটি নিখুঁত পথ হয় তবে পূর্ববর্তী সমস্ত উপাদানগুলি ফেলে দেওয়া হয় এবং পরম পাথ উপাদান থেকে যোগদান অব্যাহত থাকে।

উইন্ডোজে নোট করুন, ড্রাইভ চিঠিগুলির সাথে আচরণ, যা আগের পাইথন সংস্করণের তুলনায় পরিবর্তিত হয়েছে বলে মনে হয়:

উইন্ডোজে, যখন কোনও পরম পাথ উপাদান (যেমন, r'\foo') সম্মুখীন হয় তখন ড্রাইভ লেটারটি পুনরায় সেট করা হয় না । যদি কোনও উপাদানটিতে ড্রাইভ লেটার থাকে, তবে পূর্ববর্তী সমস্ত উপাদান ফেলে দেওয়া হয় এবং ড্রাইভ লেটারটি পুনরায় সেট করা হয়। নোট করুন যেহেতু প্রতিটি ড্রাইভের জন্য একটি বর্তমান ডিরেক্টরি রয়েছে তাই ড্রাইভের বর্তমান ডিরেক্টরিটির সাথে সম্পর্কিত os.path.join("c:", "foo")একটি পাথ উপস্থাপন করে C:( c:foo), না c:\foo


85
-1: কোনও স্ট্রিংয়ে একটি "/" অন্তর্ভুক্ত করা উচিত। Os.path.join এর একটি সম্পূর্ণ বিন্দু হ'ল পথে কোনও স্ল্যাশ না দেওয়া।
এস .লট

6
Str.join () এর সমস্যাটি অবশ্যই এটি যে ডাবল স্ল্যাশগুলি দূর করবে না। আমি মনে করি এটি os.path.join ব্যবহার করে লোকদের জন্য প্রাথমিক উদ্দেশ্য। উদাহরণস্বরূপ '/'.জয়িনউদ্দিন'/etc/', '/ conf']) এর ফলে তিনটি
কমিয়ে দেওয়া হয়েছে

17
এই লক্ষ্যটি os.path.normpathঅর্জন করতে আপনি ব্যবহার করতে পারেন
গ্যারেথ লেটি

5
os.path.join আচরণের কারণে লোকেরা কেন হতাশ, সে সম্পর্কে কোনও ধারণা নেই। অন্যান্য ভাষায়, সমান পথ-যোগ গ্রন্থাগার / পদ্ধতি হুবহু আচরণ করে। এটি নিরাপদ এবং আরও বোধগম্য।
ডন চ্যাডল

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

151

ধারণা os.path.join()আপনার প্রোগ্রাম ক্রস-প্ল্যাটফর্ম (লিনাক্সের / উইন্ডোজ / ইত্যাদি) করা হয়।

এমনকি একটি স্ল্যাশ এটি নষ্ট করে দেয়।

সুতরাং এটি কেবল তখনই বুদ্ধিমান হয় যখন কোনও ধরণের রেফারেন্স পয়েন্ট os.environ['HOME']বা এর মতো ব্যবহার করা হয় os.path.dirname(__file__)


75

os.path.join()os.path.sepআপেক্ষিক পথের পরিবর্তে একটি নিখুঁত তৈরি করতে এর সাথে একত্রে ব্যবহার করা যেতে পারে ।

os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')

8
os.path.sepপরম পথ তৈরিতে প্রথম উপাদান হিসাবে ব্যবহার করা এখানে অন্য যে কোনও উত্তরের চেয়ে ভাল! os.pathমৌলিক str পদ্ধতিগুলির পরিবর্তে ব্যবহারের সম্পূর্ণ পয়েন্টটি লেখা এড়ানো /। প্রতিটি উপ-ডিরেক্টরিকে নতুন যুক্তি হিসাবে স্থাপন এবং সমস্ত স্ল্যাশ সরিয়ে নেওয়াও দুর্দান্ত। todaystrস্ল্যাশ দিয়ে শুরু হয় না এমন চেকটি দিয়ে নিশ্চিত করা ভাল ধারণা হতে পারে ! ;)
snooze92

3
এটি উইন্ডোতেও (অজগর ২.7..6) কাজ করে। এটি 'সি: \' এর সাথে হস্তক্ষেপ করেনি এবং উপ-ডিরেক্টরিতে যোগদান করেছে।
রিকফুসুসা

23

রুট ডিরেক্টরিটিকে উল্লেখ করে ব্যতীত পাথ উপাদানগুলির শুরুতে ফরোয়ার্ড স্ল্যাশ ব্যবহার করবেন না:

os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')

আরও দেখুন: http://docs.python.org/library/os.path.html#os.path.join


21

কেন এই বিস্ময়কর আচরণটি সম্পূর্ণ ভয়ানক নয় তা বুঝতে সহায়তা করার জন্য , এমন একটি অ্যাপ্লিকেশন বিবেচনা করুন যা কোনও কনফিগার ফাইলের নামকে আর্গুমেন্ট হিসাবে গ্রহণ করে:

config_root = "/etc/myapp.conf/"
file_name = os.path.join(config_root, sys.argv[1])

যদি অ্যাপ্লিকেশনটি সাথে সম্পাদিত হয়:

$ myapp foo.conf

কনফিগারেশন ফাইলটি /etc/myapp.conf/foo.confব্যবহার করা হবে।

তবে অ্যাপ্লিকেশনটি যদি কল করা হয় তবে কী হবে তা বিবেচনা করুন:

$ myapp /some/path/bar.conf

তারপরে কনফিগারেশন ফাইলটি ব্যবহার করা myapp উচিত/some/path/bar.conf (এবং না /etc/myapp.conf/some/path/bar.confঅনুরূপ)।

এটি দুর্দান্ত নাও হতে পারে তবে আমি বিশ্বাস করি এটিই পরম পথের আচরণের প্রেরণা।


ধন্যবাদ! আপনার উত্তর না পড়া পর্যন্ত আমি সবসময় এই আচরণটিকে ঘৃণা করেছিলাম! এটি ডকুমেন্টস.পাইথন.আর. / ৩.৫ / library / os.path.html # os.path.join নথিবদ্ধ , তবে এটির জন্য অনুপ্রেরণা নয়।
এলিবিবি

এই মুহুর্তে যখন আপনার ঠিক সমাধানের প্রয়োজন হয় তখন অনেক লোককে ভয়াবহ মনে করে।
আশ্রমুন

12

এটি কারণ এটি আপনার '/new_sandbox/'একটি দিয়ে শুরু হয় /এবং এইভাবে মূল ডিরেক্টরিটির সাথে সম্পর্কিত বলে ধরে নেওয়া হয়। নেতৃস্থানীয় সরান /


8

আপনার ফাংশনটিকে আরও বহনযোগ্য করতে, এটি ব্যবহার করুন:

os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')

অথবা

os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')

8

এর কম্বো ব্যবহার করে দেখুন split("/")এবং *বিদ্যমান যোগদান করে দিয়ে স্ট্রিং জন্য।

import os

home = '/home/build/test/sandboxes/'
todaystr = '042118'
new = '/new_sandbox/'

os.path.join(*home.split("/"), todaystr, *new.split("/"))


কিভাবে এটা কাজ করে...

split("/") বিদ্যমান পাথকে তালিকায় পরিণত করে: ['', 'home', 'build', 'test', 'sandboxes', '']

* তালিকার সামনে তার প্রতিটি প্যারামিটার তালিকার প্রতিটি আইটেম বিভক্ত হয়


3

new_sandboxশুধুমাত্র সঙ্গে চেষ্টা করুন

os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')

2

অতিরিক্ত স্ল্যাশ ছাড়াই এটি করুন

root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")

0

মনে রাখবেন যে অনুরূপ ইস্যু আপনাকে দংশিত করতে পারে যদি আপনি os.path.join()ইতিমধ্যে বিন্দুকে অন্তর্ভুক্ত করে এমন কোনও এক্সটেনশান অন্তর্ভুক্ত করেন যা আপনি ব্যবহার করার পরে স্বয়ংক্রিয়ভাবে ঘটে os.path.splitext()। এই উদাহরণে:

components = os.path.splitext(filename)
prefix = components[0]
extension = components[1]
return os.path.join("avatars", instance.username, prefix, extension)

যদিও আপনার extensionহতে পারে .jpg"foobar.jpg" নামক কোনও ফাইলের চেয়ে "foobar" নামক ফোল্ডারটি শেষ করা যায়। এটি রোধ করতে আপনার আলাদাভাবে এক্সটেনশান যুক্ত করতে হবে:

return os.path.join("avatars", instance.username, prefix) + extension

0

আপনি যা করতে পারেন :strip'/'

>>> os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/'.strip('/'))
'/home/build/test/sandboxes/04122019/new_sandbox'

0

আমি দ্বিতীয় এবং নিম্নলিখিত স্ট্রিংগুলি থেকে স্ট্রিংটি সুপারিশ করব os.path.sep, তাদের পরম পথ হিসাবে ব্যাখ্যা করতে বাধা দিতে:

first_path_str = '/home/build/test/sandboxes/'
original_other_path_to_append_ls = [todaystr, '/new_sandbox/']
other_path_to_append_ls = [
    i_path.strip(os.path.sep) for i_path in original_other_path_to_append_ls
]
output_path = os.path.join(first_path_str, *other_path_to_append_ls)

0
os.path.join("a", *"/b".split(os.sep))
'a/b'

একটি পূর্ণ সংস্করণ:

import os

def join (p, f, sep = os.sep):
    f = os.path.normpath(f)
    if p == "":
        return (f);
    else:
        p = os.path.normpath(p)
        return (os.path.join(p, *f.split(os.sep)))

def test (p, f, sep = os.sep):
    print("os.path.join({}, {}) => {}".format(p, f, os.path.join(p, f)))
    print("        join({}, {}) => {}".format(p, f, join(p, f, sep)))

if __name__ == "__main__":
    # /a/b/c for all
    test("\\a\\b", "\\c", "\\") # optionally pass in the sep you are using locally
    test("/a/b", "/c", "/")
    test("/a/b", "c")
    test("/a/b/", "c")
    test("", "/c")
    test("", "c")

আসলে যদি os.sep হয় "\"? তারপরে আপনার প্রথম উদাহরণটি হয়ে যায় os.path.join("a", *"/b".split("\\")), যা ফল দেয় "/b"... আমি সন্দেহ করি এটিই ফলাফল result
নিকটজেন্স

1
আপডেট - আমি মনে করি আপনি যে চালনাটি চালাচ্ছেন সেগুলির থেকে স্থানীয়ভাবে স্বতন্ত্রভাবে আপনি যে পথের সেপ ব্যবহার করছেন তা আপনাকে একটি ইঙ্গিত দিতে হবে
নীল ম্যাকগিল

1
হ্যাঁ. বিকল্পভাবে একজন উভয়ই সাধারণ ব্যবহৃত বিকল্পগুলিতে বিভক্ত হতে পারে ... তবে তার পরে অন্য কিছু ওএস তৃতীয় অংশ নিয়ে আসতে পারে।
নিকটজেন্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.