动机
由this problem激励 - OP正在使用urlopen()
并意外地将sys.argv
列表而不是字符串作为url
传递。抛出此错误消息:
AttributeError:'list'对象没有属性'timeout'
由于编写urlopen
的方式,错误消息本身和回溯信息量不大,特别是对于Python新手来说可能很难理解:
Traceback (most recent call last):
File "test.py", line 15, in <module>
get_category_links(sys.argv)
File "test.py", line 10, in get_category_links
response = urlopen(url)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 420, in open
req.timeout = timeout
AttributeError: 'list' object has no attribute 'timeout'
问题
以下是我正在使用的缩短代码:
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
import sys
def get_category_links(url):
response = urlopen(url)
# do smth with response
print(response)
get_category_links(sys.argv)
我正在考虑是否可以使用PyCharm等智能IDE,静态代码分析工具(如flake8
或pylint
)静态捕获此类错误,或者使用 type annotations 等语言功能。
但是,我没有发现问题:
flake8
和pylint
而言可能过于具体 - 他们没有警告这个问题 PyCharm
并未警告sys.argv
被传递到urlopen
,即使您“跳转到”来源sys.argv
,它也被定义为:
argv = [] # real value of type <class 'list'> skipped
如果我将函数参数注释为字符串并传递sys.argv
,则不会出现警告:
def get_category_links(url: str) -> None:
response = urlopen(url)
# do smth with response
get_category_links(sys.argv)
问题
是否可以静态捕获此问题(不实际执行代码)?
答案 0 :(得分:5)
您可以使用mypy来分析代码,而不是保持编辑器的特定性。这样它就可以在所有开发环境中运行,而不仅仅是那些使用PyCharm的人。
from urllib.request import urlopen
import sys
def get_category_links(url: str) -> None:
response = urlopen(url)
# do smth with response
get_category_links(sys.argv)
response = urlopen(sys.argv)
mypy针对上述代码指出的问题:
error: Argument 1 to "get_category_links" has incompatible type List[str]; expected "str"
error: Argument 1 to "urlopen" has incompatible type List[str]; expected "Union[str, Request]"
这里的Mypy可以猜测sys.argv
的类型,因为它在存根文件中的定义。现在,一些标准库模块仍然是missing from typeshed
,因此您必须提供它们或忽略相关错误,直到它们被添加: - )。
要捕获此类错误,您可以在CI工具中使用带有测试的注释对文件运行mypy。在项目中的所有文件上运行它可能需要一些时间,对于一个小项目,它是您的选择。
添加一个预先提交的钩子,在分段文件上运行mypy并立即指出问题(如果需要一段时间,可能会对开发者有点烦恼)。
答案 1 :(得分:0)
首先,您需要检查url类型是否为字符串,如果是string,则检查ValueError异常(Valid url)
import sys
from urllib2 import urlopen
def get_category_links(url):
if type(url) != type(""): #Check if url is string or not
print "Please give string url"
return
try:
response = urlopen(url)
# do smth with response
print(response)
except ValueError: #If url is string but invalid
print "Bad URL"
get_category_links(sys.argv)