处理python套接字中的超时错误
Posted
技术标签:
【中文标题】处理python套接字中的超时错误【英文标题】:Handling a timeout error in python sockets 【发布时间】:2012-08-05 15:10:01 【问题描述】:我试图弄清楚如何使用 try 和 except 来处理套接字超时。
from socket import *
def main():
client_socket = socket(AF_INET,SOCK_DGRAM)
client_socket.settimeout(1)
server_host = 'localhost'
server_port = 1234
while(True):
client_socket.sendto('Message',(server_host,server_port))
try:
reply, server_address_info = client_socket.recvfrom(1024)
print reply
except socket.Timeouterror:
#more code
我添加套接字模块的方式是导入所有内容,但是如何处理文档中的异常,它说您可以使用 socket.timeouterror,但这对我不起作用。另外,如果我做了import socket
,我将如何编写try 异常块?有人还可以解释进口的区别吗?
【问题讨论】:
【参考方案1】:from foo import *
将foo
中不带前导下划线的所有名称(或仅在模块__all__
属性中定义的名称)添加到当前模块中。
在上面带有from socket import *
的代码中,您只想捕获timeout
,因为您已将timeout
拉入当前命名空间。
from socket import *
提取 socket
内所有内容的定义,但不添加 socket
本身。
try:
# socketstuff
except timeout:
print 'caught a timeout'
许多人认为import *
有问题并尽量避免。这是因为以这种方式导入的 2 个或多个模块中的公共变量名称会相互冲突。
例如,考虑以下三个 python 文件:
# a.py
def foo():
print "this is a's foo function"
# b.py
def foo():
print "this is b's foo function"
# yourcode.py
from a import *
from b import *
foo()
如果您运行yourcode.py
,您将只看到输出“这是 b 的 foo 函数”。
出于这个原因,我建议要么导入模块并使用它,要么从模块中导入特定名称:
例如,带有显式导入的代码如下所示:
import socket
from socket import AF_INET, SOCK_DGRAM
def main():
client_socket = socket.socket(AF_INET, SOCK_DGRAM)
client_socket.settimeout(1)
server_host = 'localhost'
server_port = 1234
while(True):
client_socket.sendto('Message', (server_host, server_port))
try:
reply, server_address_info = client_socket.recvfrom(1024)
print reply
except socket.timeout:
#more code
只是多打了一点点,但一切都很明确,读者很清楚一切的来源。
【讨论】:
我认为你的意思是socket.timeout
而不是 socket.Timeouterror
: docs.python.org/2/library/socket.html#socket.timeout【参考方案2】:
我已经取得了足够的成功,只是赶上了socket.timeout
和socket.error
;尽管可以出于多种原因引发 socket.error 。小心点。
import socket
import logging
hostname='google.com'
port=443
try:
sock = socket.create_connection((hostname, port), timeout=3)
except socket.timeout as err:
logging.error(err)
except socket.error as err:
logging.error(err)
【讨论】:
【参考方案3】:当您执行from socket import *
时,python 正在将socket
模块加载到当前命名空间。因此,您可以使用模块的成员,就好像它们是在您当前的 python 模块中定义的一样。
当您执行import socket
时,模块会加载到单独的命名空间中。当你访问它的成员时,你应该在它们前面加上一个模块名称。例如,如果要引用socket
类,则需要编写client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
。
至于超时问题 - 您只需将 except socket.Timeouterror:
更改为 except timeout:
,因为 timeout
类是在 socket
模块中定义的,并且您已将其所有成员导入您的命名空间。
【讨论】:
【参考方案4】:这是我在一个项目中使用的解决方案。
network_utils.telnet
import socket
from timeit import default_timer as timer
def telnet(hostname, port=23, timeout=1):
start = timer()
connection = socket.socket()
connection.settimeout(timeout)
try:
connection.connect((hostname, port))
end = timer()
delta = end - start
except (socket.timeout, socket.gaierror) as error:
logger.debug('telnet error: ', error)
delta = None
finally:
connection.close()
return
hostname: delta
测试
def test_telnet_is_null_when_host_unreachable(self):
hostname = 'unreachable'
response = network_utils.telnet(hostname)
self.assertDictEqual(response, 'unreachable': None)
def test_telnet_give_time_when_reachable(self):
hostname = '127.0.0.1'
response = network_utils.telnet(hostname, port=22)
self.assertGreater(response[hostname], 0)
【讨论】:
以上是关于处理python套接字中的超时错误的主要内容,如果未能解决你的问题,请参考以下文章
heroku 中的 Django Redis 连接错误:写入套接字时出现错误 110。连接超时
TimeoutError:[Errno 60]操作超时(Python套接字请求)