Как исправить ошибку TypeError: expected string or bytes-like object?

Я написал регулярное выражение для проверки FQDN адресов, однако, оно не работает. Точно такое же регулярное выражение для ip-адресов выше проблем не создает. Я пытался приводить value словаря к строке в условии if/else, но это не помогло.

Полный текст ошибки:

Traceback (most recent call last):
  File "c:\Users\kvvol\Desktop\Pytest\Script.py", line 72, in <module>
    mistakes()
  File "c:\Users\kvvol\Desktop\Pytest\Script.py", line 31, in mistakes
    if(fqdnadd_pat.match(firewall['Исходящий FQDN']) and firewall['Исходящий FQDN'] != None):
TypeError: expected string or bytes-like object

Сам код:

import openpyxl
import re

wb = openpyxl.reader.excel.load_workbook(filename="Zayavka.xlsx")

wb.active = 0
ws = wb.active
firewall = {} #один блок с одним средством защиты

ipadd_pat = re.compile("^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([1-9]|[1-2][0-9]|3[0-2]))?\s?(\([Nn][Aa][Tt]\s(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\))?;\s?){1,}$")
fqdnadd_pat = re.compile("^(([a-zA-Z0-9]+\.?)+\s?\(((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]);\s?){1,}\);\s?){1,}$")

def mistakes():
    if (firewall['Сегмент источника'] == firewall['Сегмент назначения']):
        print('Сегмент источника и сегмент назначения совпадать не должны')
    else:
        if(firewall['Адрес/сеть назначения'] == None):
            print('Заполните поле "Адрес/сеть назначения"')

        if(firewall['Исходящий адрес'] != None):
                print('Поле "Исходящий адрес" оставьте пустым')
        elif(firewall['Исходящий IP-адрес/сеть'] == None and firewall['Исходящий адрес'] != None):
                print('Содержимое поля "Исходящий адрес" перенесите в поле "Исходящий IP-адрес/сеть"')

        if(ipadd_pat.match(firewall['Исходящий IP-адрес/сеть']) and firewall['Исходящий IP-адрес/сеть'] != None):
            print("Ip-адреса заполнены корректно")
        else:
            print("Ip-адреса заполнены некорректно")
            
        if(fqdnadd_pat.match(firewall['Исходящий FQDN']) and firewall['Исходящий FQDN'] != None): # на этой строке ошибка
            print('FQDN заполнены корректно')
        else:
            print('FQDN заполнены некорректно')

        if(firewall['Протокол доступа'] != None):
                print('Поле "Протокол доступа" оставьте пустым')
            
        if(firewall['Порт доступа'] != None):
                print('Поле "Порт доступа" оставьте пустым')

def fire_fill():

    firewall['Название средства защиты'] = ws['B' +str(i+1)].value
    firewall['Сегмент источника'] = ws['B' +str(i+2)].value
    firewall['Сегмент назначения'] = ws['B' +str(i+3)].value
    firewall['Протокол доступа'] = ws['B' +str(i+4)].value
    firewall['Исходящий адрес'] = ws['B' +str(i+5)].value
    firewall['Порт доступа'] = ws['B' +str(i+6)].value
    firewall['Исходящая учётная запись/AD'] = ws['B' +str(i+7)].value
    firewall['Исходящий IP-адрес/сеть'] = ws['B' +str(i+8)].value
    firewall['Исходящий FQDN'] = ws['B' +str(i+9)].value
    firewall['Адрес/сеть назначения'] = ws['B' +str(i+10)].value
    firewall['Адрес назначения FQDN'] = ws['B' +str(i+11)].value
    firewall['Номер порта TCP'] = ws['B' +str(i+12)].value
    firewall['Номер порта UDP'] = ws['B' +str(i+13)].value

for i in range(1, ws.max_row):
    
    checker = i
    
    if(ws['A' +str(i)].value == '№ Заявки'):    
        firewall['№ Заявки'] = ws['B' +str(i)].value
        print()
        print('Заявка ' + str(firewall['№ Заявки']))
        block_counter = 1

    while ws['A' +str(checker+1)].value == 'Название средства защиты':
        fire_fill()
        print()
        print('Блок ' + str(block_counter))
        mistakes()
        checker += 12
        block_counter += 1

Ответы (1 шт):

Автор решения: MaxU

Конструкция condition1 and condition2 and condition3 выполняется в Python слева направо и если находится хотя бы одно условие для которого выполняется bool(conditionX) == False - проверка обрывается на этом месте и возвращается False. Все последующие условия не проверяются.

В вашем случае первым выполняется проверка fqdnadd_pat.match(firewall['Исходящий FQDN']), которая вызывает указанную в вопросе ошибку.

Поэтому вам надо изменить порядок проверки и кроме того лучше использовать идиоматический вид проверки на None:

if firewall.get('Исходящий FQDN') and fqdnadd_pat.match(firewall['Исходящий FQDN']):
    ...

if firewall.get('Исходящий FQDN') - делает сразу две проверки:

  1. проверка на существование в словаре firewall ключа "Исходящий FQDN", т.к. dict.get(<not-existing-key>) вернет None
  2. проверка на то, что значение firewall['Исходящий FQDN'] не None

PS по канонам PEP-8, правильно проверять на variable is None следует так:

if not variable:
    ...

и для variable is not None:

if variable:
    ...
→ Ссылка