使用 NetworkManager 和 Python 断开 WiFi 接入点
Posted
技术标签:
【中文标题】使用 NetworkManager 和 Python 断开 WiFi 接入点【英文标题】:Disconnect a WiFi access point using NetworkManager and Python 【发布时间】:2012-02-14 20:20:04 【问题描述】:我正在构建一个 Python 应用程序,它必须在 linux 机器上连接和断开 Wifi。我正在使用 NetworkManager 层,通过在 cnetworkmanager(NetworkManager http://vidner.net/martin/software/cnetworkmanager/thanx to Martin Vidner 的 Python CLI)中找到的不错的 networkmanager 库,在一个守护进程(名为 stationd)中。 这个守护进程运行一个 gobject.MainLoop。一旦 timeout_add_seconds 唤醒(由用户在 GUI 中的操作触发),我必须断开当前正在运行的 Wifi 并连接到一个新的:
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
from networkmanager import NetworkManager
import networkmanager.applet.settings as settings
from networkmanager.applet import USER_SERVICE
from networkmanager.applet.service import NetworkManagerUserSettings, NetworkManagerSettings
import time
import memcache
import gobject
loop = gobject.MainLoop()
nm = NetworkManager()
dummy_handler = lambda *args: None
cache = memcache.Client(['127.0.0.1:11211',] )
def get_device(dev_spec, hint):
candidates = []
devs = NetworkManager().GetDevices()
for dev in devs:
if dev._settings_type() == hint:
candidates.append(dev)
if len(candidates) == 1:
return candidates[0]
for dev in devs:
if dev["Interface"] == dev_spec:
return dev
print "Device '%s' not found" % dev_spec
return None
def kill_allconnections():
connections=nm['ActiveConnections']
for c in connections:
print c.object_path
nm.DeactivateConnection(c.object_path)
class Wifi(object):
def connect(self, ssid, security="open", password=None):
"Connects to given Wifi network"
c=None # connection settings
us = NetworkManagerUserSettings([])
if security=="open":
c = settings.WiFi(ssid)
elif security=="wep":
c = settings.Wep(ssid, password)
elif security=="wpa":
c = settings.WpaPsk(ssid, password)
else:
raise AttributeError("invalid security model '%s'"%security)
svc = USER_SERVICE
svc_conn = us.addCon(c.conmap)
hint = svc_conn.settings["connection"]["type"]
dev = get_device("", hint)
appath = "/"
nm.ActivateConnection(svc, svc_conn, dev, appath, reply_handler=dummy_handler, error_handler=dummy_handler)
def change_network_settings():
key="station:network:change"
change=cache.get(key)
if change is not None:
print "DISCONNECT"
kill_allconnections()
print "CHANGE SETTINGS"
wifi=cache.get(key+':wifi')
if wifi is not None:
ssid=cache.get(key+':wifi:ssid')
security=cache.get(key+':wifi:security')
password=cache.get(key+':wifi:password')
print "SWITCHING TO %s"%ssid
Wifi().connect(ssid, security, password)
cache.delete(key)
return True
def mainloop():
gobject.timeout_add_seconds(1, change_network_settings)
try:
loop.run()
except KeyboardInterrupt:
loop.quit()
if __name__=="__main__":
mainloop()
这对于第一次连接运行完美(阅读:盒子未连接,守护程序运行并且盒子完美连接到 Wifi)。问题是当我尝试连接到另一个 Wifi 时:kill_allconnections() 静默运行,connect 方法在 nm.ActivateConnection 上引发异常:
Traceback (most recent call last):
File "stationd.py", line 40, in change_network_settings
Wifi().connect(ssid, security, password)
File "/home/biopredictive/station/lib/network.py", line 88, in connect
us = NetworkManagerUserSettings([])
File "/home/biopredictive/station/lib/networkmanager/applet/service/__init__.py", line 71, in __init__
super(NetworkManagerUserSettings, self).__init__(conmaps, USER_SERVICE)
File "/home/biopredictive/station/lib/networkmanager/applet/service/__init__.py", line 33, in __init__
dbus.service.Object.__init__(self, bus, opath, bus_name)
File "/usr/lib/pymodules/python2.6/dbus/service.py", line 480, in __init__
self.add_to_connection(conn, object_path)
File "/usr/lib/pymodules/python2.6/dbus/service.py", line 571, in add_to_connection
self._fallback)
KeyError: "Can't register the object-path handler for '/org/freedesktop/NetworkManagerSettings': there is already a handler"
看起来我以前的连接没有释放它的所有资源? 我对 gobject/dbus 编程非常陌生。你能帮忙吗?
【问题讨论】:
【参考方案1】:我在 D-Bus 邮件列表中有answered。在此引用存档:
class Wifi(...):
def connect(...):
...
us = NetworkManagerUserSettings([])
NetworkManagerUserSettings 是服务器,而不是客户端。 (这是一个设计 NM 的怪癖在 NM 0.9 中被消除) 您应该只为守护进程创建一个,而不是为每个连接创建一个 尝试。
【讨论】:
以上是关于使用 NetworkManager 和 Python 断开 WiFi 接入点的主要内容,如果未能解决你的问题,请参考以下文章
Linux NetworkManager 的使用方法(nmcli和nmtui)
Linux NetworkManager 的使用方法(nmcli和nmtui)