paj*_*j28 16 python python-requests
使用Session时,似乎每次都需要提供完整的URL,例如
session = requests.Session()
session.get('http://myserver/getstuff')
session.get('http://myserver/getstuff2')
Run Code Online (Sandbox Code Playgroud)
这有点单调乏味.有没有办法做这样的事情:
session = requests.Session(url_base='http://myserver')
session.get('/getstuff')
session.get('/getstuff2')
Run Code Online (Sandbox Code Playgroud)
rou*_*ble 12
此功能已被要求在论坛上几次1,2,3.这里记录的首选方法是子类化,如下所示:
from requests import Session
from urlparse import urljoin
class LiveServerSession(Session):
def __init__(self, prefix_url=None, *args, **kwargs):
super(LiveServerSession, self).__init__(*args, **kwargs)
self.prefix_url = prefix_url
def request(self, method, url, *args, **kwargs):
url = urljoin(self.prefix_url, url)
return super(LiveServerSession, self).request(method, url, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
你可以简单地使用它如下:
baseUrl = 'http://api.twitter.com'
with LiveServerSession(baseUrl) as s:
resp = s.get('/1/statuses/home_timeline.json')
Run Code Online (Sandbox Code Playgroud)
rob*_*one 11
你可以像这样子类化request.Session和重载它__init__和request方法:
# my_requests.py
import requests
class SessionWithUrlBase(requests.Session):
# In Python 3 you could place `url_base` after `*args`, but not in Python 2.
def __init__(self, url_base=None, *args, **kwargs):
super(SessionWithUrlBase, self).__init__(*args, **kwargs)
self.url_base = url_base
def request(self, method, url, **kwargs):
# Next line of code is here for example purposes only.
# You really shouldn't just use string concatenation here,
# take a look at urllib.parse.urljoin instead.
modified_url = self.url_base + url
return super(SessionWithUrlBase, self).request(method, modified_url, **kwargs)
Run Code Online (Sandbox Code Playgroud)
然后你可以使用你的子类代替requests.Session你的代码:
from my_requests import SessionWithUrlBase
session = SessionWithUrlBase(url_base='https://stackoverflow.com/')
session.get('documentation') # https://stackoverflow.com/documentation
Run Code Online (Sandbox Code Playgroud)
你也可以使用monkey-patch requests.Session来避免修改现有的代码库(这个实现应该是100%兼容的),但是在任何代码调用之前一定要做实际的修补requests.Session():
# monkey_patch.py
import requests
class SessionWithUrlBase(requests.Session):
...
requests.Session = SessionWithUrlBase
Run Code Online (Sandbox Code Playgroud)
然后:
# main.py
import requests
import monkey_patch
session = requests.Session()
repr(session) # <monkey_patch.SessionWithUrlBase object at ...>
Run Code Online (Sandbox Code Playgroud)
requests_toolbelt.sessions.BaseUrlSession https://github.com/requests/toolbelt/blob/f5c86c51e0a01fbc8b3b4e1c286fd5c7cb3aacfa/requests_toolbelt/sessions.py#L6
注意:这使用标准库中的urljoin。当心urljoin的行为。
In [14]: from urlparse import urljoin
In [15]: urljoin('https://localhost/api', '/resource')
Out[15]: 'https://localhost/resource'
In [16]: urljoin('https://localhost/api', 'resource')
Out[16]: 'https://localhost/resource'
In [17]: urljoin('https://localhost/api/', '/resource')
Out[17]: 'https://localhost/resource'
In [18]: urljoin('https://localhost/api/', 'resource')
Out[18]: 'https://localhost/api/resource'
Run Code Online (Sandbox Code Playgroud)
要么
import requests
from functools import partial
def PrefixUrlSession(prefix=None):
if prefix is None:
prefix = ""
else:
prefix = prefix.rstrip('/') + '/'
def new_request(prefix, f, method, url, *args, **kwargs):
return f(method, prefix + url, *args, **kwargs)
s = requests.Session()
s.request = partial(new_request, prefix, s.request)
return s
Run Code Online (Sandbox Code Playgroud)