আপনি যখন পাইথনে ইউআরএল তৈরি করছেন তখন কীভাবে কোনও পাথের উপাদানগুলিতে যোগদান করবেন


103

উদাহরণস্বরূপ, আমি /js/foo.js এর মতো রিসোর্স পাথগুলির একটি উপসর্গের পথে যোগদান করতে চাই।

আমি চাই যে ফলাফলটি পাথটি সার্ভারের মূলের সাথে সম্পর্কিত হোক। উপরের উদাহরণে উপসর্গটি যদি "মিডিয়া" হয় তবে আমি ফলাফলটি /media/js/foo.js হতে চাই।

os.path.join এটি সত্যিই ভাল করে তবে এটি কীভাবে পাথগুলিতে যোগ দেয় এটি ওএস নির্ভর is এই ক্ষেত্রে আমি জানি যে আমি স্থানীয় ফাইল সিস্টেমকে নয়, ওয়েবকে টার্গেট করছি।

আপনি যখন ইউআরএলগুলিতে ব্যবহার করবেন এমন রাস্তাগুলি নিয়ে কাজ করছেন তখন কি কোনও সেরা বিকল্প আছে? Os.path.join কি যথেষ্ট কাজ করবে? আমি কি শুধু আমার নিজের রোল করা উচিত?


1
os.path.joinকাজ করবে না. তবে কেবল /চরিত্রটিতে যোগ দেওয়া সমস্ত ক্ষেত্রে কাজ করা উচিত - /এটি নির্দিষ্টকরণের জন্য এইচটিটিপি-র স্ট্যান্ডার্ড পাথ বিভাজক।
intgr

উত্তর:


60

যেহেতু, ওপি পোস্ট করা মন্তব্যগুলি থেকে, মনে হচ্ছে তিনি যোগদানের "পরম ইউআরএলগুলি" সংরক্ষণ করতে চান না (যা urlparse.urljoin;-) এর মূল কাজগুলির মধ্যে একটি , তাই আমি এড়াতে পরামর্শ দেব)। os.path.joinঠিক একই কারণে, খারাপ হবে।

সুতরাং, আমি এর মতো কিছু ব্যবহার করব '/'.join(s.strip('/') for s in pieces)(যদি নেতৃস্থানীয়দেরও /অবশ্যই উপেক্ষা করা উচিত - যদি শীর্ষস্থানীয় টুকরোটি বিশেষভাবে তৈরি করা আবশ্যক তবে এটি অবশ্যই সম্ভাব্য ;-)।


1
ধন্যবাদ। দ্বিতীয় অংশের শীর্ষস্থানীয় '/' সেখানে থাকতে না পারার পক্ষে এতটা প্রয়োজনীয়তা আমি মনে করি না, তবে প্রথম অংশে '/' লেজের প্রয়োজন পড়ে মনে হয় যেন এই ব্যবহারের ক্ষেত্রে urljoin কিছু করছে না আমার জন্য. আমি কমপক্ষে ("/ মিডিয়া", "জেএস ​​/ foo.js") যোগদান এবং ("/ মিডিয়া /", "জেএস ​​/ foo.js") যোগদান করতে চাই। সঠিক উত্তর বলে মনে হচ্ছে তার জন্য ধন্যবাদ: নিজের নিজস্ব রোল করুন।
amjoconn

আমি আশা করি কিছু আমার জন্য '/' ফেলা এবং যোগদান করবে।
স্ট্যাচুফোমিকে

নাহ, এটি উইন্ডোতে কাজ করছে না, যেখানে os.path.join('http://media.com', 'content')ঘুরঘুর ফিরবে http://media.com\content
এসএফ

154

আপনি ব্যবহার করতে পারেন urllib.parse.urljoin:

>>> from urllib.parse import urljoin
>>> urljoin('/media/path/', 'js/foo.js')
'/media/path/js/foo.js'

তবে সাবধান :

>>> urljoin('/media/path', 'js/foo.js')
'/media/js/foo.js'
>>> urljoin('/media/path', '/js/foo.js')
'/js/foo.js'

আপনি যে কারণে আলাদা ফলাফল পেয়েছেন /js/foo.jsএবং js/foo.jsএর কারণ হল প্রাক্তনটি স্ল্যাশ দিয়ে শুরু হয় যা ইঙ্গিত দেয় যে এটি ইতিমধ্যে ওয়েবসাইটের মূল থেকে শুরু হয়েছে।

