Python: 如何检查是否可以使用可选参数?

Python: how to check if optional argument can be used?

使用 urllib2,最新版本允许在调用 urlopen 时使用可选参数 "context"。

我整理了一些代码来利用它:

# For Python 3.0 and later
from urllib.request import urlopen, HTTPError, URLError
except ImportError:
# Fall back to Python 2's urllib2
from urllib2 import urlopen, HTTPError, URLError
import ssl

context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
response = urlopen(url=url, context=context)

运行 我的 python 2.78 ... 我得到:

Traceback (most recent call last):
  File "test.py", line 5, in <module>
  context = ssl.create_default_context()
  AttributeError: 'module' object has no attribute 'create_default_context'

所以我想:那我们去python3吧;现在我得到:

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    response = urlopen(url=url, context=context)
TypeError: urlopen() got an unexpected keyword argument 'context'

我花了一段时间才发现使用那个命名参数上下文...还需要比我的 ubuntu 14.04 上安装的 3.4.0 更新的 python 版本。

我的问题:在调用 urlopen 时,检查 "context" 是否可用的 "canonical" 方法是什么?只是调用它并期待 TypeError?或者对我在 运行 中的 python 进行准确的版本检查?

我确实在这里和 google 进行了搜索,但也许我只是错过了正确的搜索词……因为我找不到任何有用的东西……

这里描述了如何检查函数的签名:How can I read a function's signature including default argument values?

但是,某些函数具有通用签名,例如:

def myfunc(**kwargs):
    print kwargs.items()

    if kwargs.has_key('foo'):
        ...

    if kwargs.has_key('bar'):
        ...

在调用它们之前不可能知道它们使用了哪些参数。例如 matplotlib / pylab 有很多这样的函数使用 kwargs.

使用try/except。见 python glossary:

EAFP

Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

检查Python的版本:

import sys

if sys.hexversion >= 0x03050000:
    urlopen = urllib.urlopen
else:
    def urlopen (*args, context=None, **kwargs):
        return urllib.urlopen(*args, **kwargs)

现在只需使用 urlopen() 而不是 urllib.urlopen()

我认为这将在 3.5 的早期 alpha 中中断,但 alpha 注定要中断,所以我不太关心追踪引入此参数的确切版本。