【问题标题】:Test if an internet connection is present in python测试python中是否存在互联网连接
【发布时间】:2014-01-21 16:46:44
【问题描述】:

我有以下代码来检查是否存在互联网连接。

import urllib2

def internet_on():
    try:
        response=urllib2.urlopen('http://74.125.228.100',timeout=20)
        return True
    except urllib2.URLError as err: pass
    return False

这将测试互联网连接,但效果如何?

我知道互联网的质量因人而异,所以我正在寻找对广谱最有效的东西,上面的代码似乎存在人们可以找到错误的漏洞。例如,如果某人的连接速度非常慢,并且响应时间超过 20 秒。

【问题讨论】:

  • 为什么?正如所问的,这听起来像是“在跳跃之前先看”的简单示例。更好的方法通常是“请求宽恕比许可容易”。如果您解释您要完成的工作,您可能会得到更好的答案。
  • @Jean-PaulCalderone 在我的程序开始执行一些将更新系统的任务之前,我正在尝试确保用户有互联网连接。比如从镜像下载包,然后安装。
  • 你为什么不试试下载那些包呢?如果与镜像的连接尝试超时,那么您可以向用户报告超时。用户将非常更喜欢这种体验,而不是您尝试检测他们的网络是否正常工作的错误尝试。

标签: python python-2.7 networking


【解决方案1】:

我的方法是这样的:

import socket
REMOTE_SERVER = "one.one.one.one"
def is_connected(hostname):
  try:
    # see if we can resolve the host name -- tells us if there is
    # a DNS listening
    host = socket.gethostbyname(hostname)
    # connect to the host -- tells us if the host is actually
    # reachable
    s = socket.create_connection((host, 80), 2)
    s.close()
    return True
  except:
     pass
  return False
%timeit is_connected(REMOTE_SERVER)
> 10 loops, best of 3: 42.2 ms per loop

如果没有连接,这将在不到一秒的时间内返回(OSX,Python 2.7)。

注意:此测试可能会返回误报——例如DNS 查找可能会返回本地网络中的服务器。要真正确保您已连接到互联网并与有效主机通信,请务必使用更复杂的方法(例如 SSL)。

【讨论】:

  • 这似乎是一个更好的方法。
  • 如果用户已将 www.google.com 添加到他们的 /etc/hosts 文件中怎么办?如果他们正在运行本地缓存名称服务器或在附近有缓存名称服务器的 LAN 上怎么办?如果他们“连接到互联网”但流量实际上没有正确路由怎么办?失败的方法有很多。
  • @Jean-PaulCalderone 公平点,包括实际的连接测试和相应的评论。如果您认为合适,请随时改进答案
  • 不要使用google.com,而是使用1.1.1.1,它会一直运行,速度更快,而且不会有隐私问题。 1.1.1.1 是 DNS 服务器,需要保持正常运行。 1.1.1.1也可以通过one.one.one.one访问
  • @smarie 取决于您可以使用请求的代理类型或类似PySocks
【解决方案2】:

从 Python 2.6 和更新版本(包括 Python 3)开始,一个更直接且与 IPv6 兼容的解决方案是

import socket


def is_connected():
    try:
        # connect to the host -- tells us if the host is actually
        # reachable
        socket.create_connection(("1.1.1.1", 53))
        return True
    except OSError:
        pass
    return False

它解析名称并在断定它处于脱机状态之前尝试连接到每个返回地址。这也包括 IPv6 地址。

【讨论】:

  • 感谢您的解决方案
  • 我可能还会检查其他端口,例如网站的 443,已知 ftp 站点或某些 dns 服务器的 21,例如,可能 ping 一些众所周知的 IP 地址,以防 dns被缓存或阻止...
【解决方案3】:

检查互联网可用性的有效方法(修改了@andrebrait 的答案)。

import socket

def isConnected():
    try:
        # connect to the host -- tells us if the host is actually
        # reachable
        sock = socket.create_connection(("www.google.com", 80))
        if sock is not None:
            print('Clossing socket')
            sock.close
        return True
    except OSError:
        pass
    return False

