web-dev-qa-db-ja.com

pythonソケットでのタイムアウトエラーの処理

私はtryを使用する方法を見つけようとしていますが、ソケットのタイムアウトを処理することを除いています。

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例外ブロックを作成しますか?誰かが輸入の違いを説明できますか。

24
Greg Brown
from foo import * 

先頭にアンダースコアを付けずにすべての名前を追加します(またはモジュールで定義された名前のみ__all__属性)fooを現在のモジュールに追加します。

上記のコードでfrom socket import *timeoutを現在のネームスペースにプルしたので、timeoutをキャッチしたいだけです。

from socket import *socket内のすべての定義を取り込みますが、socket自体は追加しません。

try:
    # socketstuff
except timeout:
    print 'caught a timeout'

多くの人がimport *問題があり、それを避けてください。これは、この方法でインポートされた2つ以上のモジュールの共通変数名が互いに重なるためです。

たとえば、次の3つの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

ほんの少しタイピングしますが、すべてが明示的であり、すべてがどこから来たのかは読者には明らかです。

31
stderr

キャッチするだけで十分な成功を収めました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)
5
ThorSummoner

_from socket import *_ pythonを実行すると、socketモジュールが現在のネームスペースにロードされます。したがって、現在のpythonモジュール内で定義されているかのように、モジュールのメンバーを使用できます。

_import socket_を実行すると、モジュールは別のネームスペースにロードされます。メンバーにアクセスするときは、モジュール名をプレフィックスとして付ける必要があります。たとえば、socketクラスを参照する場合は、client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)を記述する必要があります。

タイムアウトの問題については、timeoutクラスがsocketモジュール内で定義されており、すべてをインポートしているため、_except socket.Timeouterror:_を_except timeout:_に変更するだけです。名前空間へのメンバー。

2

私のプロジェクトで使用しているソリューションを次に示します。

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)
0
Édouard Lopez