2017-03-04 19 views
5

Podczas korzystania z sesji wydaje się, że za każdym razem należy podać pełny adres URL, np.Żądania w pythonie: baza adresów URL w sesji

session = requests.Session() 
session.get('http://myserver/getstuff') 
session.get('http://myserver/getstuff2') 

To trochę żmudne. Czy istnieje sposób, aby zrobić coś takiego:

session = requests.Session(url_base='http://myserver') 
session.get('/getstuff') 
session.get('/getstuff2') 

Odpowiedz

1

nie widzę wbudowany sposób to zrobić, ale można użyć funkcji otoki, aby dodać funkcjonalność chcesz:

from functools import wraps 
import inspect 
import requests 
from requests.compat import urljoin 

def _base_url(func, base): 
    '''Decorator for adding a base URL to func's url parameter''' 

    @wraps(func) 
    def wrapper(*args, **kwargs): 
     argname = 'url' 
     argspec = inspect.getargspec(func) 

     if argname in kwargs: 
      kwargs[argname] = urljoin(base, kwargs[argname]) 
     else: 
      # Find and replace url parameter in positional args. The argspec 
      # includes self while args doesn't, so indexes have to be shifted 
      # over one 
      for i, name in enumerate(argspec[0]): 
       if name == argname: 
        args = list(args) 
        args[i-1] = urljoin(base, args[i-1]) 
        break 

     return func(*args, **kwargs) 
    return wrapper 

def inject_base_url(func): 
    '''Decorator for adding a base URL to all methods that take a url param''' 

    @wraps(func) 
    def wrapper(*args, **kwargs): 
     argname = 'base_url' 

     if argname in kwargs: 
      obj = args[0] 

      # Add base_url decorator to all methods that have a url parameter 
      for name, method in inspect.getmembers(obj, inspect.ismethod): 
       argspec = inspect.getargspec(method.__func__) 

       if 'url' in argspec[0]: 
        setattr(obj, name, _base_url(method, kwargs[argname])) 

      del kwargs[argname] 

     return func(*args, **kwargs) 
    return wrapper 

# Wrap requests.Session.__init__ so it takes a base_url parameter 
setattr(
    requests.Session, 
    '__init__', 
    inject_base_url(getattr(requests.Session, '__init__')) 
) 

teraz można określić podstawowy adres URL podczas budowy nowego obiektu requests.Session:

s = requests.Session(base_url='http://stackoverflow.com') 
s.get('questions')  # http://stackoverflow.com/questions 
s.post('documentation') # http://stackoverflow.com/documentation 

# With no base_url, you get the default behavior 
s = requests.Session() 
s.get('http://google.com') 
+0

lubię tę odpowiedź, ale to działa tylko wtedy, gdy baza url ma podpoziomów jak bo 'urljoin' nadpisuje je z tym, co jest warunkiem uzyskania jak URL i metod post. potrzebowałem go w moim przypadku, więc zamieniłem wywołanie 'urljoin' z prostą konkatenacją ciągów –

4

można tylko podklasy request.Session przeciążenia jego __init__ i request metody takie jak to:

# 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) 

A potem można użyć swoją podklasę zamiast requests.Session w kodzie:

from my_requests import SessionWithUrlBase 


session = SessionWithUrlBase(url_base='https://stackoverflow.com/') 
session.get('documentation') # https://stackoverflow.com/documentation 

Również można małpa-łata requests.Session uniknąć modyfikując istniejące codebase (implementacja ta powinna być 100% kompatybilny), ale należy to zrobić przed wywołuje rzeczywiste łatanie dowolny kod requests.Session():

# monkey_patch.py 
import requests 


class SessionWithUrlBase(requests.Session): 
    ... 

requests.Session = SessionWithUrlBase 

, a następnie:

# main.py 
import requests 
import monkey_patch 


session = requests.Session() 
repr(session) # <monkey_patch.SessionWithUrlBase object at ...> 
Powiązane problemy