Python Forum
testing for a network connection - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: General (https://python-forum.io/forum-1.html)
+--- Forum: News and Discussions (https://python-forum.io/forum-31.html)
+--- Thread: testing for a network connection (/thread-27659.html)



testing for a network connection - Skaperen - Jun-16-2020

my function gets an open file with a write method. what's the simplest way to test if it is a network connection that is connected?


RE: testing for a network connection - Gribouillis - Jun-16-2020

I don't know if this is possible in general, but it looks like bad design. Friendly python functions that receive a file with a write() method will usually accept any file-like object and will never try to guess what's beyond the write method. I think if you need the information, give the responsibility to the caller and change the signature to
def flood_with_spam(file, is_network):
    pass



RE: testing for a network connection - DeaD_EyE - Jun-16-2020

Quote:what's the simplest way to test if it is a network connection that is connected?

I had done this kind of task.
Situation: There is a device, which connects to wifi, then it should check if the device can reach the default gateway (router IP) or if it's in "online-mode", it should check a known IP in internet.

This was my preparation to obtain local IPs and the gateway IP with two different solutions.
One solution is using iproute2 (ip command, which can return json) or netifaces which works also on Windows.

Code: https://pastebin.com/yqcAQGyh


Example code which works only on my machine ^^
import json
from socket import gethostbyname, gaierror
from subprocess import check_output, call, DEVNULL


OK = "✓"
FAIL = "✗"


def get_default_gateways():
    cmd = ["ip", "-j", "-4", "r", "s", "default"]
    result = json.loads(check_output(cmd, encoding="utf8"))
    return [res.get("gateway", "") for res in result]


def ping_ip(ip):
    return call(["ping", "-c1", "-W1", ip], stdout=DEVNULL, stderr=DEVNULL) == 0


def check_dns():
    try:
        gethostbyname("google.com")
    except OSError:
        return False
    else:
        return True


if __name__ == "__main__":
    result = False
    gateways = get_default_gateways()
    if gateways:
        result = ping_ip(gateways[0])
    if result:
        print(f"[{OK}] Gateway")
    else:
        print(f"[{FAIL}] Gateway")

    if ping_ip("1.1.1.1"):
        print(f"[{OK}] Internet")
    else:
        print(f"[{FAIL}] Internet")

    if check_dns():
        print(f"[{OK}] DNS")
    else:
        print(f"[{FAIL}] DNS")
Obviously I'm online:
Output:
[✓] Gateway [✓] Internet [✓] DNS



RE: testing for a network connection - Skaperen - Jun-16-2020

as for the design issues, i do try to make commands and APIs give more detailed and intelligent response codes and error messages than just letting things fail where they may. i do not agree with the idea of requiring the user to be sure things are correct (user in the case of an API being the programmer of the calling program).


RE: testing for a network connection - Gribouillis - Jun-16-2020

I understand that you want intelligent APIs but what I mean is that you are doing something unnatural when you're extracting information from a file object other than the information that can be obtained from the file object's documented attributes and methods. If the function wants to act differently depending on whether the file object is connected to the internet or not, it means that the file object is only an item of a more general context and the function should receive contextual elements in its arguments besides the pointer to file, or perhaps be a method of some class that provides these contextual elements. Alternately, the file object could be an instance of a specialized class containing thîs extra context.

May be it's just me.


RE: testing for a network connection - DeaD_EyE - Jun-17-2020

Don't try to solve it with checking everything before.
Work with timeouts. Set the timeout to your socket, then it will throw a socket.timeout exception if you try to read a file and the read took longer than the timeout.

import socket


def read(fd):
    try:
        fd.read(1)
    except socket.timeout:
        print("Read timed out")


s = socket.socket()
s.settimeout(10) # 10 seconds
s.connect(("google.com", 80))
f = s.makefile()

# will fail
read(f)
Regular files won't throw a socket.timeout.
I hope this is a better answer.

By the way, how do you check if a socket is still connected?
I think there is no safe method.