Python Forum

Full Version: Read list of IP addresses from file and return a network
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have been trying for hours using Google and stack overflow to read a list of IP addresses and return networks. The ip address command works in the Python shell but seems to be tripping over the imported list. I have tried stripping the new line and reading the file in multiple different ways but I keep getting an error returned. I am sure it is something with how I am reading the file in but I just can't figure it out.

Here is the current code. Let's call it revision number 4186!

import ipaddress
def process(line):
    # Output network with mask bits (192.168.0.0/24)
    try:
        return ipaddress.IPv4Interface(line).network
    except Exception:
        return print("FAIL_OR_EMPTY")
with open('ipaddrlong.txt', 'r') as f:
    for line in f:
        process(line)
and the input file called looks like this. There is only the data and a newline (/n).

192.168.252.146/24
192.168.252.158/24
192.168.252.203/24
192.168.252.209/24
If I change the return line to a simple print, it looks fine to me. There are no extra spaces or characters.

'192.168.252.146/24', '192.168.252.158/24', '192.168.252.203/24', '192.168.252.209/24'
And when I try the command from the shell, it seems to work fine:

>>> x="192.168.0.1/24"
>>> ipaddress.IPv4Interface(x).network
IPv4Network('192.168.0.0/24')
But when I run the script the exception "FAIL_OR_EMPTY" is returned. I tried strip() but since there are no extra spaces, that did not help.
remove the try/except and see what the exception is. Generally it is considered bad practice to have catch-all try/except like you do.
In this case the problem is that you don't strip the new line at the end of the line
>>> x="192.168.0.1/24\n"
>>> ipaddress.IPv4Interface(x).network
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/ipaddress.py", line 1386, in __init__
    self.network = IPv4Network(address, strict=False)
  File "/usr/lib/python3.5/ipaddress.py", line 1531, in __init__
    self.netmask, self._prefixlen = self._make_netmask(arg)
  File "/usr/lib/python3.5/ipaddress.py", line 1094, in _make_netmask
    prefixlen = cls._prefix_from_ip_string(arg)
  File "/usr/lib/python3.5/ipaddress.py", line 518, in _prefix_from_ip_string
    cls._report_invalid_netmask(ip_str)
  File "/usr/lib/python3.5/ipaddress.py", line 474, in _report_invalid_netmask
    raise NetmaskValueError(msg) from None
ipaddress.NetmaskValueError: '24\n' is not a valid netmask
change last line to
process(line.strip())
I had tried this line a few times before and it never worked but I know why now.

process(line.strip())

The first line of my input file was a header row that the program was tripping over. Not sure why the try/except did not just throw an error on line 1 and continue which is odd. I would get pages of FAIL_OR_EMPTY (input file is 4000+ lines).

Thanks for your help!

Follow-up question, what should I read up on regarding the handling of errors so that user error on a single entry won't throw off the program entirely? I suppose I would have to add validation code to the input or is there anything more elegant that can be done?
You can skipe the first line. The fileobject is also an iterator. When it's called file for example, you skip it before you enter the for loop with the next function.

with open(your_file) as file:
    header = next(file)
    for line in file:
        process(line.strip())
You can also use csv module and both csv.reader and csv.DictReader will handle the header properly