ネットワーク接続を確認しています


133

オンラインAPIにアクセスできるかどうかを確認したいのですが、そのためにはインターネットアクセスが必要です。

Pythonを使用して利用可能なアクティブな接続があるかどうかを確認するにはどうすればよいですか?


Pythonを使用している場合、ほとんどの場合、接続障害またはタイムアウトが発生すると例外がスローされます。あなたはそれを試す/キャッチするか、単にそれを浮上させることができます。
jdizzle

1
@Triptych:うまくいかないので、それは冗談だったと思います
inspectorG4dget

1
@ inspectorG4dget:easy_install system_of_tubes
S.Lott

2
@aF:Unutbuのソリューションを見てください。これは、google.comにアクセスできるかどうかを確認する方法を(可能な限り最速で)示しています。問題がAPIへのアクセスに関係している場合は、timeout = 1に設定してアクセスしてみてください。これにより、アクセスしたいAPIがアクセス可能かどうかが正確にわかります。それがわかったら、APIにアクセスするか、アクセスできるようになるまで待つことができます。
inspectorG4dget

私が言ったように、私はunutbuが言ったような単純なものが必要でした。あなたはこれでそのような大騒ぎをする必要はありません..
aF。

回答:


132

おそらく、次のようなものを使用できます。

import urllib2

def internet_on():
    try:
        urllib2.urlopen('http://216.58.192.142', timeout=1)
        return True
    except urllib2.URLError as err: 
        return False

現在、216.58.192.142はgoogle.comのIPアドレスの1つです。迅速な対応が期待できるサイトに変更http://216.58.192.142ます。

この固定IPはgoogle.comに永久にマッピングされません。したがって、このコードは堅牢ではありません。コードを機能させるには、定期的なメンテナンスが必要です。

上記のコードが完全修飾ドメイン名(FQDN)ではなく固定IPアドレスを使用する理由は、FQDNがDNSルックアップを必要とするためです。マシンにインターネット接続が機能していない場合、DNSルックアップ自体がurllib_request.urlopen 1秒以上。これを指摘してくれた@rzetterbergに感謝します。


上記の固定IPアドレスが機能しない場合、次のコマンドを実行すると、google.com(UNIX)の現在のIPアドレスを見つけることができます

% dig google.com  +trace 
...
google.com.     300 IN  A   216.58.192.142

1
urlopenインターネットが「オン」になっていなくても、への通話に1秒以上かかることはありません。指定されたURLが無効な場合、これは当てはまりません。DNSルックアップがブロックされます。これは、Webサーバーへの実際の接続にのみ当てはまります。このDNSルックアップブロックを回避する最も簡単な方法は、代わりにIPアドレスを使用することです。1秒しか
かから

8
これはもはや機能しません。2013年9月の時点で、74.125.113.99は長時間経過するとタイムアウトになるため、この関数は常にFalseを返します。Googleがネットワークを変更したと思います。
theamk 2013

4
あとは簡単です。「74.125.113.99 urllib」のGoogle。不正なコードを組み込んだ何千ものオープンソースプロジェクトを返します。(私にとって、最初のページには少なくとも5つが含まれています:nvpy、sweekychebot、malteseDict、upy、checkConnection)。彼らは今すべて壊れています。
theamk 2013

4
明確でない場合は、この方法を使用しないことをお勧めします。古いIPは3年未満で十分でした。新しいIPは今日機能します。あなたのプロジェクトにそれを入れてください、そして、それは再び、3年未満で神秘的に壊れるかもしれません。
theamk 2013

1
えっと…ただ開けhttp://google.comば、みんながここで話し続けている問題をすべて解決できます。IPアドレスを使用する必要はありません...
Jason C

106

インターネットサーバーに接続できれば、接続は確立されています。ただし、最速かつ最も信頼性の高いアプローチのために、すべてのソリューションは少なくとも次の要件に準拠する必要があります。

  • DNS解決を回避する(よく知られており、ほとんどの時間利用できることが保証されているIPが必要です)
  • アプリケーション層の接続を回避する(HTTP / FTP / IMAPサービスに接続する)
  • Pythonまたはその他の選択した言語からの外部ユーティリティの呼び出しを回避します(サードパーティのソリューションに依存しない、言語に依存しないソリューションを考え出す必要があります)。

