python编程案例_Python实用案例编程入门:第八章 如何自动连接WIFI

本章的主题为介绍如何自动连接WIFI。如果你们公司也是使用WIFI网络环境办公,那么也有可能遇到同样的问题。在介绍具体实现之前,会先介绍一些常用的基础库,比如sys,time等。

4ebc61c4a409fb059ce55ef8f3ad682b.png

8.1 要解决什么问题

如果公司的网络环境是WIFI,那么随着笔记本位置的移动,就需要接入就近的无线路由器。正常情况下使用是没问题的,但是有段时间网络有点问题,不能很快的正常接入网络。需要手动重新连接。即使电脑位置不变,也总是会断网,只有手动重新连接。所以,既然手动能解决的问题,那么我们为何不写个程序帮助我们默默的把这件事做了呢?

8.2 实现思路

现在我们需要思考一下如何去实现。一个最简单的思路就是让程序模拟我们自己的动作。

我们会去先ping一下百度,如果能ping通,那就表明网络是通的,否则就表明网络断了。一旦检测到网络断了,那么就需要去进行连接。一个最简单的方法就是利用dos命令种的netsh命令来管理网络。

如果觉得上面的办法太简易且不专业,那我们可以再用更专业的思路去实现我们的想法。那就是pywifi模块,不需要去通过ping百度来确定网络是否正常了。而且代码也会更灵活,可以配置WIFI名称密码等。

用上面思路实现的程序都需要我们手动去执行一次。我们还有办法,那就是将上面的程序实现为服务,这样就不用每次启动都执行一次了。

我们这里有点过设计的嫌疑,也有点类似茴香豆的茴字有多少中写法的味道。但从做技术的角度来讲,我们需要也应该知道不同方案的优缺点,以便于我们做出更适合我们需求的方案选择。

8.3 相关模块的安装及介绍

本节将会涉及time模块,sys模块,subprocess模块和pywifi模块。接下来会逐个进行详细介绍。

8.3.1 time模块

time模块提供了时间相关的各种函数。

time.asctime()函数可以将结构体struct_time所代表的时间转换为这样的字符串'Sun Jun 19 13:31:15 1994'。我们可以通过time.localtime()函数得到结构体struct_time。

time.sleep()函数的入参单位是秒,如果线程需要被挂起,可以通过调用此函数达到该目的。这里的入参也可以是小数,表示更精确的睡眠时间。我们将会使用该函数进行必要的等待以确保另一件事情结束。

time.strftime()函数也用于格式化时间。

>>> import time>>> time.strftime('%Y%m%d',time.localtime(time.time()))'20190714'>>>>>> time.strftime('%Y-%m-%d')'2019-07-14'>>>

8.3.2 sys模块

sys模块提供了对Python解释器使用的一些变量的访问,并可以进行一些修改,例如对环境变量PATH的读取和修改,并提供了某些和解释器进行交互的函数以使我们的程序能够和解释器进行交互。

例如,sys.argv会将命令行参数以list的形式传递给Python脚本,sys.argv[0]是脚本的名字,sys.argv[1]是第一个参数,以此类推。

sys.exit()表示退出程序,也可以带参数表示退出码,如果有其他程序调用该程序,即可以通过返回的数字来确定被调用程序的退出原因。

sys.implementation查看当前正在运行的Python解释器的版本信息。

>>> sys.implementationnamespace(cache_tag='cpython-36', hexversion=50726384, name='cpython', version=sys.version_info(major=3, minor=6, micro=5, releaselevel='final', serial=0))>>>

sys.stdin,sys.stddout,sys.stderr解释器用于标准输入,标准输出和错误。

8.3.3 subprocess模块

subprocess模块,我们可以利用该模块创建一个新的进程。如果需要的话,可以通过入口连接到程序的输入,输出和错误管道,并通过相应的管道获取程序的输入,输出和错误返回。

subprocess.run()函数可以运行由参数组成的命令的字符串,并且直到命令完成,在完成后返回一个完成实例。

>>> import subprocess>>> subprocess.run("ping -n 1 www.baidu.com", shell=True)正在 Ping www.a.shifen.com [180.97.33.108] 具有 32 字节的数据:来自 180.97.33.108 的回复: 字节=32 时间=33ms TTL=55180.97.33.108 的 Ping 统计信息:数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失),往返行程的估计时间(以毫秒为单位):最短 = 33ms,最长 = 33ms,平均 = 33msCompletedProcess(args='ping -n 1 www.baidu.com', returncode=0)>>>

subprocess.PIPE代表管道是一个特殊的值,使用该值可以将标准流的管道打开。打开后可以通过sys.stdin获取输入,通过sys.stdout读出输出结果,同时也可以通过sys.stderr得到错误输出。

subprocess.Popen()在新进程中执行子程序,在本书中我们将会多次使用该接口,某些场景下我们不需要等待被调用程序执行完成或返回,只需要将其启动即可。在预订测试线章节的例子中,我们将使用该接口去启动升级切换程序,启动后无需等待其返回。如果需要等待执行完成,则只需要调用wait()接口等待其完成即可。

