예를 들어 /js/foo.js와 같은 리소스 경로에 대한 접두사 경로를 결합하고 싶습니다.
결과 경로가 서버의 루트에 상대적 이길 원합니다. 위의 예에서 접두사가 “media”이면 결과는 /media/js/foo.js가됩니다.
os.path.join은이 작업을 정말 잘 수행하지만 경로를 연결하는 방법은 OS에 따라 다릅니다. 이 경우 로컬 파일 시스템이 아닌 웹을 대상으로한다는 것을 알고 있습니다.
URL에서 사용되는 경로로 작업 할 때 가장 좋은 대안이 있습니까? os.path.join이 충분히 잘 작동합니까? 내가 직접 굴려야하나요?
답변
OP가 게시 한 댓글에서 그는 조인 ( ;- 의 핵심 작업 중 하나)에서 “절대 URL”을 보존하고 싶지 않은 것 urlparse.urljoin
같으 므로 피하는 것이 좋습니다. os.path.join
정확히 같은 이유로 나쁠 것입니다.
그래서 나는 다음과 같은 것을 사용할 것입니다. '/'.join(s.strip('/') for s in pieces)
(리딩 /
도 무시해야한다면-리딩 부분이 특수한 경우라면 당연히 가능합니다 ;-).
답변
다음을 사용할 수 있습니다 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
전자는 이미 웹 사이트의 루트에서 시작 것을 의미 슬래시로 시작하기 때문이다.
Python 2에서는 다음을 수행해야합니다.
from urlparse import urljoin
답변
말했듯 os.path.join
이 현재 OS를 기반으로 경로를 결합합니다. posixpath
네임 스페이스 아래 posix 시스템에서 사용되는 기본 모듈입니다 os.path
.
>>> os.path.join is posixpath.join
True
>>> posixpath.join('/media/', 'js/foo.js')
'/media/js/foo.js'
따라서 사용 posixpath.join
가능하며 모든 플랫폼에서 작동하는 URL 대신 가져 와서 사용할 수 있습니다 .
편집 : @Pete의 제안은 좋은 것입니다. 가독성을 높이기 위해 가져 오기를 별칭으로 지정할 수 있습니다.
from posixpath import join as urljoin
편집 : 소스를 살펴보면 이것이 더 명확 해졌거나 적어도 이해하는 데 도움이되었다고 생각합니다 os.py
(여기 코드는 Python 2.7.11에서 가져온 것입니다. os.py
네임 스페이스에서 사용할 경로 모듈을 선택하는 조건부 가져 오기가 있습니다 os.path
. 모든 기본 모듈 ( posixpath
, ntpath
, os2emxpath
, riscospath
)에서 가져올 수 os.py
별칭으로, path
, 거기 모든 시스템에서 사용할 수 존재한다. 현재 OS를 기반으로 런타임에 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'
답변
이것은 일을 훌륭하게 수행합니다.
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))
답변
urllib 패키지 의 basejoin 함수는 당신이 찾고있는 것일 수 있습니다.
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에 직접 매핑되어 후자가 선호됩니다.
답변
furl을 사용 pip install furl
하면 다음과 같습니다.
furl.furl('/media/path/').add(path='js/foo.js')
답변
나는 이것이 OP가 요청한 것보다 조금 더 많다는 것을 알고 있지만 다음 URL에 조각을 가지고 있었고 간단한 방법을 찾고있었습니다.
>>> 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 URL 체계 지정자 빈 문자열
netloc 1 네트워크 위치 부분 빈 문자열
경로 2 계층 적 경로 빈 문자열
쿼리 3 쿼리 구성 요소 빈 문자열
조각 4 조각 식별자 빈 문자열