これらに準拠するには、1つのアプローチとして、GoogleのパブリックDNSサーバーの 1つにアクセスできるかどうかを確認します。これらのサーバーのIPv4アドレスは8.8.8.8および8.8.4.4です。それらのいずれかに接続してみることができます。

ホストの簡単なNmap 8.8.8.8は以下の結果を与えました:

$ sudo nmap 8.8.8.8

Starting Nmap 6.40 ( http://nmap.org ) at 2015-10-14 10:17 IST
Nmap scan report for google-public-dns-a.google.com (8.8.8.8)
Host is up (0.0048s latency).
Not shown: 999 filtered ports
PORT   STATE SERVICE
53/tcp open  domain

Nmap done: 1 IP address (1 host up) scanned in 23.81 seconds

ご覧のとおり、53/tcpは開いており、フィルタリングされていません。非rootユーザーの場合は、sudoまたは-PnNmap の引数を使用して、巧妙に細工されたプローブパケットを送信し、ホストが起動しているかどうかを確認してください。

Pythonを試す前に、外部ツールNetcatを使用して接続をテストしてみましょう。

$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!

netcatを、我々は達することができることを確認8.8.8.8オーバー53/tcp。これ8.8.8.8:53/tcpで、Pythonでへのソケット接続を設定して、接続を確認できます。

import socket

def internet(host="8.8.8.8", port=53, timeout=3):
    """
    Host: 8.8.8.8 (google-public-dns-a.google.com)
    OpenPort: 53/tcp
    Service: domain (DNS/TCP)
    """
    try:
        socket.setdefaulttimeout(timeout)
        socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
        return True
    except socket.error as ex:
        print(ex)
        return False

internet()

別の方法としては、手動で作成したDNSプローブをこれらのサーバーの1つに送信して、応答を待つ方法があります。ただし、パケットのドロップやDNS解決の失敗などにより、速度が遅くなる可能性があると思います。それ以外の場合はコメントしてください。

更新#1:@theamkのコメントのおかげで、タイムアウトは引数になり3s、デフォルトで初期化されます。

更新#2:この質問に対するすべての有効な回答の最も速くて最も一般的な実装を特定するために、簡単なテストを行いました。要約は次のとおりです。

$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.487

iamaziz.py
True
00:00:00:00.335

ivelin.py
True
00:00:00:00.105

jaredb.py
True
00:00:00:00.533

kevinc.py
True
00:00:00:00.295

unutbu.py
True
00:00:00:00.546

7h3rAm.py
True
00:00:00:00.032

そしてもう一度:

$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.450

iamaziz.py
True
00:00:00:00.358

ivelin.py
True
00:00:00:00.099

jaredb.py
True
00:00:00:00.585

kevinc.py
True
00:00:00:00.492

unutbu.py
True
00:00:00:00.485

7h3rAm.py
True
00:00:00:00.035

True上記の出力では、それぞれの作成者によるこれらすべての実装がインターネットへの接続を正しく識別していることを示しています。時間はミリ秒単位で表示されます。

更新#3:例外処理の変更後に再度テスト:

defos.py
True
00:00:00:00.410

iamaziz.py
True
00:00:00:00.240

ivelin.py
True
00:00:00:00.109

jaredb.py
True
00:00:00:00.520

kevinc.py
True
00:00:00:00.317

unutbu.py
True
00:00:00:00.436

7h3rAm.py
True
00:00:00:00.030

6
これは、DNS解決を避け、最良の答えであり、皮肉なことに、ポート53上でGoogleのDNSサービスをコンサルティング
m3nda

1
@AviMehenwal GoogleはこのIPを無料のDNS名前解決サービスの一部として提供しています。Googleが別の方法で決定しない限り、IPは変更されません。私は何年も問題なく代替DNSサーバーとして使用してきました。
7h3rAm

1
@ルークそれを指摘してくれてありがとう。例外をユーザーに通知し、デフォルトの回答としてFalseを返すように回答を更新しました。
7h3rAm 2016年

2
@JasonC TCP / 53への接続は、ポート53経由のDNS接続とは異なります。類推によれば、アプリケーションで使用されるすべてのTCPポートは、アプリケーションレベルのプロトコル接続として分類されます。いいえ、そうではありません。TCPソケットを介したポートへの接続は、アプリケーションレベルの接続ではありません。DNSルックアップを行うのではなく、TCPの半分のハンドシェイクを行うだけです。これは、完全なDNSルックアップを行うことと同じではありません。
7h3rAm 2016年

2
close()ソケットを呼び出さないでください。
brk

60

HEADリクエストを作成する方が高速なので、HTMLはフェッチされません。
また、グーグルはこの方法でそれをより良くしたいと思います:)

