在 Python 个请求中使用 super() 继承多个 Session
Using super() to inherit from multiple Sessions in Python requests
为了以 DRY 方式编写许多 HTTP 请求,我想定义 requests Session 的几个子类,并根据需要从它们继承。我试过以下方法:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
但是,如果我尝试 运行 这个(在 Python 3 中),我得到
In [9]: exec(open('requestbin_test_python3.py').read())
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-cc670860ddd1> in <module>()
----> 1 exec(open('requestbin_test_python3.py').read())
<string> in <module>()
TypeError: __init__() missing 1 required positional argument: 'auth_token'
我希望 super().__init__
应用于 AuthorizedJSONDebugSession
将是 'clever enough' 以了解 auth_token
用于初始化 AuthorizedSession
和verify
初始化 DebugSession
。 (仅使用 AuthorizedSession
和 JSONSession
的类似示例确实有效)。
然而,情况似乎并非如此。我如何修改此代码以使其工作?
我非常怀疑这种方法在一般情况下是否有效,但您可以尝试显式调用所需的 __init__
方法:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
AuthorizedSession.__init__(self, auth_token)
JSONSessions.__init__(self)
DebugSession.__init__(self, verify=verify)
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
看看这个
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
您的问题是 with AuthorizedJSONDebugSession()
您没有提供任何参数,但 init 方法需要 1 个身份验证令牌参数。 def __init__(self, auth_token, verify=False)
这与尝试执行以下操作基本相同:
>>> x=10
>>> def foo(x):
... return x + 1
...
>>> foo()
TypeError: foo() missing 1 required positional argument: 'x'
在函数范围内,x
与全局x
不一样
要解决此问题,请执行以下操作:
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
或者,您可以更改 init 方法来执行此操作,但我不推荐这样做。
def __init__(self, auth_token=auth_token, verify=False)
您还应该注意如何使用 super()
传递参数。在这方面,您的代码还有其他一些问题。您必须确保 MRO 中的每个 class 都在与您想要做的事情合作,并将参数传递给 superclass.
你也应该熟悉Python的super
是如何工作的,这与其他语言不同。
处理这个问题的标准方法是只允许关键字参数并使所有 类 接受 **kwargs
:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, **kwargs):
try:
self.auth_token = kwargs.pop('auth_token')
except KeyError:
raise TypeError('Missing auth_token parameter!')
super().__init__(**kwargs)
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, **kwargs):
self.verify = kwargs.pop('verify', False)
super().__init__(**kwargs)
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, **kwargs):
super().__init__(**kwargs)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
dict.pop
方法查找给定的键并将其从字典中删除。第二个参数是要使用的默认值,如果没有提供 KeyError
则被引发。
请注意,必不可少 每当您在子类中定义 __init__
时,您也会调用 super().__init__(**kwargs)
,即使您认为在那种情况下不需要。因为将子类添加到具有多个祖先的 类 的层次结构中可以更改 mro,并且如果不执行此调用,您可能会导致初始化失败。
为了以 DRY 方式编写许多 HTTP 请求,我想定义 requests Session 的几个子类,并根据需要从它们继承。我试过以下方法:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
但是,如果我尝试 运行 这个(在 Python 3 中),我得到
In [9]: exec(open('requestbin_test_python3.py').read())
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-cc670860ddd1> in <module>()
----> 1 exec(open('requestbin_test_python3.py').read())
<string> in <module>()
TypeError: __init__() missing 1 required positional argument: 'auth_token'
我希望 super().__init__
应用于 AuthorizedJSONDebugSession
将是 'clever enough' 以了解 auth_token
用于初始化 AuthorizedSession
和verify
初始化 DebugSession
。 (仅使用 AuthorizedSession
和 JSONSession
的类似示例确实有效)。
然而,情况似乎并非如此。我如何修改此代码以使其工作?
我非常怀疑这种方法在一般情况下是否有效,但您可以尝试显式调用所需的 __init__
方法:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
AuthorizedSession.__init__(self, auth_token)
JSONSessions.__init__(self)
DebugSession.__init__(self, verify=verify)
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
看看这个
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
您的问题是 with AuthorizedJSONDebugSession()
您没有提供任何参数,但 init 方法需要 1 个身份验证令牌参数。 def __init__(self, auth_token, verify=False)
这与尝试执行以下操作基本相同:
>>> x=10
>>> def foo(x):
... return x + 1
...
>>> foo()
TypeError: foo() missing 1 required positional argument: 'x'
在函数范围内,x
与全局x
要解决此问题,请执行以下操作:
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
或者,您可以更改 init 方法来执行此操作,但我不推荐这样做。
def __init__(self, auth_token=auth_token, verify=False)
您还应该注意如何使用 super()
传递参数。在这方面,您的代码还有其他一些问题。您必须确保 MRO 中的每个 class 都在与您想要做的事情合作,并将参数传递给 superclass.
你也应该熟悉Python的super
是如何工作的,这与其他语言不同。
处理这个问题的标准方法是只允许关键字参数并使所有 类 接受 **kwargs
:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, **kwargs):
try:
self.auth_token = kwargs.pop('auth_token')
except KeyError:
raise TypeError('Missing auth_token parameter!')
super().__init__(**kwargs)
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, **kwargs):
self.verify = kwargs.pop('verify', False)
super().__init__(**kwargs)
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, **kwargs):
super().__init__(**kwargs)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
dict.pop
方法查找给定的键并将其从字典中删除。第二个参数是要使用的默认值,如果没有提供 KeyError
则被引发。
请注意,必不可少 每当您在子类中定义 __init__
时,您也会调用 super().__init__(**kwargs)
,即使您认为在那种情况下不需要。因为将子类添加到具有多个祖先的 类 的层次结构中可以更改 mro,并且如果不执行此调用,您可能会导致初始化失败。