পাইথন 2 এ, আপনাকে করতে হবে

from urlparse import urljoin

সুতরাং আমার কাছে /js/foo.js তে শীর্ষস্থানীয় "/" বন্ধ আছে, তবে এটি os.path.join এর ক্ষেত্রেও হবে বলে মনে হয়। মিডিয়া পরে স্ল্যাশ প্রয়োজন মানে যেভাবেই হোক বেশিরভাগ কাজ আমার নিজেরাই করতে হবে।
amjoconn

বিশেষত একবার আমার কাছে থাকলে উপসর্গটি শেষ হতে হবে / এবং লক্ষ্য পথটি শুরু হতে পারে না / আমি পাশাপাশি কেবল সম্মতি জানাতে পারি। এই ক্ষেত্রে আমি নিশ্চিত না যে urljoin আসলেই সহায়তা করছে কিনা?
amjoconn

3
@ মেঘাটগায়েদ এটি আমার পক্ষে পরিষ্কার নয় যে urljoin'/' কে কখনও সরিয়ে দেয়। যদি আমি এটির সাথে urlparse.urljoin('/media/', '/js/foo.js')ফিরে কল করি তবে তা '/js/foo.js' হবে। এটি 'মিডিয়া'র সদৃশ নয়, সমস্ত মিডিয়া সরিয়ে দিয়েছে। বস্তুত urlparse.urljoin('/media//', 'js/foo.js')আসলে আয় '/media//js/foo.js', তাই কোন মুছে সদৃশ।
amjoconn

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

7
দুর্ভাগ্যক্রমে urljoinইউআরএল যোগ দেওয়ার জন্য নয়। এটি এইচটিএমএল ডকুমেন্টস ইত্যাদিতে পাওয়া সম্পর্কিত আপেক্ষিক ইউআরএলগুলি সমাধান করার জন্য
অরেঞ্জডোগ

46

আপনি os.path.joinযেমনটি বলেছেন, বর্তমান ওএসের ভিত্তিতে পাথগুলিতে যোগ দেয়। posixpathঅন্তর্নিহিত মডিউল যা নাম স্থানের অধীনে পোস্টিক্স সিস্টেমে ব্যবহৃত হয় os.path:

>>> os.path.join is posixpath.join
True
>>> posixpath.join('/media/', 'js/foo.js')
'/media/js/foo.js'

সুতরাং আপনি posixpath.joinইউআরএলগুলির পরিবর্তে কেবল আমদানি করতে এবং ব্যবহার করতে পারেন যা উপলভ্য এবং যে কোনও প্ল্যাটফর্মে কাজ করবে ।

সম্পাদনা করুন: @ পিটের পরামর্শটি বেশ ভাল, আপনি বর্ধনযোগ্য পাঠযোগ্যতার জন্য আমদানি করতে পারেন

from posixpath import join as urljoin

সম্পাদনা: আমি মনে করি এটি পরিষ্কার হয়ে গেছে, বা কমপক্ষে আমাকে বুঝতে সহায়তা করেছে, আপনি যদি os.pyউত্সটির সন্ধান করেন তবে (এখানে কোডটি পাইথন ২.7.১১ এর, এছাড়াও আমি কিছু বিট ছাঁটাই করেছি)। os.pyনেমস্পেসে কোন পাথ মডিউলটি ব্যবহার করতে হবে সেগুলিতে শর্তাধীন আমদানি রয়েছে os.path। সকল অন্তর্নিহিত মডিউল ( posixpath, ntpath, os2emxpath, riscospath) যে আমদানি করা যেতে পারে os.py, যেমন ওরফে path, আছে এবং সমস্ত সিস্টেমে ব্যবহার করা যায়। বর্তমান ওএসের উপর ভিত্তি করে রান টাইমে os.pyনেমস্পেসে ব্যবহারের জন্য মডিউলগুলির মধ্যে একটি বেছে নিচ্ছে os.path

# os.py
import sys, errno

_names = sys.builtin_module_names

if 'posix' in _names:
    # ...
    from posix import *
    # ...
    import posixpath as path
    # ...

elif 'nt' in _names:
    # ...
    from nt import *
    # ...
    import ntpath as path
    # ...

elif 'os2' in _names:
    # ...
    from os2 import *
    # ...
    if sys.version.find('EMX GCC') == -1:
        import ntpath as path
    else:
        import os2emxpath as path
        from _emx_link import link
    # ...