try:
    import httplib
except:
    import http.client as httplib

def have_internet():
    conn = httplib.HTTPConnection("www.google.com", timeout=5)
    try:
        conn.request("HEAD", "/")
        conn.close()
        return True
    except:
        conn.close()
        return False

8
20ミリ秒しかかかりませんが、トップの回答は1秒です。
ウォーリー

8
+1サーバーが到達可能で応答しているかどうかを確認するだけの場合は、ページ全体をダウンロードしても意味がありません。コンテンツが必要な場合は、コンテンツをダウンロードしてください
thatsIch

理由もなく、「8.8」というURLを使用しても機能しますが、「8.8」または「8.8」は実際のWebブラウザでは機能しません。
Polv

2時間、有効なソリューションを探していたところ、これがわかりました...クリーンでシンプル
Pedro Serpa

21

ubutnu's / Kevin Cの回答の代わりに、次のrequestsようなパッケージを使用します。

import requests

def connected_to_internet(url='http://www.google.com/', timeout=5):
    try:
        _ = requests.get(url, timeout=timeout)
        return True
    except requests.ConnectionError:
        print("No internet connection available.")
    return False

ボーナス:これは、Webサイトにpingするこの機能に拡張できます。

def web_site_online(url='http://www.google.com/', timeout=5):
    try:
        req = requests.get(url, timeout=timeout)
        # HTTP errors are not raised by default, this statement does that
        req.raise_for_status()
        return True
    except requests.HTTPError as e:
        print("Checking internet connection failed, status code {0}.".format(
        e.response.status_code))
    except requests.ConnectionError:
        print("No internet connection available.")
    return False

1
リクエストは素晴らしいライブラリです。ただし、多くの例とは異なり、IANAのexample.comまたはexample.orgは、ICANNによって完全に制御されるため、より信頼性の高い長期的な選択肢として使用します
2017年

インターネットの稼働状況を確認する他の方法はありますか?google.comもう一度ピン留めすると、IPがブロックされます。他に方法はありますか?
Sanjiv

15

Python 3.2の新しいコードについてunutbuが言ったことを更新するだけです

def check_connectivity(reference):
    try:
        urllib.request.urlopen(reference, timeout=1)
        return True
    except urllib.request.URLError:
        return False

そして、注意してください、ここでの入力(参照)は、確認するURLです:私はあなたが住んでいる場所にすばやく接続するものを選択することをお勧めします-つまり、私は韓国に住んでいるため、おそらくhttp:/への参照を設定します/www.naver.com


利用可能なDNSサーバーがない場合は30秒待機します。
Viktor

10

あなただけのデータをダウンロードしようとすることができ、接続が失敗した場合は、接続に問題があることがわかります。

基本的に、コンピュータがインターネットに接続されているかどうかを確認することはできません。失敗には、DNS構成の誤り、ファイアウォール、NATなど、多くの理由が考えられます。したがって、いくつかのテストを行ったとしても、実際に試すまでは、APIとの接続が保証されるわけではありません。


2
「許可よりも許しを求める方が簡単です」
cobbal

これはそれほど良い必要はありません。私は単にサイトに接続するか、何かをpingする必要があり、タイムアウトが発生する場合は失敗します。どうやってやるの?
aF。

APIに接続できない理由はありますか?実際に接続する前に確認する必要があるのはなぜですか?
Tomasz Wysocki

私はpythonを使用してhtmlページを作成します。HTMLページは、Pythonプログラムで指定する引数に依存しています。APIにアクセスできる場合にのみ、HTMLコードを配置する必要があります。それが私が以前に知る必要がある理由です。
aF。

6
import urllib

def connected(host='http://google.com'):
    try:
        urllib.urlopen(host)
        return True
    except:
        return False

# test
print( 'connected' if connected() else 'no internet!' )

Python 3の場合は、 urllib.request.urlopen(host)


4

とにかくしようとした操作を試してください。失敗した場合、Pythonは例外をスローして通知します。

