- Как словить exception от socket.timeout?
- Python Socket Accept Timeout
- Socket Accept, Reject, and Timeout
- Socket Methods and Their Uses in Python
- Example of Socket Accept Timeout in Python
- Socket Accept Timeout in Python When No Timeout Limit Is Set
- Socket Accept Timeout in Python When Timeout Is Set
- Set Default Timeout For Each Socket in Python
- Conclusion
- Related Article — Python Socket
Как словить exception от socket.timeout?
Пишу одну небольшую программу, иконка в трее и уведомления о непрочитанных письмах в почтовом ящике. Программа уже на стадии завершения, сейчас делаю «защиту от дурака», обрабатываю некоторые распространенные ошибки, чтобы юзеру выводилось сообщение об ошибке, а не краш программы.
Конкретно застрял на вводе заведомо неправильных параметров ящика (логин, пароль, порт). Экспериментирую с подсовыванием программе вместо своего собственного почтового сервера адреса «mail.yandex.ru». Программа от этого на несколько секунд впадает в ступор, а потом вываливается со следующим выхлопом:
Traceback (most recent call last): File "./mail-notifier.py", line 198, in mail_check() File "./mail-notifier.py", line 161, in mail_check if (SettingsExist() == True and Mail().testConnection() == False): File "./mail-notifier.py", line 142, in __init__ self.imap = imaplib.IMAP4_SSL(settings.value("MailServer"), settings.value("Port")) File "/usr/lib64/python3.4/imaplib.py", line 1221, in __init__ IMAP4.__init__(self, host, port) File "/usr/lib64/python3.4/imaplib.py", line 181, in __init__ self.open(host, port) File "/usr/lib64/python3.4/imaplib.py", line 1234, in open IMAP4.open(self, host, port) File "/usr/lib64/python3.4/imaplib.py", line 257, in open self.sock = self._create_socket() File "/usr/lib64/python3.4/imaplib.py", line 1224, in _create_socket sock = IMAP4._create_socket(self) File "/usr/lib64/python3.4/imaplib.py", line 247, in _create_socket return socket.create_connection((self.host, self.port)) File "/usr/lib64/python3.4/socket.py", line 512, in create_connection raise err File "/usr/lib64/python3.4/socket.py", line 503, in create_connection sock.connect(sa) socket.timeout: timed out
Вот класс Mail(), который занимается проверкой почты ( checkMail() ) и проверкой на доступность соединения с почтовым ящиком ( testConnection () ).
class Mail(): def __init__(self): self.user = settings.value("Login") self.password = settings.value("Password") socket.setdefaulttimeout(5) self.imap = imaplib.IMAP4_SSL(settings.value("MailServer"), settings.value("Port")) self.imap.login(self.user, self.password) def checkMail(self): self.imap.select() self.unRead = self.imap.search(None, 'UnSeen') return len(self.unRead[1][0].split()) def testConnection(self): # This code doesn't work try: socket.create_connection(settings.value("MailServer"),settings.value("Port"),2) return True except: pass return False
Есть еще небольшая отдельная функция mail_check() которая только использует этот класс и обрабатывает полученные результаты (присваивает текст разным tooltip’ам, и тому подобные безобидные вещи). Вот она:
def mail_check(): if (SettingsExist() == True and Mail().testConnection() == True): if Mail().checkMail() == 0: window.mailboxEmpty() else: window.mailboxFull() else: window.mailboxError()
Вопрос: почему у меня exception в методе testConnection() не срабатывает, хотя стоит только он один и ни на одну категорию ошибки не настроен, должен обрабатывать все? Мне нужно сделать так, чтобы программа не крашилась и я бы мог отправить юзеру сообщение об ошибке при работающей программе.
Python Socket Accept Timeout
- Socket Accept, Reject, and Timeout
- Socket Methods and Their Uses in Python
- Example of Socket Accept Timeout in Python
- Set Default Timeout For Each Socket in Python
- Conclusion
The socket is the basic building block for network communication. A socket is opened whenever two network entities need to transfer the data.
These sockets stay connected during the session. But sometimes, while working with sockets in Python, you may be left waiting for long periods while the other end still accepts the socket connection.
This article discusses the timeout feature of sockets in Python that is necessary to mitigate the issue of waiting for socket accept for an infinite time.
Socket Accept, Reject, and Timeout
Whenever you try to establish a connection to a server using Python script, you are required to open a socket connection. This socket connection acts as a tunnel for transferring the data between the client and the server.
Socket Accept : When the socket is opened successfully, and the server and client are now connected to send and receive data, we term it socket accept . This scenario is the final goal of opening a socket.
Socket reject : Let us say you opened a socket but passed some different parameters, forgot to pass parameters or the process of opening a socket was not followed correctly; you would get a reject. It means the connection to send and receive data could not be established.
Socket Accept timeout : This is an important yet overlooked scenario. Sometimes when you try to open a socket, you may not get any response from the other end.
Due to this, you are left waiting forever. This is an unwanted situation as you would like to close the current request and try another request rather than wait forever.
Socket Methods and Their Uses in Python
accept() : As the name suggests, the accept() method accepts an incoming socket request from another party. This method returns a socket connection that you can use to transfer the data between the connected entities.
bind() : This method binds or attaches a socket connection to an address. This method is a must to be called method if you want to work with sockets.
The bind() method accepts a tuple of an IP address and a port to which it binds the socket.
listen() : This is a server-side method that enables the server to accept a socket to transfer data between the connections.
connect() : This method accepts an address as an argument. It then connects the remote socket at the address.
settimeout() : This method accepts a non-zero number as the number of seconds to wait before it raises a TimeoutError . This method is important to mitigate the problem of infinite wait times.
Example of Socket Accept Timeout in Python
Let us look at an example of socket accept timeout with the help of code in Python. For this example, we would need to write two Python scripts, one for the server and the other for the client.
The first scenario is when there is no timeout limit set. In this case, the client would keep on waiting.
Note that, depending on your operating system, the request may be automatically turned down after some time.
The second scenario is where we set the timeout limit using the settimeout() method. In this case, you will get the TimeoutError after the set limit.
Let us see the codes of the three cases above one by one.
Socket Accept Timeout in Python When No Timeout Limit Is Set
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('', 1717))
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect(('127.0.0.1', 1717))
You can see no listen() method on the server side. Therefore, the server is not responding, and the client is waiting.
Socket Accept Timeout in Python When Timeout Is Set
In this case, you will see that the client aborts the operation and raises a TimeoutError after the timeout time is passed.
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('', 1717))
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(3) s.connect(('127.0.0.1', 1717))
In this case, a Python socket TimeoutError is raised. Please note that sockets can behave differently depending on the platform.
On the Linux machine, the socket throws the ConnectionRefusedError: [Errno 111] Connection refused error until you do not accept the socket on the server side.
Set Default Timeout For Each Socket in Python
This method would set the same default timeout for all your new sockets. In this way, you can save time and hassle by setting the timeout for each socket separately.
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('', 1717))
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: socket.setdefaulttimeout(3) s.connect(('127.0.0.1', 1717))
Note that for setdefaulttimeout() , you must use the socket class directly instead of the object because it sets the timeout for all threads.
Conclusion
The socket timeout is an important aspect of socket programming in Python. If you do not handle the timeout, you may leave your client waiting for the socket forever.
Or in the other case, depending on your environment implementation, it may throw an error.
Related Article — Python Socket
Copyright © 2023. All right reserved