elif 'ce' in _names:
    # ...
    from ce import *
    # ...
    # We can use the standard Windows path.
    import ntpath as path

elif 'riscos' in _names:
    # ...
    from riscos import *
    # ...
    import riscospath as path
    # ...

else:
    raise ImportError, 'no os specific module found'

4
from posixpath import join as urljoinএটি পড়ার জন্য সহজ কিছু এটিকে সুন্দরভাবে ডাকিয়া দেয়।
পিট

29

এটি কাজটি সুন্দরভাবে করে:

def urljoin(*args):
    """
    Joins given arguments into an url. Trailing but not leading slashes are
    stripped for each argument.
    """

    return "/".join(map(lambda x: str(x).rstrip('/'), args))

9

Basejoin ফাংশন urllib প্যাকেজ আপনি যা খুঁজছেন তা হতে পারে।

basejoin = urljoin(base, url, allow_fragments=True)
    Join a base URL and a possibly relative URL to form an absolute
    interpretation of the latter.

সম্পাদনা: আমি এর আগে খেয়াল করিনি, তবে urllib.basejoin সরাসরি urlparse.urljoin এ মানচিত্র করে বলে মনে হচ্ছে, পরবর্তীটি পছন্দসই করে।


9

ফুল ব্যবহার করে, pip install furlএটি হবে:

 furl.furl('/media/path/').add(path='js/foo.js')

1
আপনি যদি ফলাফলটি একটি স্ট্রিং হতে চান তবে আপনি .urlশেষে যুক্ত করতে পারেন :furl.furl('/media/path/').add(path='js/foo.js').url
আইয়াল লেভিন

পাইথন 2 কমপক্ষে (y) এর urlparse.urljoin এর সাথে তুলনায় ইউআরএল যোগ দিতে আরও ভাল কাজ করে
সিয়াস্তো পাইকারজ

এটা করতে ভালো furl('/media/path/').add(path=furl('/js/foo.js').path).urlকারণ furl('/media/path/').add(path='/js/foo.js').urlহল/media/path//js/foo.js
Bartolo-otrit

5

আমি জানি এটি ওপি যা চেয়েছিল তার চেয়ে কিছুটা বেশি, তবে আমার কাছে টুকরোটি নীচের ইউআরএলটিতে ছিল এবং আমি তাদের সাথে যোগ দেওয়ার একটি সহজ উপায় খুঁজছিলাম:

>>> url = 'https://api.foo.com/orders/bartag?spamStatus=awaiting_spam&page=1&pageSize=250'

চারপাশে কিছু খুঁজছেন:

>>> split = urlparse.urlsplit(url)
>>> split
SplitResult(scheme='https', netloc='api.foo.com', path='/orders/bartag', query='spamStatus=awaiting_spam&page=1&pageSize=250', fragment='')
>>> type(split)
<class 'urlparse.SplitResult'>
>>> dir(split)
['__add__', '__class__', '__contains__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__getstate__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_asdict', '_fields', '_make', '_replace', 'count', 'fragment', 'geturl', 'hostname', 'index', 'netloc', 'password', 'path', 'port', 'query', 'scheme', 'username']
>>> split[0]
'https'
>>> split = (split[:])
>>> type(split)
<type 'tuple'>

সুতরাং ইতিমধ্যে অন্যান্য উত্তরে উত্তর দেওয়া হয়েছে সেই পথে যোগ দেওয়ার পাশাপাশি, আমি যা খুঁজছিলাম তা পাওয়ার জন্য আমি নিম্নলিখিতটি করেছি:

>>> split
('https', 'api.foo.com', '/orders/bartag', 'spamStatus=awaiting_spam&page=1&pageSize=250', '')
>>> unsplit = urlparse.urlunsplit(split)
>>> unsplit
'https://api.foo.com/orders/bartag?spamStatus=awaiting_spam&page=1&pageSize=250'

ডকুমেন্টেশন অনুযায়ী একটি 5 অংশের টিউপল লাগে।

নিম্নলিখিত টিপল বিন্যাস সহ:

স্কিম 0 ইউআরএল স্কিম নির্দিষ্টকরণকারী খালি স্ট্রিং

নেটলোক 1 নেটওয়ার্ক অবস্থান অংশ খালি স্ট্রিং

পাথ 2 শ্রেণিবদ্ধ পথ খালি স্ট্রিং

ক্যোরি 3 ক্যোয়ারী উপাদান খালি স্ট্রিং