import subprocess, osp = subprocess.Popen("dir", cwd=os.getcwd(), shell=True,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)p.wait()

如上面代码中使用的一样,wait()等待子程序结束。同时可以设置等待超时时间。

8.3.4 pywifi模块

pywifi模块提供了一个跨平台的wifi控制模块,是用Python实现的,可以利用该模块进行操控wifi,这也是本章的例子要进行介绍的主题。

在命令行中输入下面的命令进行安装:

C:甥敳獲ggangliu>pip install pywifiCollecting pywifiDownloading https://files.pythonhosted.org/packages/89/55/170a52685eeefeab36bfaf26bdca629263a0a28efffc3b556b2cc86ab966/pywifi-1.1.12-py3-none-any.whlInstalling collected packages: pywifiSuccessfully installed pywifi-1.1.12C:甥敳獲ggangliu>

通常只有一个wifi接口,所以可以用索引0来得到WIFI接口。这里可以看到本机的WIFI接口名为Intel(R) Dual Band Wireless-AC 8265。

>>> import pywifi>>> wifi = pywifi.PyWiFi()>>> iface = wifi.interfaces()[0]>>> iface>>> print(iface.name())Intel(R) Dual Band Wireless-AC 8265>>>

8.4 代码实现

到现在,我们万事俱备只欠编码。接下来就开始将我们的思想变为代码。

8.4.1 编写伪码

开始编码前,我们先写个基本的伪码,相当于概要设计。在小的程序中编写伪码的优势不是很明显,但希望初学者能够给从一开始就养成一个良好的习惯。这些良好的习惯不局限于写伪码,有很多好的编码规则,我们应该在学习之初就进行学习,并强迫自己遵守。慢慢的就变成自己编程能力的一部分,而这些好习惯也一定让您终身受益。

#首先,我们需要周期性的检测,所以必须起一个while循环#while True:#ping一下百度看看能否ping通#如果可以ping通,证明网络没问题,#否则认为网络断了#if 网络断了:#重连网络#sleep(5) 5秒后重新检测

8.4.2 Python代码

基于伪码的思想,我们编写的第一个简易版本的程序如下。如我们最初所想的,就是用ping百度的方法来确认网络是否正常。虽然简易,但功能没问题,能解决我们的问题,所以不管黑猫白猫能抓住老鼠的就是好猫。

# -*- coding: utf-8 -*-"""该程序用于重连wifi,避免人手动去重连我们利用dos命令netsh进行重连操作,假设我的网络名为GGangnetsh wlan connect name=GGang"""from time import sleepfrom subprocess import runwhile True:sleep(3)p = run("ping -n 1 www.baidu.com", shell=True)print(p)if 1 == p.returncode:run("netsh wlan connect name=GGang", shell=True)sleep(5)

现在,我们不满足于解决问题,我们想让代码更专业点,通过检测WIFI接口的状态来确认网络是否正常。

下面就是我们的优化,主要目的重新实现网络状态判断的部分。

# -*- coding: utf-8 -*-"""Created on Mon Nov 5 15:48:47 2018@author: ggang.liu"""import pywifi, time, sys#保存包中写义的常量from pywifi import constdef wifi_connect_status():"""判断本机是否有无线网卡,以及连接状态:return: 已连接或存在无线网卡返回1,否则返回0"""#创建一个院线对象wifi = pywifi.PyWiFi()#取当前机器,第一个无线网卡iface = wifi.interfaces()[0] #有可能有多个无线网卡,所以要指定#判断是否连接成功if iface.status() in [const.IFACE_CONNECTED,const.IFACE_INACTIVE]:print('wifi已连接')return 1else:print('wifi未连接')return 0def scan_wifi():"""扫苗附件wifi:return: 扫苗结果对象"""#扫苗附件wifiwifi = pywifi.PyWiFi()iface = wifi.interfaces()[0]iface.scan() #扫苗附件wifitime.sleep(1)basewifi = iface.scan_results()for i in basewifi:print('wifi扫苗结果:{}'.format(i.ssid)) # ssid 为wifi名称print('wifi设备MAC地址:{}'.format(i.bssid))return basewifidef connect_wifi(ssid, password):wifi = pywifi.PyWiFi() # 创建一个wifi对象ifaces = wifi.interfaces()[0] # 取第一个无限网卡print(ifaces.name()) # 输出无线网卡名称ifaces.disconnect() # 断开网卡连接time.sleep(3) # 缓冲3秒profile = pywifi.Profile() # 配置文件profile.ssid = ssid # wifi名称profile.auth = const.AUTH_ALG_OPEN # 需要密码profile.akm.append(const.AKM_TYPE_WPA2PSK) # 加密类型profile.cipher = const.CIPHER_TYPE_CCMP # 加密单元profile.key = password #wifi密码ifaces.remove_all_network_profiles() # 删除其他配置文件tmp_profile = ifaces.add_network_profile(profile) # 加载配置文件print("Connecting, wait a moment...")ifaces.connect(tmp_profile) # 连接time.sleep(5) # 尝试10秒能否成功连接isok = Trueif ifaces.status() == const.IFACE_CONNECTED:print("Connection successful")else:print("Connection failed")isok = Falsetime.sleep(1)return isokif __name__ == "__main__":password = ''if len(sys.argv) >= 2:password = sys.argv[1]else:print("Usage: connect-wifi-while-start.exe [password]")connect_wifi('GGang', password)