最初にいくつかの簡単な操作を試みて接続を検出すると、競合状態が発生します。テスト時にインターネット接続は有効だが、実際の作業を行う前にダウンした場合はどうなりますか?


3

localhostが127.0.0.1 Try から変更されている場合、これは機能しない可能性があります

import socket
ipaddress=socket.gethostbyname(socket.gethostname())
if ipaddress=="127.0.0.1":
    print("You are not connected to the internet!")
else:
    print("You are connected to the internet with the IP address of "+ ipaddress )

編集しない限り、インターネットに接続していない場合、コンピューターのIPは127.0.0.1になります。このコードは基本的にIPアドレスを取得し、それがlocalhost IPアドレスであるかどうかを尋ねます。それが役に立てば幸い


これは興味深いチェックですが、ネットワークに接続されているかどうかしか確認できません。それがインターネットであるかNATで接続されたサブネットであるかは、依然として問題のままです。
7h3rAm

@ 7h3rAm、それは良い点です。DCHPはインターネット接続を必要としません。

これには、IPが割り当てられたネットワークNIC接続が必要です。他のすべての回答とは異なり、LAN、ルーター、ファイアウォール、ISPへの接続が別のシステムまで必要ありません。それは非DHCP割り当てられたアドレス(静的)だかどうかは、まだNICが接続されていることを示すために失敗した
user150471

@ user150471、すでに指摘したように、あなたの貢献に感謝します。

3

これが私のバージョンです

import requests

try:
    if requests.get('https://google.com').ok:
        print("You're Online")
except:
    print("You're Offline")

1
私はこれが好きですが、リクエストから発生した特定のタイムアウトまたは接続エラーを除いた方がいいでしょう。すぐに、すぐに使えるCtrl-Cがオフラインで印刷されます。
user2561747

2

を備えた最新のポータブルソリューションrequests

import requests

def internet():
    """Detect an internet connection."""

    connection = None
    try:
        r = requests.get("https://google.com")
        r.raise_for_status()
        print("Internet connection detected.")
        connection = True
    except:
        print("Internet connection not detected.")
        connection = False
    finally:
        return connection

または、例外を発生させるバージョン:

import requests
from requests.exceptions import ConnectionError

def internet():
    """Detect an internet connection."""

    try:
        r = requests.get("https://google.com")
        r.raise_for_status()
        print("Internet connection detected.")
    except ConnectionError as e:
        print("Internet connection not detected.")
        raise e

1

これを行う最良の方法は、PythonがWebサイトを見つけられない場合に常に提供するIPアドレスに対してチェックを行うことです。この場合、これは私のコードです:

import socket

print("website connection checker")
while True:
    website = input("please input website: ")
    print("")
    print(socket.gethostbyname(website))
    if socket.gethostbyname(website) == "92.242.140.2":
        print("Website could be experiencing an issue/Doesn't exist")
    else:
        socket.gethostbyname(website)
        print("Website is operational!")
        print("")

1

クラスターでスクリプトを実行するかどうかに関係なく、

import subprocess

def online(timeout):
    try:
        return subprocess.run(
            ['wget', '-q', '--spider', 'google.com'],
            timeout=timeout
        ).returncode == 0
    except subprocess.TimeoutExpired:
        return False

これはwgetを静かに実行し、何もダウンロードせずに、指定されたリモートファイルがWeb上に存在することを確認します


0