টুকরা 4 খণ্ড শনাক্তকারী খালি স্ট্রিং


5

রুন কাগার্ড একটি দুর্দান্ত এবং কমপ্যাক্ট সমাধান সরবরাহ করেছে যা আমার পক্ষে কাজ করেছে, আমি এটিতে আরও প্রসারিত করেছি:

def urljoin(*args):
    trailing_slash = '/' if args[-1].endswith('/') else ''
    return "/".join(map(lambda x: str(x).strip('/'), args)) + trailing_slash

এটি উপস্থিত থাকলে শেষ স্ল্যাশ সংরক্ষণের সময় অনুসরণ এবং শেষ স্ল্যাশ নির্বিশেষে সমস্ত যুক্তিগুলিতে যোগদানের অনুমতি দেয়।


তালিকা বোধগম্যতা ব্যবহার করে আপনি শেষ লাইনটি আরও খাটো এবং আরও বেশি পাইথোনিক তৈরি করতে পারেন, যেমন:return "/".join([str(x).strip("/") for x in args]) + trailing_slash
ড্যান কোটস

3

অ্যালেক্স মার্তেলির প্রতিক্রিয়াটির তুলনায় কিছুটা উন্নতি করতে, নিম্নলিখিতগুলি অতিরিক্ত স্ল্যাশগুলি কেবল সাফাই করবে না তবে ট্রেইলিং (শেষ) স্ল্যাশগুলি সংরক্ষণ করবে, যা কখনও কখনও দরকারী হতে পারে:

>>> items = ["http://www.website.com", "/api", "v2/"]
>>> url = "/".join([(u.strip("/") if index + 1 < len(items) else u.lstrip("/")) for index, u in enumerate(items)])
>>> print(url)
http://www.website.com/api/v2/

এটি পড়া যেমন সহজ তত সহজ নয়, এবং একাধিক অতিরিক্ত ট্রেলিং স্ল্যাশগুলি পরিষ্কার করা হবে না।


3

উপরের সমস্ত সমাধানগুলি পছন্দ না করার মতো জিনিসগুলি পেয়েছি, তাই আমি নিজেরাই এনেছি। এই সংস্করণটি নিশ্চিত করে যে অংশগুলি একক স্ল্যাশ এবং একা লিডিং এবং ট্রেইলিং স্ল্যাশের সাথে যুক্ত হয়েছে। না pip install, কোন urllib.parse.urljoinঅদ্ভুততা নেই।

In [1]: from functools import reduce

In [2]: def join_slash(a, b):
   ...:     return a.rstrip('/') + '/' + b.lstrip('/')
   ...:

In [3]: def urljoin(*args):
   ...:     return reduce(join_slash, args) if args else ''
   ...:

In [4]: parts = ['https://foo-bar.quux.net', '/foo', 'bar', '/bat/', '/quux/']

In [5]: urljoin(*parts)
Out[5]: 'https://foo-bar.quux.net/foo/bar/bat/quux/'

In [6]: urljoin('https://quux.com/', '/path', 'to/file///', '//here/')
Out[6]: 'https://quux.com/path/to/file/here/'

In [7]: urljoin()
Out[7]: ''

In [8]: urljoin('//','beware', 'of/this///')
Out[8]: '/beware/of/this///'

In [9]: urljoin('/leading', 'and/', '/trailing/', 'slash/')
Out[9]: '/leading/and/trailing/slash/'

0

ফুল এবং রেজেেক্স ব্যবহার করে (পাইথন 3)

>>> import re
>>> import furl
>>> p = re.compile(r'(\/)+')
>>> url = furl.furl('/media/path').add(path='/js/foo.js').url
>>> url
'/media/path/js/foo.js'
>>> p.sub(r"\1", url)
'/media/path/js/foo.js'
>>> url = furl.furl('/media/path').add(path='js/foo.js').url
>>> url
'/media/path/js/foo.js'
>>> p.sub(r"\1", url)
'/media/path/js/foo.js'
>>> url = furl.furl('/media/path/').add(path='js/foo.js').url
>>> url
'/media/path/js/foo.js'
>>> p.sub(r"\1", url)
'/media/path/js/foo.js'
>>> url = furl.furl('/media///path///').add(path='//js///foo.js').url
>>> url
'/media///path/////js///foo.js'
>>> p.sub(r"\1", url)
'/media/path/js/foo.js'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.