The Stupid Engineer
The Stupid Engineer

Reputation: 402

How do I use "not in" correctly to identify an item is not in a list of strings in Python?

I have a list of tuples comprised of an interface name and access list name. Like this: exempt_int_acl_tuple=[('(app)', 'access-list nonat'), ('(app2)', 'access-list nonat')]

Sample config to search through is something like this:

config=['access-list nonat extended permit ip 10.0.0.0 255.0.0.0 10.0.0.0 255.0.0.0','access-list nonat extended permit ip 10.0.0.0 255.0.0.0 192.168.15.0 255.255.255.0','access-list nonat extended permit ip 10.0.0.0 255.0.0.0 1.1.1.1 255.255.255.240','blah','blah blah','some more blah']

I have a list strings in which I look for a specific pattern. If the list matches the pattern, I add it to a new list called exempt_acl.

So my code looks like this:

exempt_acl=[]
for interface,acl_name in exempt_int_acl_tuple:
      for someline in config:
        acl_statement=acl_name+' extended permit ip '
        if (acl_statement in someline) and (someline not in exempt_acl):
          exempt_acl.append(someline)

In this case, the access list name in the tuple is repeated so the config file is searched for twice. So exempt_acl looks like this:

['access-list nonat extended permit ip 10.0.0.0 255.0.0.0 10.0.0.0 255.0.0.0 ', 'access-list nonat extended permit ip 10.0.0.0 255.0.0.0 192.168.15.0 255.255.255.0 ', 'access-list nonat extended permit ip 10.0.0.0 255.0.0.0 1.1.1.1 255.255.255.240 ']
['access-list nonat extended permit ip 10.0.0.0 255.0.0.0 10.0.0.0 255.0.0.0 ', 'access-list nonat extended permit ip 10.0.0.0 255.0.0.0 192.168.15.0 255.255.255.0 ', 'access-list nonat extended permit ip 10.0.0.0 255.0.0.0 1.1.1.1 255.255.255.240 ']

However, the same lines are added twice, and it is creating a list of lists, instead of a list of strings. I thought the boolean evaluation for (someline not in exempt_acl) would prevent the line being added a second time, but it is. What am I doing wrong? I am using file.read().splitlines() to read the config file in case that makes a difference.

Upvotes: 0

Views: 99

Answers (3)

The Stupid Engineer
The Stupid Engineer

Reputation: 402

I found the answer to why the configuration was being printed twice.

Main was calling the function twice. Once incorrectly (not mapping the function output to a value, but performing the printing involved in the debugging), and once correctly, hence not affecting output.

Thanks to all who assisted. I'm very grateful for your help, and I learned a few things too! The most important lesson for me was to formulate an MCVE before posting in the future.

Upvotes: 0

Wayne Werner
Wayne Werner

Reputation: 51877

Assuming you have a file named config.txt with these contents:

access-list nonat extended permit ip 10.0.0.0 255.0.0.0 10.0.0.0 255.0.0.0
access-list nonat extended permit ip 10.0.0.0 255.0.0.0 192.168.15.0 255.255.255.0
access-list nonat extended permit ip 10.0.0.0 255.0.0.0 1.1.1.1 255.255.255.240

And test.py containing this:

exempt_acl = [('(app)', 'access-list nonat'),
              ('(app2)', 'access-list nonat'),
             ]

results = []
with open('config.txt') as config:
    for line in config:
        line = line.strip()
        for _,acl_name in exempt_acl:
            acl_statement = acl_name + ' extended permit ip '
            if line.startswith(acl_statement) and line not in results:
                results.append(line)

for result in results:
    print(result)

That should do what you're looking for, if I understand your question correctly.


I'm not sure exactly what you were doing in your original code base - the code in your question was definitely not an MCVE. This code also works as expected:

config = [line.strip() for line in open('config.txt')]

results = []
for _, acl_name in exempt_acl:
    for line in config:
        acl_statement = acl_name + ' extended permit ip '
        if acl_statement in line and line not in results:
            results.append(line)

for result in results:
    print(result)

Upvotes: 1

jez
jez

Reputation: 15359

To start with, delistify someline by saying someline = someline[0].

If lines still appear to be appended twice, it probably comes down to the ambiguity of the condition if (acl_statement in someline) . If two lines are slightly different (e.g. different amounts of whitespace) but nonetheless contain the same acl_statement, both will be appended.

Upvotes: 1

Related Questions