8.4.3 打包为exe文件进行发布

我们的程序编写好了,也运行良好,能解决我们的问题。现在如果想把它分享给我们亲爱的其他同事,我们该怎么做呢?最好是将它打包为EXE文件,否则使用的人也需要安装Python,且必须安装所有的依赖库,似乎太麻烦了。没等听您解释完就不想用了。

这里我们同时也提供了打包为EXE的代码。由于我们使用pyinstaller进行打包,所以需要提前安装。当然安装也很简单,使用pip命令就可以安装。

C:甥敳獲ggangliu>pip install pyinstallerCollecting pyinstallerUsing cached https://files.pythonhosted.org/packages/e2/c9/0b44b2ea87ba36395483a672fddd07e6a9cb2b8d3c4a28d7ae76c7e7e1e5/PyInstaller-3.5.tar.gzInstalling build dependencies ... doneGetting requirements to build wheel ... donePreparing wheel metadata ... doneRequirement already satisfied: setuptools in c:python36-32libsite-packages (from pyinstaller) (40.6.2)Collecting altgraph (from pyinstaller)Downloading https://files.pythonhosted.org/packages/0a/cc/646187eac4b797069e2e6b736f14cdef85dbe405c9bfc7803ef36e4f62ef/altgraph-0.16.1-py2.py3-none-any.whlCollecting pefile>=2017.8.1 (from pyinstaller)Downloading https://files.pythonhosted.org/packages/36/58/acf7f35859d541985f0a6ea3c34baaefbfaee23642cf11e85fe36453ae77/pefile-2019.4.18.tar.gz (62kB)|████████████████████████████████| 71kB 24kB/sCollecting pywin32-ctypes>=0.2.0 (from pyinstaller)Downloading https://files.pythonhosted.org/packages/9e/4b/3ab2720f1fa4b4bc924ef1932b842edf10007e4547ea8157b0b9fc78599a/pywin32_ctypes-0.2.0-py2.py3-none-any.whlRequirement already satisfied: future in c:python36-32libsite-packages (from pefile>=2017.8.1->pyinstaller) (0.17.1)Building wheels for collected packages: pyinstallerBuilding wheel for pyinstaller (PEP 517) ... doneCreated wheel for pyinstaller: filename=PyInstaller-3.5-cp36-none-any.whl size=2877932 sha256=0a9c02249d51dc0dab0929d145bba34b557890514e969488d96df61440888f50Stored in directory: C:甥敳獲ggangliuAppDataLocalpipCachewheelsc6a4e0d9a1c5d3d876eb0675171281c293aed80839115e2eb022e6d2Successfully built pyinstallerInstalling collected packages: altgraph, pefile, pywin32-ctypes, pyinstallerRunning setup.py install for pefile ... doneSuccessfully installed altgraph-0.16.1 pefile-2019.4.18 pyinstaller-3.5 pywin32-ctypes-0.2.0C:甥敳獲ggangliu>安装成功后我们就可以通过下面的代码进行打包了。import os, shutil#删除上次打包生成的临时目录if os.path.exists('dist'):shutil.rmtree("dist")if os.path.exists('build'):shutil.rmtree("build")if os.path.exists('__pycache__'):shutil.rmtree("__pycache__")os.system("pyinstaller -F -c -i images/wifi.ico connect-wifi-while-start.py")shutil.copyfile("dist/connect-wifi-while-start.exe", "./connect-wifi-while-start.exe")shutil.rmtree("dist")shutil.rmtree("build")shutil.rmtree("__pycache__")

注意,images/wifi.ico这个图标文件如果不存在,可以将打包命令中的这个参数删除。

这里顺便提一下,有一些网站是可以将图片转换为ico图标文件,所以有需要的话,可以进行百度或谷歌就找到这样的网站进行转换。

8.5 本章小结

本章我们学习如何自动连接WIFI,在这个过程中我们认识了几个基本的库sys,time,subprocess和pywifi。通过一些基本的学习代码以及实战案例中的使用,您应该能有一个基本的了解。在后面的章节中我们将会不断使用到这些基础库,随着不断的重复学习,我相信逐渐的都能够熟练的掌握其用法。

编程就是这样一个过程,每过一段时间我们再回头看我们写过的代码就会看出一些问题,或者一些让你自己觉得不满意的地方。这证明我们在不断的进步。所以坚持学习,定会有所收获。


欢迎关注,转发,收藏,感谢支持

Python实用案例编程入门:第一章 Python概述及为什么学Python

Python实用案例编程入门:第二章 字符串

Python实用案例编程入门:第三章 列表和元组

Python实用案例编程入门:第四章 字典和文件

Python实用案例编程入门:第五章 函数和类

Python实用案例编程入门:第六章 控制流语句

Python实用案例编程入门:第七章 调式手段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值