撮影unutbuの答えの開始点としての、および「静的」IPアドレスを変更することで、過去に焼かれた、私はDNSルックアップを使用して一度チェックが(すなわち、「URLを使用していることを単純なクラスを作りました// WWW:HTTPS .google.com ")、次に、後続のチェックで使用するために応答サーバーのIPアドレスを保存します。このようにして、IPアドレスは常に最新の状態になります(クラスが少なくとも数年ごとに1回程度再初期化されると仮定)。また、この回答についてgawryに感謝します。これにより、サーバーのIPアドレスを取得する方法がわかりました(リダイレクト後など)。このソリューションの明らかなハックを無視してください。ここでは最小限の作業例を示します。:)

これが私が持っているものです:

import socket

try:
    from urllib2 import urlopen, URLError
    from urlparse import urlparse
except ImportError:  # Python 3
    from urllib.parse import urlparse
    from urllib.request import urlopen, URLError

class InternetChecker(object):
    conn_url = 'https://www.google.com/'

    def __init__(self):
        pass

    def test_internet(self):
        try:
            data = urlopen(self.conn_url, timeout=5)
        except URLError:
            return False

        try:
            host = data.fp._sock.fp._sock.getpeername()
        except AttributeError:  # Python 3
            host = data.fp.raw._sock.getpeername()

        # Ensure conn_url is an IPv4 address otherwise future queries will fail
        self.conn_url = 'http://' + (host[0] if len(host) == 2 else
                                     socket.gethostbyname(urlparse(data.geturl()).hostname))

        return True

# Usage example
checker = InternetChecker()
checker.test_internet()

0

シックスの答えを取ると、私はどういうわけか単純化できると思います。非常に技術的な問題で新規参入者が失われるので、重要な問題です。

ここで、PVモニタリングのために1日に1回接続(3G、低速)が確立されるのを待つために最終的に使用するものです。

Rypbian 3.4.2のPyth3で動作します

from urllib.request import urlopen
from time import sleep
urltotest=http://www.lsdx.eu             # my own web page
nboftrials=0
answer='NO'
while answer=='NO' and nboftrials<10:
    try:
        urlopen(urltotest)
        answer='YES'
    except:
        essai='NO'
        nboftrials+=1
        sleep(30)       

最大実行時間:5分に達した場合、1時間で試してみますが、もう1つのスクリプトです!


あなたのessai varは使われませんか?
kidCoder 2017年

0

私のルーターがIPアドレス192.168.0.1を配信し、google.comへのクエリ時にインターネットに接続していない場合はヘッドを返すため、Ivelinの回答受け取り、追加のチェックを追加します。

import socket

def haveInternet():
    try:
        # first check if we get the correct IP-Address or just the router's IP-Address
        info = socket.getaddrinfo("www.google.com", None)[0]
        ipAddr = info[4][0]
        if ipAddr == "192.168.0.1" :
            return False
    except:
        return False

    conn = httplib.HTTPConnection("www.google.com", timeout=5)
    try:
        conn.request("HEAD", "/")
        conn.close()
        return True
    except:
        conn.close()
        return False

0

これはPython3.6で私のために働きます

import urllib
from urllib.request import urlopen


def is_internet():
    """
    Query internet using python
    :return:
    """
    try:
        urlopen('https://www.google.com', timeout=1)
        return True
    except urllib.error.URLError as Error:
        print(Error)
        return False


if is_internet():
    print("Internet is active")
else:
    print("Internet disconnected")

0

Joelのコードにいくつか追加しました。

    import socket,time
    mem1 = 0
    while True:
        try:
                host = socket.gethostbyname("www.google.com") #Change to personal choice of site
                s = socket.create_connection((host, 80), 2)
                s.close()
                mem2 = 1
                if (mem2 == mem1):
                    pass #Add commands to be executed on every check
                else:
                    mem1 = mem2
                    print ("Internet is working") #Will be executed on state change

        except Exception as e:
                mem2 = 0
                if (mem2 == mem1):
                    pass
                else:
                    mem1 = mem2
                    print ("Internet is down")
        time.sleep(10) #timeInterval for checking

0

私のプロジェクトでは、GoogleパブリックDNSサーバー8.8.8.8にpingするように変更されたスクリプトを使用します。1秒のタイムアウトを使用し、外部依存関係のないコアPythonライブラリ:

import struct
import socket
import select


def send_one_ping(to='8.8.8.8'):
   ping_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp'))
   checksum = 49410
   header = struct.pack('!BBHHH', 8, 0, checksum, 0x123, 1)
   data = b'BCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwx'
   header = struct.pack(
      '!BBHHH', 8, 0, checksum, 0x123, 1
   )
   packet = header + data
   ping_socket.sendto(packet, (to, 1))
   inputready, _, _ = select.select([ping_socket], [], [], 1.0)
   if inputready == []:
      raise Exception('No internet') ## or return False
   _, address = ping_socket.recvfrom(2048)
   print(address) ## or return True


send_one_ping()

選択タイムアウト値は1であるが、この例では1秒よりも容易に失敗する任意の浮動小数点数であることができます。


0

リクエストをインポートして、この単純なPythonコードを試してください。

def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
    _ = requests.get(url, timeout=timeout)
    return True
except requests.ConnectionError:
return False
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.