【讨论】:

    【解决方案4】:

    我已经用了一段时间了, 工作正常

    import requests 
    while True:
        try:
            requests.get('https://www.google.com/').status_code
            break
        except:
            time.sleep(5)
            pass
    

    【讨论】:

    • 有没有我们可以使用的事件处理程序来代替 while 循环。顺便说一句,while 循环会痛吗?
    • 这里的 while 循环停止程序当前正在执行的任何其他操作,因此我将使用您必须导入的 await asyncio.sleep() 以及 time。此外,您不需要.status_code,因为您只想检查主机是否可访问。到目前为止,其余的似乎都不错(虽然没有测试)
    • @FlexGames 你是对的,但这有点取决于很多脚本的情况,我需要停止执行直到建立网络连接,所以我只使用while 循环跨度>
    【解决方案5】:

    这会起作用

    import urllib
    try :
        stri = "https://www.google.co.in"
        data = urllib.urlopen(stri)
        print "Connected"
    except e:
        print "not connected" ,e 
    

    【讨论】:

    • 这是不好的方法!因为你加载了整个页面!你不需要这个!
    • @Ievgen 有没有其他方法可以检查互联网运行状态。因为如果您再次 PIN google.com,那么他们将阻止我们的 IP。那么还有其他方法吗?
    【解决方案6】:

    补充miraculixx's answer;可能会发生很多情况

    1. 用户没有网络适配器或没有连接到网络。这可以在 DNS 解析失败时检测到 (socket.gethostbyname)

    2. 用户连接到具有直接互联网访问权限的本地网络(无 DNS 代理,无 TCP/HTTP 代理)。在这种情况下,DNS 解析失败 (socket.gethostbyname) 也将表明与 Internet 的连接丢失

    3. 用户连接到存在 DNS 代理但不需要 TCP/HTTP(s) 代理来访问互联网的本地网络。在这种情况下,DNS 解析成功不足以表明连接到 Internet,需要 HTTP 查询(或至少在 HTTP(s) 端口上打开 TCP 会话):socket.create_connection

    4. 用户连接到需要 TCP/HTTP(s) 代理才能访问互联网的本地网络。在这种情况下,socket.create_connection失败,因为 TCP 套接字需要指向代理,而不是最终主机。您可以使用urllib.getproxies (python 2) 或urllib.request.getproxies (python 3) 获取当前代理配置。因此,在使用urllib.parse.urlparse 识别代理信息后,您可以使用urllib ——更容易——requests 来建立到某个已知 url 的 HTTP GET。

    但是,如果用户没有在urllibrequests 使用的操作系统环境变量中配置代理,而是一个接一个地配置他的工具,那么最后一种方法可能会失败(表明实际上没有连接) (例如 conda 使用 .condarc proxy_servers 部分)。在这种情况下,没有什么神奇的方法可以检测故障是否来自错误的代理配置或 Internet 连接丢失 - 除了检查您希望实际使用的工具的代理配置文件。

    作为结论,

    • dns 解析失败是检测“无法访问互联网”的可靠方法
    • 如果您确定用户没有坐在代理后面(例如移动应用程序),失败/成功的 TCP 会话是检测“没有/有互联网访问”的好方法李>
    • 否则,使用requests 成功的 HTTP GET 是检测“可以访问互联网”的好方法,但失败不足以表明任何事情

    另请参阅this page 了解与代理相关的配置技巧。

    【讨论】:

      【解决方案7】:

      这是我在 Windows 上用于持续监控连接的脚本。以绿色/红色打印,并在连接中断时减少等待时间。

      from datetime import datetime
      import time, os, requests
      from termcolor import colored
      
      os.system('color')
      url = 'https://www.google.com/'
      timeout = 2
      sleep_time = 10
      op = None
      
      while True:
          now = datetime.now()
          try:
              op = requests.get(url, timeout=timeout).status_code
              if op == 200:
                  print(now, colored("Connected", "green"))
                  sleep_time = 10
              else:
                  print(now, colored("Status Code is not 200", "red"))
                  print("status Code", op)
          except:
              print(now, colored("Not Connected", "red"))
              print("status Code", op)
              sleep_time = 5
          time.sleep(sleep_time)
      

      【讨论】:

        【解决方案8】:

        对于检查网络可用性,Http 级别似乎太高了。

        尽管如此,您可以创建一个线程来定期检查连接并存储连接状态,接下来 internet_on 方法可以只检查存储的状态。这应该比每次都测试连接性更快。

        【讨论】:

        • 它只需要检查一次连接,就在你运行它的时候。
        【解决方案9】:

        虽然答案已被勾选,但它对我没有帮助,我收到了类似的错误

        urllib2 未定义

        所以我曾尝试使用 pip 安装 urllib2 库,但无能为力,然后我四处寻找,幸运的是我找到了解决方案 请检查以下代码,分享因为有人会遇到我以前遇到的问题,会得到解决方案

        from urllib.request import urlopen
        
        def is_internet_available():
            try:
                urlopen('http://216.58.192.142', timeout=1)
                return True
            except:
                return False
        
        
        print(is_internet_available())
        

        【讨论】:

          【解决方案10】:

          通过从 NTP 服务器获取当前日期,可以间接了解 Internet 是否连接。

          import ntplib
          import datetime, time
              
          
          try:
          
              client = ntplib.NTPClient()
              response = client.request('pool.ntp.org')
              Internet_date_and_time = datetime.datetime.fromtimestamp(response.tx_time)  
              print('\n')
              print('Internet date and time as reported by server: ',Internet_date_and_time)
          
          
          except OSError:
          
              print('\n')
              print('Internet date and time could not be reported by server.')
              print('There is not internet connection.')
              
          

          【讨论】:

            【解决方案11】:

            我们可以在一行内测试互联网连接,但是这种方法不建议每次都使用。使用此答案了解 python 中的一行编码;)

            print((lambda a: 'Internet connected and working' if 0 == a.system('ping google.com -w 4 > clear') else 'Internet not connected.')(__import__('os')))
            

            在上述代码中,__import__ 函数将在一行中导入模块。

            正常方式:

            import os
            def check_internet():
                cmd = os.system('ping google.com -w 4 > clear')
                if cmd == 0:
                    print('Internet is connected')
                else:
                    print('Internet is not connected')
            
            if __name__ == '__main__':
                check_internet()
            

            用python中的一行编码的❤️发布这个问题

            【讨论】:

            • 如果禁用 ICMP 请求,此方法将不起作用。 see!
            【解决方案12】:

            我想在无限循环中测试我的互联网连接,以监控我的网络何时启动和关闭。我注意到以下情况:当我的网络出现故障并且我像这样启动监视脚本并且网络恢复时,脚本没有注意到它。网络还活着,但脚本没有看到。当我的网络打开并且我像这样启动脚本时,它注意到了这些变化。所以我想出了以下两种情况都适用的解决方案:

            import shlex
            from subprocess import call, PIPE, STDOUT
            
            def get_return_code_of_simple_cmd(cmd, stderr=STDOUT):
                """Execute a simple external command and return its exit status."""
                args = shlex.split(cmd)
                return call(args, stdout=PIPE, stderr=stderr)
            
            def is_network_alive():
                cmd = "ping -c 1 www.google.com"
                return get_return_code_of_simple_cmd(cmd) == 0
            

            这里我们依赖一个独立于我们脚本的外部程序 (ping)。

            【讨论】:

              【解决方案13】:

              希望能帮到你。

              import urllib
              try :
                  url = "https://www.google.com"
                  urllib.urlopen(url)
                  status = "Connected"
              except :
                  status = "Not connect"
              print status
              

              【讨论】:

                【解决方案14】:

                我不需要在每次检查时都发布帖子...所以我会在设备从联机到脱机时发出通知,反之亦然。

                import socket
                import 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
                

                【讨论】:

                【解决方案15】:

                这是我的代码,它工作正常。

                 import requests
                 try:
                    requests.get('https://www.google.com/').status_code
                    print("Connected")
                 except:
                    print("Not Connected")
                    exit()
                

                【讨论】:

                  【解决方案16】:

                  使用谷歌检查连接,因为它是世界上最快的网站,并且也适用于慢速网络

                  import urllib.request
                      def connect():
                          host='http://google.com'
                          try:
                              urllib.request.urlopen(host) #Python 3.x
                              return True
                          except:
                              return False
                  

                  返回布尔值 True 表示连接可用 并返回 False 表示没有 Internet 连接

                  【讨论】:

                    【解决方案17】:

                    使用 Python 请求检查互联网

                    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")
                    

                    【讨论】:

                      【解决方案18】:

                      这是我用的:

                      import subprocess
                      
                      subprocess.call('ping -t 8.8.8.8')
                      

                      【讨论】:

                      • 另外,这仅测试 icmp - 用户防火墙可能允许 ping,但阻止 http 连接...
                      【解决方案19】:
                      import socket
                      IPaddress=socket.gethostbyname(socket.gethostname())
                      if IPaddress=="127.0.0.1":
                          print("No internet, your localhost is "+ IPaddress)
                      else:
                          print("Connected, with the IP address: "+ IPaddress )
                      

                      【讨论】:

                      • 这不是为了检查互联网是否连接。即使你在没有互联网的情况下连接到热点,IP地址也会分配给设备。IP地址用于查找路径,它用于路由器和设备之间的通信而不是用于互联网。
                      【解决方案20】:

                      将超时时间增加到 30 秒?多试几次?尝试几个主机?

                      【讨论】:

                      • 嗯,我有点希望有人可能有一个更好的替代代码或更好的错误证明。我只有少数人可以测试我的软件,所以如果问题没有出现在他们身上,我很可能不知道。我可以增加超时时间,但也有些人的连接很奇怪,可以发送请求,但收不到他们的回复,所以我想让超时时间仍然有点低...
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-11-06
                      • 1970-01-01
                      • 2018-12-27
                      相关资源
                      最近更新 更多