如何使用Python 3在Windows上连接到WiFi网络? [英] How to connect to WiFi network on Windows using Python 3?
问题描述
我正在尝试用Python 3编写脚本,但是今天可用的所有模块都可以在python 2上运行,这将使我能够搜索无线网络并连接到它们.是否有任何Python 3库?
I am trying to write a script in Python 3 but all modules available today work on python 2 which will enable me to search for wireless networks and to connect to them. Is there any Python 3 library for this?
我为python 2尝试过的代码
The code I tried for python 2
from wireless import Wireless
wireless = Wireless()
wireless.connect(ssid='ssid', password='password')
这给我一个错误
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\Himanshu Poddar\AppData\Local\Programs\Python\Python36-32\lib\site-packages\wireless\Wireless.py", line 23, in __init__
self._driver_name = self._detectDriver()
File "C:\Users\Himanshu Poddar\AppData\Local\Programs\Python\Python36-32\lib\site-packages\wireless\Wireless.py", line 50, in _detectDriver
compare = self.vercmp(ver, "0.9.9.0")
File "C:\Users\Himanshu Poddar\AppData\Local\Programs\Python\Python36-32\lib\site-packages\wireless\Wireless.py", line 71, in vercmp
return cmp(normalize(actual), normalize(test))
NameError: name 'cmp' is not defined
但是这不起作用,因为它基于python2.有没有办法使用Python 3连接到wifi?
But this is not working since it is based on python 2. Is there any way to connect to a wifi using Python 3
推荐答案
注释(大约 [PyPI]:无线0.3.2 ]):
- 不(尚未)支持 Python 3 :因为它在代码中的某处使用了 cmp 函数(仅在 Python 2 中可用)
- 我想提交一个拉取请求(因为修复很简单),但是显然在 GitHub 上它已经修复,但是 PyPI 存储库未更新(因为2016)
- Does not (yet) support Python 3: as somewhere in the code it uses the cmp function (which is only available in Python 2)
- I wanted to submit a pull request (as the fix is trivial), but apparently on GitHub it was already fixed, yet the PyPI repository was not updated (since 2016)
因此,我建议寻找替代方案:
As a consequence, I'd suggest looking for alternatives:
- 几天前我遇到的一个是 Win32Wifi :( [SO]:无法获取使用Python中所有WlanGetAvailableNetworkList的所有可用网络(@CristiFati的答案)以获取更多详细信息(还可以检查
- One that I've encountered a couple of days ago is Win32Wifi: ([PyPI]: win32wifi 0.1.0, although this wasn't updated since 2017 either). Check [SO]: Unable to get all available networks using WlanGetAvailableNetworkList in Python (@CristiFati's answer) for more details (might also check [SO]: Force wifi scan using WlanScan in Python (@CristiFati's answer))
好的,经过大量浏览:
- Win32Wifi 源代码
- Google :
- Win32Wifi source code
- Google:
- [MS.Docs]: wlanapi.h header
- [CodePlex.Archive]: managedwifi
- [MS.Docs]: Netsh Commands for Wireless Local Area Network (WLAN) in Windows Server 2008
- Many others
,我能够提出一些建议.
, I was able to come up with something.
code00.py :
#!/usr/bin/env python3 import sys import time import ctypes import comtypes import traceback from win32wifi import Win32Wifi as ww ERROR_SUCCESS = 0 WLAN_CONNECTION_HIDDEN_NETWORK = 0x00000001 class WLANException(Exception): pass class ConnectCallbackContext(ctypes.Structure): _fields_ = [ ("guid", ctypes.c_wchar_p), ("start", ctypes.c_byte), ("end", ctypes.c_byte), ("fail", ctypes.c_byte), ] def _wlan_connect_callback(data, context_addr): if context_addr: context = ConnectCallbackContext.from_address(context_addr) if str(data.interfaceGuid) == context.guid and data.notificationSource == ww.WLAN_NOTIFICATION_SOURCE_DICT[ww.WLAN_NOTIFICATION_SOURCE_ACM]: if data.notificationCode == ww.WLAN_NOTIFICATION_ACM_ENUM.wlan_notification_acm_connection_start.name: context.start += 1 elif context.start: if data.notificationCode == ww.WLAN_NOTIFICATION_ACM_ENUM.wlan_notification_acm_connection_complete.name: context.end += 1 elif data.notificationCode == ww.WLAN_NOTIFICATION_ACM_ENUM.wlan_notification_acm_connection_attempt_fail.name: context.fail += 1 def wireless_connect( ssid, password, timeout=15, # secs authentication="WPA2PSK", # "open", encryption="AES", # "WEP", key_type="passPhrase", # "networkKey", interface_index=0, # Don't modify this (until PCs with more than 1 WLAN adapter arise :) ) ): interfaces = ww.getWirelessInterfaces() if interface_index < 0 or len(interfaces) < interface_index: raise WLANException(-1, "No WLAN interface for given index") interface = interfaces[interface_index] profile_name = ssid + "_profile_tmp" ssid_hex = "".join((hex(ord(c))[2:] for c in ssid)).upper() profile_string = f"""<?xml version=\"1.0\"?> <WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\"> <name>{profile_name}</name> <SSIDConfig> <SSID> <hex>{ssid_hex}</hex> <name>{ssid}</name> </SSID> </SSIDConfig> <connectionType>ESS</connectionType> <connectionMode>manual</connectionMode> <MSM> <security> <authEncryption> <authentication>{authentication}</authentication> <encryption>{encryption}</encryption> <useOneX>false</useOneX> </authEncryption> <sharedKey> <keyType>{key_type}</keyType> <protected>false</protected> <keyMaterial>{password}</keyMaterial> </sharedKey> </security> </MSM> </WLANProfile> """ connection_params = { "connectionMode": "wlan_connection_mode_temporary_profile", "profile": profile_string, "ssid": None, "bssidList": None, "bssType": "dot11_BSS_type_infrastructure", "flags": WLAN_CONNECTION_HIDDEN_NETWORK, } ctx = ConnectCallbackContext(interface.guid_string, 0, 0, 0) notification_obj = ww.registerNotification(_wlan_connect_callback, context=ctypes.pointer(ctx)) try: res = ww.connect(interface, connection_params) except Exception as e: ww.unregisterNotification(notification_obj) raise WLANException("WlanConnect failed") from e end_time = time.time() + timeout; while time.time() < end_time: time.sleep(0.5) if ctx.end: break ww.unregisterNotification(notification_obj) if ctx.end: if ctx.fail: raise WLANException(-2, "Connection failed") else: raise WLANException(-3, "Connection timed out") return interface.guid_string def wireless_disconnect(interface_guid): # Borrowed (and improved) this func from win32wifi.Win32Wifi, to avoid creting the interface when only its guid is required handle = ww.WlanOpenHandle() try: ww.WlanDisconnect(handle, comtypes.GUID(interface_guid)) except Exception as e: raise WLANException("WlanDisconnect failed") from e finally: ww.WlanCloseHandle(handle) def main(argv): if argv: try: guid = argv[0] print("Disconnecting wireless interface {:s} ...".format(guid)) wireless_disconnect(guid) except: traceback.print_exc() else: try: print("Connecting to wireless network ...") ssid = "Network SSID" # ssid and pwd here are (deliberately) dummy pwd = "Network password" guid = wireless_connect(ssid, pwd) print("Connected interface {:s}".format(guid)) except: traceback.print_exc() if __name__ == "__main__": print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) main(sys.argv[1:]) print("\nDone.")
script.bat :
setlocal enableextensions enabledelayedexpansion set _EXE_PTYHON="e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" time <nul ping www.google.com %_EXE_PTYHON% code00.py ping www.google.com %_EXE_PTYHON% code00.py {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806} ping www.google.com time <nul
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056721759]> sopr.bat *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages *** [prompt]> script.bat [prompt]> time 0<nul The current time is: 1:45:08.31 Enter the new time: [prompt]> ping www.google.com Ping request could not find host www.google.com. Please check the name and try again. [prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Connecting to wireless network ... Connected interface {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806} Done. [prompt]> ping www.google.com Pinging www.google.com [2a00:1450:400d:809::2004] with 32 bytes of data: Reply from 2a00:1450:400d:809::2004: time=11ms Reply from 2a00:1450:400d:809::2004: time=12ms Reply from 2a00:1450:400d:809::2004: time=12ms Reply from 2a00:1450:400d:809::2004: time=19ms Ping statistics for 2a00:1450:400d:809::2004: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 11ms, Maximum = 19ms, Average = 13ms [prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806} Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Disconnecting wireless interface {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806} ... Done. [prompt]> ping www.google.com Ping request could not find host www.google.com. Please check the name and try again. [prompt]> time 0<nul The current time is: 1:45:12.82 Enter the new time:
注释:
- 为了创建 POC ,我必须添加一些与问题不一定相关的代码(例如 wireless_disconnect ),这会增加复杂性.
BTW ,代码比我最初预期的要复杂得多(这就是为什么我不费心去解释它-因为这太过分了),但是我看不到任何方式修剪 - script.bat (和
time <nul
)只是为了在控制台中证明代码正在与无线网络连接/断开连接(并且我不是从 Win 并行)- 我不知道
time 0<nul
(在输出中)的" 0 "部分来自哪里
- In order to create a POC I had to add some code (e.g. wireless_disconnect) not necessarily related to the question, which adds complexity.
BTW, the code is waaay more complex than I initially anticipated (that's why I didn't bother to explain it - as it would be an overkill), but I don't see any way of trimming it down - script.bat (and
time <nul
) are just to prove in console that the code is connecting / disconnecting from the wireless network (and that I'm not connecting from Win in parallel)- I don't know where the " 0" part from
time 0<nul
(in the output) comes from
最重要的一个:上面的代码无法使用 OOTB ,因为 Win32Wifi 有错误 >.我发现了2个在这种情况下致命(严重)的错误,以及许多其他较小的错误.
我刚刚提交了 [GitHub]:kedos/win32wifi-修复(某些问题)关键)和改进 .不知道它的结果是什么(考虑不活动时间).THE MOST IMPORTANT ONE: The above code will not work OOTB, because Win32Wifi is buggy. I found 2 bugs that are fatal (critical) for this scenario, and a bunch of other smaller ones.
I've just submitted [GitHub]: kedos/win32wifi - Fixes (some critical) and improvements. Not sure what its outcome it's going to be (considering the inactivity period).作为替代,您可以下载补丁,然后在本地应用更改.检查 [ [SO]:从鼠标右键单击PyCharm Community Edition中的上下文菜单运行/调试Django应用程序的UnitTests? (@CristiFati的答案)(修补 utrunner 部分),了解如何在 Win 上应用补丁(基本上,每行以一个"+" 符号进入,以一个-" 符号开头的每一行都熄灭).我正在使用 Cygwin , btw .
As an alternative, you could download the patch, and apply the changes locally. Check [SO]: Run/Debug a Django application's UnitTests from the mouse right click context menu in PyCharm Community Edition? (@CristiFati's answer) (Patching utrunner section) for how to apply patches on Win (basically, every line that starts with one "+" sign goes in, and every line that starts with one "-" sign goes out). I am using Cygwin, btw.
这篇关于如何使用Python 3在Windows上连接到WiFi网络?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- I don't know where the " 0" part from
- 我不知道