美文网首页python交流学习虫虫
想知道怎么用python自动根据网速自动切换网关吗 ? 这里告诉

想知道怎么用python自动根据网速自动切换网关吗 ? 这里告诉

作者: 78c40b03ee4e | 来源:发表于2019-02-14 22:06 被阅读49次

    前言

    公司里装了两条不同的宽带,根据使用的情况,比如拨VPN,或者使用人数过多,网速不行了就要切换下。每次手动去切换很不方便,而且网速也很难判断。这里分享下如何用Python检测网速,然后自动切换网关。

    使用speedtest-cli测试网速

    相信很多人都用过speedtest.net来测试网络速度,speedtest-cli是一个Python开源项目。通过链接speedtest.net来检测上传速度和下载速度。

    安装

    pip install speedtest-cli
    

    或者

    easy_install speedtest-cli
    

    测试网速

    安装之后就可以通过命令行来测试下网速:

    speedtest-cli --bytes
    

    根据log我们大概可以推测下这个程序的工作步骤:

    从speedtest.net读取配置文件。

    获得一个server列表。

    找到最近的server作为最优选择用来测试速度。

    这种最优方式适合检测网络的最大下载速度。而我现在需要的是根据网络访问速度切换网关,比如我需要经常访问国外某个网站,这个最大下载速度就没有意义了。要检测速度,我可以随意设置一些这个网站上的图片资源作为测试数据,而并不需要使用speedtest.net。

    自定义函数用于检测网速

    通过学习源码,我们可以自己重写一个网速测试函数。找到{Python Installation Directory}\Lib\site-packages\speedtest_cli.py根据speedtest()创建的函数很简单:

    def testSpeed(urls):
        speedtest_cli.shutdown_event = threading.Event()
        signal.signal(signal.SIGINT, speedtest_cli.ctrl_c)
     
        print "Start to test download speed: "
        dlspeed = speedtest_cli.downloadSpeed(urls)
        dlspeed = (dlspeed / 1000 / 1000)
        print('Download: %0.2f M%s/s' % (dlspeed, 'B'))
     
        return dlspeed
    

    原始代码是先找到最佳服务器,然后从上面获取URL资源。这里只需要随便设置我需要的资源:

    urls = ["http://www.dynamsoft.com/assets/images/logo-index-dwt.png", 
    "http://www.dynamsoft.com/assets/images/logo-index-dnt.png", 
    "http://www.dynamsoft.com/assets/images/logo-index-ips.png", 
    "http://www.codepool.biz/wp-content/uploads/2015/06/django_dwt.png", 
    "http://www.codepool.biz/wp-content/uploads/2015/07/drag_element.png"]
    

    看看源码中的下载速度是如何计算的?

    def downloadSpeed(files, quiet=False):
        """Function to launch FileGetter threads and calculate download speeds"""
     
        start = timeit.default_timer()
     
        def producer(q, files):
            for file in files:
                thread = FileGetter(file, start)
                thread.start()
                q.put(thread, True)
                if not quiet and not shutdown_event.isSet():
                    sys.stdout.write('.')
                    sys.stdout.flush()
     
        finished = []
     
        def consumer(q, total_files):
            while len(finished) < total_files:
                thread = q.get(True)
                while thread.isAlive():
                    thread.join(timeout=0.1)
                finished.append(sum(thread.result))
                del thread
     
        q = Queue(6)
        prod_thread = threading.Thread(target=producer, args=(q, files))
        cons_thread = threading.Thread(target=consumer, args=(q, len(files)))
        start = timeit.default_timer()
        prod_thread.start()
        cons_thread.start()
        while prod_thread.isAlive():
            prod_thread.join(timeout=0.1)
        while cons_thread.isAlive():
            cons_thread.join(timeout=0.1)
        return (sum(finished) / (timeit.default_timer() - start))
    
    • 在线程中读取读取图片资源。

    • 把线程放入阻塞的队列中。

    • 从队列中把线程的结果一个个读取出来。

    • speed = total file sizes / total time cost

    学习从来不是一个人的事情,要有个相互监督的伙伴,工作需要学习python或者有兴趣学习python的伙伴可以私信回复小编“学习”或者评论,留言,点赞 领取全套免费python学习资料、视频()装包

    查询网络适配器设置,并设置网关

    如何用Python设置网关?在StackOverflow上可以找到解答。推荐的方法是使用WMI (Windows Management Instrumentation)。

    安装

    WMI
    Python for Windows Extensions

    Win32网络适配器设置

    很多人的电脑上会看到很多的网络适配器,比如无线网卡的,虚拟网卡的,以太网卡的等等。每个适配器都有很多属性,看下微软的定义Win32_NetworkAdapterConfiguration class::

    [Provider("CIMWin32")]class Win32_NetworkAdapterConfiguration : CIM_Setting
    {
      boolean  ArpAlwaysSourceRoute;
      boolean  ArpUseEtherSNAP;
      string   Caption;
      string   DatabasePath;
      boolean  DeadGWDetectEnabled;
      string   DefaultIPGateway[];
      uint8    DefaultTOS;
      uint8    DefaultTTL;
      string   Description;
      boolean  DHCPEnabled;
      datetime DHCPLeaseExpires;
      datetime DHCPLeaseObtained;
      string   DHCPServer;
      string   DNSDomain;
      string   DNSDomainSuffixSearchOrder[];
      boolean  DNSEnabledForWINSResolution;
      string   DNSHostName;
      string   DNSServerSearchOrder[];
      boolean  DomainDNSRegistrationEnabled;
      uint32   ForwardBufferMemory;
      boolean  FullDNSRegistrationEnabled;
      uint16   GatewayCostMetric[];
      uint8    IGMPLevel;
      uint32   Index;
      uint32   InterfaceIndex;
      string   IPAddress[];
      uint32   IPConnectionMetric;
      boolean  IPEnabled;
      boolean  IPFilterSecurityEnabled;
      boolean  IPPortSecurityEnabled;
      string   IPSecPermitIPProtocols[];
      string   IPSecPermitTCPPorts[];
      string   IPSecPermitUDPPorts[];
      string   IPSubnet[];
      boolean  IPUseZeroBroadcast;
      string   IPXAddress;
      boolean  IPXEnabled;
      uint32   IPXFrameType[];
      uint32   IPXMediaType;
      string   IPXNetworkNumber[];
      string   IPXVirtualNetNumber;
      uint32   KeepAliveInterval;
      uint32   KeepAliveTime;
      string   MACAddress;
      uint32   MTU;
      uint32   NumForwardPackets;
      boolean  PMTUBHDetectEnabled;
      boolean  PMTUDiscoveryEnabled;
      string   ServiceName;
      string   SettingID;
      uint32   TcpipNetbiosOptions;
      uint32   TcpMaxConnectRetransmissions;
      uint32   TcpMaxDataRetransmissions;
      uint32   TcpNumConnections;
      boolean  TcpUseRFC1122UrgentPointer;
      uint16   TcpWindowSize;
      boolean  WINSEnableLMHostsLookup;
      string   WINSHostLookupFile;
      string   WINSPrimaryServer;
      string   WINSScopeID;
      string   WINSSecondaryServer;
    };
    

    找到了某个特定属性所对应的值,我们就可以很容易找到目标适配器了。我是这样查找的:

    • 右键目标网络适配器。

    • 选择配置。

    • 点击详细。

    • 看一下属性列表及对应的值。
      最后选择了设备描述Realtek PCIe GBE Family Controller。


    用Python查询Windows IP和网关

    wmiObj = wmi.WMI()
    sql = "select IPAddress,DefaultIPGateway from Win32_NetworkAdapterConfiguration where Description=\"Realtek PCIe GBE Family Controller\" and IPEnabled=TRUE"
    configurations = wmiObj.query(sql)
    

    设置Windows网关

    configurations = wmiObj.Win32_NetworkAdapterConfiguration(Description="Realtek PCIe GBE Family Controller", IPEnabled=True)
    configuration = configurations[0]
    ret = configuration.SetGateways(DefaultIPGateway=[gateway])
    

    请注意脚本必须用管理员权限来执行,不然设置会失败。记得查看返回值。

    for gateway in gateways:
            settingReturn = setGateway(wmiObj, gateway)
     
            if (settingReturn[0] != 0):
                print "Setting failed"
                return
     
            print "Set gateway: " + gateway
            dlspeed = testSpeed(urls)
            option = (gateway, dlspeed)
            print "Network option: " + str(option)
     
            if (option[1] > bestChoice[1]):
                bestChoice = option
    

    把Python脚本转换成可执行EXE

    如何把Python程序分发给别人使用如果他们并没有安装Python程序以及依赖库?使用Py2exe 可以很容易把Python脚本转换成exe文件。

    安装

    Py2exe

    转换Python脚本

    新建setup.py:

    from distutils.core import setup
    import py2exe
    setup(console=['network.py'])
    

    执行下面的命令:

    python setup.py py2exe
    

    目录中会生成一个dist 文件夹:


    记得执行程序的时候必须要用管理员权限

    相关文章

      网友评论

        本文标题:想知道怎么用python自动根据网速自动切换网关吗 ? 这里告诉

        本文链接:https://www.haomeiwen.com/subject/nonyeqtx.html