Determine if a computer is connected to internet via WiFi network or ethernet cable in Python

Question:

I would like to know how to have a Python script determine how a computer is connected to a network. The reason for this is because the script becomes buggy if the connection speed is too slow, so I would like to show a warning if the user is connected via WiFi.

The actual Python executable being run is located on my company’s LAN, so this is why the connection speed matters. Additionally, since this executable cannot be run without a connection, I am not concerned with checking that the user is online.

I know nothing about how Python interacts with things like this (or even if its possible), so please let me know if there’s anything I can clarify. Thanks in advance

I am using Python 2.7.6 32-bit on Windows 7 64-bit (different bits because pyEnchant)

Asked By: wnnmaw

||

Answers:

On Windows, this information is made available via WMI’s Network Adapter Classes.

In .NET (e.g., with IronPython), this is easy to use:

ni = Windows.Networking.Connectivity.NetworkInformation
profile = ni.GetInternetConnectionProfile()
if profile:
    interface = profile.NetworkAdapter.IanaInterfaceType
    if interface == 71:
        do WiFi stuff
    elif interface == 6:
        do Ethernet stuff
    else:
        do wtf stuff

The IanaInterfaceType is a number from this IANA list. (I you want to parse SNMP MIBs, you can download it that way.) Note that Windows may lump some less common/obsolete adapter types in with Ethernet, but you probably don’t care about that.


For older versions of Windows—I’m not sure whether Windows 7 counts as “older” or not—you want Win32_NetworkAdapter and friends, not MSFT_NetworkAdapter/NetworkAdapter as linked above, so the code will be different.

In particular, getting the adapter that’s supplying the default internet connection is harder, but more flexible, while getting its type is easier, but less informative. IIRC, at least in XP, even though Windows had some notion of “the internet connection”, you couldn’t access it through WMI—but you could access all internet connections, or search/iterate for the one you care about. Which is actually better if you’ve got a VPN, or are sitting on a DMZ, or have multiple NIC cards active at once, etc.

So, what you do is to search or iterate Win32_IP4RouteTable to find which connection route handles the IP address you actually want to connect to, or use Win32_NetworkAdapaterConfiguration to find which NIC handles the address you want to connect from. Either way, you will get an InterfaceIndex, and you can look up the Win32_NetworkAdapter with that InterfaceIndex. Then its AdapterType is a nice string that you can just check != "Wireless". (I believe I figured all of this out from a VBscript example at TechNet Script Center and then ported it to IronPython myself, but it was a long time ago, so I may be remembering wrong. Anyway, the docs seem more complete than they did back then, so that shouldn’t be necessary.)


Without .NET (e.g., with standard CPython), you have to use either the web services interface, or talk to the native Win32 COM interface.

In theory, you could talk to the COM interface directly via ctypes, but that’s a horrible idea; you almost certainly want pywin32 for that.

And, even better, I would suggest looking around on PyPI for wrappers, like this one, rather than building it yourself. Then, the code should be nearly as simple as with .NET.


Here’s some pseudcode using the WMI library linked above and the XP-compatible source-address method described above:

import wmi
MY_IP = '10.1.2.3'
w = wmi.WMI()
for nac in w.Win32_NetworkAdapterConfiguration():
    if MY_IP in nac.IPAddress:
        idx = nac.InterfaceIndex
        break
else:
    oops, do something, no NIC has that address
na = w.Win32_NetworkAdapter(InterfaceIndex=idx)
if not na:
    oops, unlikely race condition, NIC disabled right before we checked it
if na[0].AdapterType == 'Wireless':
    do WiFi stuff
elif na[0].AdapterType.startswith('Ethernet'):
    do Ethernet stuff
else:
    who's using LocalTalk in 2013?

It should be possible to search the NetworkAddressConfiguration, but I have no idea how to search for “IPAddress contains MY_IP” in the wmi library. Using = might work there, who knows; read through the tutorial to find out.

Searching by target address, on the other hand, should be like this:

TARGET_IP = '10.10.10.10'
w = wmi.WMI()
rt = w.Win32_IP4RouteTable(Destination=TARGET_IP)
if not rt:
    oops, no route to host
idx = rt[0].InterfaceIndex
# same as above
Answered By: abarnert

Using WMI you can determine the connection without needing the local machine IP.

Use NetConnectionID instead of AdapterType for comparing seems to work.

Works on Windows 10.

import wmi
w = wmi.WMI()
for nac in w.Win32_NetworkAdapterConfiguration():
    if nac.IPEnabled:
        idx = nac.InterfaceIndex
        break
else:
    print("oops, do something, no NIC has that address")
na = w.Win32_NetworkAdapter(InterfaceIndex=idx)
if not na:
    print("oops, unlikely race condition, NIC disabled right before we checked it")
if 'Wi' in na[0].NetConnectionID:
    print("do WiFi stuff")
elif 'Ethernet' in na[0].NetConnectionID:
    print("do Ethernet stuff")
else:
    print("who's using LocalTalk in 2013?")
Answered By: Titan Node
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.