4) Основи Python. Зчитування, зберігання та обробка файлів в автоматизації мереж

6 травня 2025 9 хвилин Автор: Cyber Witcher

У сучасному мережевому адмініструванні знання Python стає незамінним інструментом, а вміння працювати з файлами — критично важливим навиком. Збереження конфігурацій, обробка логів, автоматизація обміну даними — усе це неможливо без грамотної взаємодії зі структурованими та неструктурованими файлами. У цій статті ви дізнаєтеся, як ефективно використовувати можливості мови для роботи з файлами у щоденній практиці мережевого спеціаліста. Цей матеріал створено спеціально для тих, хто прагне поєднати гнучкість Python із реальними задачами автоматизації в інфраструктурі.

 Робота з файлами

У практичній роботі, щоб повною мірою застосовувати знання, отримані в попередніх розділах, необхідно добре розумітися на роботі з файлами. Під час взаємодії з мережевим обладнанням, а також у багатьох інших випадках, доводиться мати справу з різними типами файлів. Наприклад, конфігураційні файли можуть бути простими текстовими документами без складної структури. Їх обробка є однією з тем цього розділу. Окремо існують шаблони конфігурацій, для яких зазвичай використовується спеціальний формат і розглядається застосування шаблонізатора Jinja2 для їх створення.

Ще один поширений тип — файли, що містять параметри підключення; вони часто мають структуру у вигляді YAML, JSON або CSV, і методи їх обробки описуються у відповідному розділі про серіалізацію. Існує також необхідність у роботі з іншими скриптами Python, де важливо вміти грамотно взаємодіяти з модулями. У даному розділі головний акцент зроблено на взаємодії з простими текстовими файлами, такими як конфігурації пристроїв Cisco. Основні дії, які детально пояснюються, охоплюють відкриття, читання, запис і закриття файлів. Тут подано лише базову інформацію, необхідну для впевненої роботи з файлами в Python, а для поглибленого вивчення завжди можна звернутися до офіційної документації.

Відкриття файлів

Для початку роботи з файлом його треба відкрити. Для відкриття файлів найчастіше використовується функція open:

file = open('file_name.txt', 'r')

У функції open():

Функція open() у Python дозволяє відкривати файли для подальшої роботи з ними. Першим аргументом передається ім’я або шлях до файлу (це може бути як абсолютний, так і відносний шлях), другим — режим, у якому файл буде відкрито. Наприклад, символ 'r' означає відкриття файлу тільки для читання, і це є режимом за замовчуванням. Якщо потрібно не лише читати, а й змінювати вміст, використовується режим 'r+'.

Для створення або повного перезапису файлу використовується режим 'w'. У цьому випадку, якщо файл вже існує, його вміст повністю стирається, а якщо не існує — створюється новий. Аналогічно діє режим 'w+', але з можливістю читання. Якщо мета — додати нові дані в кінець наявного файлу, не зачіпаючи вже існуючу інформацію, застосовується режим 'a'. Для читання і дописування одночасно використовують 'a+'.

Після відкриття файлу з допомогою open() створюється файловий об’єкт, до якого можна застосовувати методи читання, запису чи закриття в залежності від обраного режиму.

  • r – read;

  • a – append;

  • w – write.

Читання файлів

У Python є кілька методів читання файлу:

  • read– Зчитує вміст файлу в рядок

  • readline– зчитує файл рядково

  • readlines– зчитує рядки файлу та створює список із рядків

Подивимося як зчитувати вміст файлів на прикладі файлу r1.txt:

!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

read

Метод read– зчитує весь файл в один рядок.

Приклад використання методу read:

In [1]: f = open('r1.txt')

In [2]: f.read()
Out[2]: '!\nservice timestamps debug datetime msec localtime show-timezone year\nservice timestamps log datetime msec localtime show-timezone year\nservice password-encryption\nservice sequence-numbers\n!\nno ip domain lookup\n!\nip ssh version 2\n!\n'

In [3]: f.read()
Out[3]: ''

При повторному читанні файлу в 3 рядку, відображається порожній рядок. Так відбувається через те, що при викликі методу зчитується readвесь файл.seek.

readline

Файл можна вважати за допомогою методу readline:

In [4]: f = open('r1.txt')

In [5]: f.readline()
Out[5]: '!\n'

In [6]: f.readline()
Out[6]: 'service timestamps debug datetime msec localtime show-timezone year\n'

Але найчастіше простіше пройтися по об’єкту file в циклі, не використовуючи методи read...

In [7]: f = open('r1.txt')

In [8]: for line in f:
   ...:     print(line)
   ...:
!

service timestamps debug datetime msec localtime show-timezone year

service timestamps log datetime msec localtime show-timezone year

service password-encryption

service sequence-numbers

!

no ip domain lookup

!

ip ssh version 2

!

readlines

Ще один корисний метод – readlines. Він зчитує рядки файлу до списку:

In [9]: f = open('r1.txt')

In [10]: f.readlines()
Out[10]:
['!\n',
 'service timestamps debug datetime msec localtime show-timezone year\n',
 'service timestamps log datetime msec localtime show-timezone year\n',
 'service password-encryption\n',
 'service sequence-numbers\n',
 '!\n',
 'no ip domain lookup\n',
 '!\n',
 'ip ssh version 2\n',
 '!\n']

Якщо потрібно отримати рядки файлу, але без перекладу рядка в кінці, можна скористатися методом splitі як роздільник вказати символ \n:

In [11]: f = open('r1.txt')

In [12]: f.read().split('\n')
Out[12]:
['!',
 'service timestamps debug datetime msec localtime show-timezone year',
 'service timestamps log datetime msec localtime show-timezone year',
 'service password-encryption',
 'service sequence-numbers',
 '!',
 'no ip domain lookup',
 '!',
 'ip ssh version 2',
 '!',
 '']

Зауважте, що останній елемент списку – порожній рядок.

Якщо перед виконанням split, скористатися методом rstrip, список буде без порожнього рядка наприкінці:

In [13]: f = open('r1.txt')

In [14]: f.read().rstrip().split('\n')
Out[14]:
['!',
 'service timestamps debug datetime msec localtime show-timezone year',
 'service timestamps log datetime msec localtime show-timezone year',
 'service password-encryption',
 'service sequence-numbers',
 '!',
 'no ip domain lookup',
 '!',
 'ip ssh version 2',
 '!']

seek

Досі файл щоразу доводилося відкривати заново, щоб знову його рахувати. Так відбувається через те, що після методів читання курсор знаходиться в кінці файлу. І повторне читання повертає порожній рядок. Щоб ще раз рахувати інформацію з файлу, потрібно скористатися методом seek, який переміщує курсор у потрібне положення.

Приклад відкриття файлу та зчитування вмісту:

In [15]: f = open('r1.txt')

In [16]: print(f.read())
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

Якщо ще раз викликати метод read, повертається порожній рядок:

In [17]: print(f.read())

Але за допомогою методу seekможна перейти на початок файлу (0 означає початок файлу):

In [18]: f.seek(0)

Після того як за допомогою seekкурсора було переведено на початок файлу, можна знову зчитувати вміст:

In [19]: print(f.read())
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

Запис файлів

При записі дуже важливо визначитися з режимом відкриття файлу, щоб випадково його не видалити:

  • w– Відкрити файл для запису. Якщо файл існує, його вміст видаляється

  • a– Відкрити файл для доповнення запису. Дані додаються до кінця файлу

При цьому обидва режими створюють файл, якщо він не існує.

Для запису у файл використовуються такі методи:

  • write– записати у файл один рядок

  • writelines– дозволяє передавати як аргумент список рядків

write

Метод writeчекає рядок для запису.

Наприклад, візьмемо список рядків із конфігурацією:

In [1]: cfg_lines = ['!',
   ...:  'service timestamps debug datetime msec localtime show-timezone year',
   ...:  'service timestamps log datetime msec localtime show-timezone year',
   ...:  'service password-encryption',
   ...:  'service sequence-numbers',
   ...:  '!',
   ...:  'no ip domain lookup',
   ...:  '!',
   ...:  'ip ssh version 2',
   ...:  '!']

Відкриття файлу r2.txt в режимі запису:

In [2]: f = open('r2.txt', 'w')

Перетворимо список команд в один великий рядок за допомогою join:

In [3]: cfg_lines_as_string = '\n'.join(cfg_lines)

In [4]: cfg_lines_as_string
Out[4]: '!\nservice timestamps debug datetime msec localtime show-timezone year\nservice timestamps log datetime msec localtime show-timezone year\nservice password-encryption\nservice sequence-numbers\n!\nno ip domain lookup\n!\nip ssh version 2\n!'

Запис рядка у файл:

In [5]: f.write(cfg_lines_as_string)

Аналогічно можна додати рядок вручну:

In [6]: f.write('\nhostname r2')

Після завершення роботи з файлом його необхідно закрити:

In [7]: f.close()

Оскільки ipython підтримує команду cat, можна легко переглянути вміст файлу:

In [8]: cat r2.txt
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!
hostname r2

writelines

Метод writelinesчекає на список рядків, як аргумент.

Запис списку рядків cfg_lines у файл:

In [1]: cfg_lines = ['!',
   ...:  'service timestamps debug datetime msec localtime show-timezone year',
   ...:  'service timestamps log datetime msec localtime show-timezone year',
   ...:  'service password-encryption',
   ...:  'service sequence-numbers',
   ...:  '!',
   ...:  'no ip domain lookup',
   ...:  '!',
   ...:  'ip ssh version 2',
   ...:  '!']

In [9]: f = open('r2.txt', 'w')

In [10]: f.writelines(cfg_lines)

In [11]: f.close()

In [12]: cat r2.txt
!service timestamps debug datetime msec localtime show-timezone yearservice timestamps log datetime msec localtime show-timezone yearservice password-encryptionservice sequence-numbers!no ip domain lookup!ip ssh version 2!

В результаті всі рядки зі списку записалися в один рядок файлу, тому що в кінці рядків не було символу \n.

Додати переклад рядка можна по-різному. Наприклад, можна просто обробити список у циклі:

In [13]: cfg_lines2 = []

In [14]: for line in cfg_lines:
   ....:     cfg_lines2.append(line + '\n')
   ....:

In [15]: cfg_lines2
Out[15]:
['!\n',
 'service timestamps debug datetime msec localtime show-timezone year\n',
 'service timestamps log datetime msec localtime show-timezone year\n',
 'service password-encryption\n',
 'service sequence-numbers\n',
 '!\n',
 'no ip domain lookup\n',
 '!\n',
 'ip ssh version 2\n',

Якщо записати отриманий список назад у файл, він уже міститиме переклади рядків:

In [18]: f = open('r2.txt', 'w')

In [19]: f.writelines(cfg_lines2)

In [20]: f.close()

In [21]: cat r2.txt
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

Закриття файлів

У реальному житті для закриття файлів найчастіше використовується конструкція with. Її набагато зручніше використовувати, ніж закривати файл явно. Але, оскільки в житті можна зустріти і метод close, у цьому розділі розглядається як його використати.

Після завершення роботи з файлом його потрібно закрити. У деяких випадках Python може самостійно закрити файл. Але краще не розраховувати і закривати файл явно.

close

Метод close зустрічався у розділі запис файлів. Там він був потрібний для того, щоб вміст файлу був записаний на диск.

Для цього в Python є окремий метод flush. Але так як у прикладі із записом файлів, не потрібно було виконувати жодних операцій, файл можна було закрити.

Відкриємо файл r1.txt:

In [1]: f = open('r1.txt', 'r')

Тепер можна вважати вміст:

In [2]: print(f.read())
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

Об’єкт file має спеціальний атрибут closed, який дозволяє перевірити, закритий файл чи ні. Якщо файл відкритий, він повертає False:

In [3]: f.closed
Out[3]: False

Тепер закриваємо файл і знову перевіряємо closed:

In [4]: f.close()

In [5]: f.closed
Out[5]: True

Якщо спробувати прочитати файл, виникне виняток:

In [6]: print(f.read())
------------------------------------------------------------------
ValueError                       Traceback (most recent call last)
<ipython-input-53-2c962247edc5> in <module>()
----> 1 print(f.read())

ValueError: I/O operation on closed file

Конструкція with

Конструкція з називається менеджер контексту. У Python існує більш зручний спосіб роботи з файлами, ніж ті, які використовувалися досі – конструкція with:

In [1]: with open('r1.txt', 'r') as f:
  ....:     for line in f:
  ....:         print(line)
  ....:
!

service timestamps debug datetime msec localtime show-timezone year

service timestamps log datetime msec localtime show-timezone year

service password-encryption

service sequence-numbers

!

no ip domain lookup

!

ip ssh version 2

!

Крім того, конструкція withгарантує закриття файлу автоматично.

Зверніть увагу на те, як зчитуються рядки файлу:

for line in f:
    print(line)

Коли з файлом потрібно працювати рядково, краще використати такий варіант.

У попередньому висновку між рядками файлу були зайві порожні рядки, так як print додає ще один переклад рядка.

Щоб позбавитися цього, можна використовувати метод rstrip:

In [2]: with open('r1.txt', 'r') as f:
  ....:     for line in f:
  ....:         print(line.rstrip())
  ....:
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

In [3]: f.closed
Out[3]: True

І звичайно ж, з конструкцією withможна використовувати не тільки такий рядковий варіант зчитування, всі методи, що розглядалися до цього, також працюють:

In [4]: with open('r1.txt', 'r') as f:
  ....:     print(f.read())
  ....:
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!

Відкриття двох файлів

Іноді потрібно працювати одночасно із двома файлами. Наприклад, треба записати деякі рядки з одного файлу, до іншого.

У такому випадку, у блоці with можна відкривати два файли таким чином:

In [5]: with open('r1.txt') as src, open('result.txt', 'w') as dest:
   ...:     for line in src:
   ...:         if line.startswith('service'):
   ...:             dest.write(line)
   ...:

In [6]: cat result.txt
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers

Це рівнозначно таким двом блокам with:

In [7]: with open('r1.txt') as src:
   ...:     with open('result.txt', 'w') as dest:
   ...:         for line in src:
   ...:             if line.startswith('service'):
   ...:                 dest.write(line)
   ...:

Приклади роботи з файлами

У цьому підрозділі розглядається робота з файлами та поєднуються теми: файли, цикли та умови.

При обробці виведення команд чи конфігурації часто потрібно буде записати підсумкові дані у словник. Не завжди очевидно, як обробляти виведення команд і як загалом підходити до розбору виведення на частини. У цьому підрозділі розглядаються кілька прикладів, із зростаючим рівнем складності.

Розбір виведення стовпцями

У цьому прикладі розбиратиметься висновок команди sh ip int br. З виведення команди нам треба отримати відповідність ім’я інтерфейсу – IP-адресу. Тобто ім’я інтерфейсу – це ключ словника, а IP-адреса – значення. При цьому, відповідність треба робити тільки для тих інтерфейсів, у яких призначено IP-адресу.

Приклад виведення команди sh ip int br (файл sh_ip_int_br.txt):

R1#show ip interface brief
Interface                  IP-Address      OK? Method Status                Protocol
FastEthernet0/0            15.0.15.1       YES manual up                    up
FastEthernet0/1            10.0.12.1       YES manual up                    up
FastEthernet0/2            10.0.13.1       YES manual up                    up
FastEthernet0/3            unassigned      YES unset  up                    down
Loopback0                  10.1.1.1        YES manual up                    up
Loopback100                100.0.0.1       YES manual up                    up

Файл working_with_dict_example_1.py:

result = {}

with open('sh_ip_int_br.txt') as f:
    for line in f:
        line_list = line.split()
        if line_list and line_list[1][0].isdigit():
            interface = line_list[0]
            address = line_list[1]
            result[interface] = address

print(result)

Команда sh ip int br відображає виведення стовпцями. Отже, потрібні поля знаходяться в одному рядку. Скрипт обробляє висновок рядково і кожен рядок розбиває методом split.

Отриманий список містить стовпці виведення. Так як з усього висновку потрібні тільки інтерфейси, на яких налаштована IP-адреса, виконується перевірка першого символу другого стовпця: якщо перший символ число, значить на інтерфейсі призначена адреса і цей рядок треба обробляти.

Так як для кожного рядка є пара ключ і значення, вони надаються в словник: .result[interface] = address

Результатом виконання скрипта буде такий словник (тут він розбитий на пари ключ-значення для зручності, у реальному висновку скрипта словник відображатиметься в один рядок):

{'FastEthernet0/0': '15.0.15.1',
 'FastEthernet0/1': '10.0.12.1',
 'FastEthernet0/2': '10.0.13.1',
 'Loopback0': '10.1.1.1',
 'Loopback100': '100.0.0.1'}

Отримання ключа та значення з різних рядків виведення

Дуже часто виведення команд виглядає таким чином, що ключ та значення знаходяться у різних рядках. І треба придумати, яким чином обробляти висновок, щоб отримати потрібну відповідність.

Наприклад, з виведення команди треба отримати відповідність ім’я інтерфейсу – MTU (файл sh_ip_interface.txt):sh ip interface:

Ethernet0/0 is up, line protocol is up
  Internet address is 192.168.100.1/24
  Broadcast address is 255.255.255.255
  Address determined by non-volatile memory
  MTU is 1500 bytes
  Helper address is not set
  ...
Ethernet0/1 is up, line protocol is up
  Internet address is 192.168.200.1/24
  Broadcast address is 255.255.255.255
  Address determined by non-volatile memory
  MTU is 1500 bytes
  Helper address is not set
  ...
Ethernet0/2 is up, line protocol is up
  Internet address is 19.1.1.1/24
  Broadcast address is 255.255.255.255
  Address determined by non-volatile memory
  MTU is 1500 bytes
  Helper address is not set
  ...

Ім’я інтерфейсу знаходиться у рядку виду , а MTU у рядку виду .Ethernet0/0 is up, line protocol is upMTU is 1500 bytes

Наприклад, спробуємо запам’ятовувати щоразу інтерфейс та виводити його значення, коли зустрічається MTU, разом із значенням MTU:

In [2]: with open('sh_ip_interface.txt') as f:
   ...:     for line in f:
   ...:         if 'line protocol' in line:
   ...:             interface = line.split()[0]
   ...:         elif 'MTU is' in line:
   ...:             mtu = line.split()[-2]
   ...:             print('{:15}{}'.format(interface, mtu))
   ...:
Ethernet0/0    1500
Ethernet0/1    1500
Ethernet0/2    1500
Ethernet0/3    1500
Loopback0      1514

Висновок організований таким чином, що спочатку йде рядок з інтерфейсом, а потім через кілька рядків – рядок з MTU. Якщо запам’ятовувати ім’я інтерфейсу кожного разу, коли воно зустрічається, то на момент, коли зустрінеться рядок з MTU, останній запам’ятований інтерфейс – це той, до якого належить MTU.

Тепер, якщо необхідно створити словник з відповідністю інтерфейсу – MTU, достатньо записати значення на момент, коли був знайдений MTU.

Файл working_with_dict_example_2.py:

result = {}

with open('sh_ip_interface.txt') as f:
    for line in f:
        if 'line protocol' in line:
            interface = line.split()[0]
        elif 'MTU is' in line:
            mtu = line.split()[-2]
            result[interface] = mtu

print(result)

Результатом виконання скрипта буде такий словник (тут він розбитий на пари ключ-значення для зручності, у реальному висновку скрипта словник відображатиметься в один рядок):

{'Ethernet0/0': '1500',
 'Ethernet0/1': '1500',
 'Ethernet0/2': '1500',
 'Ethernet0/3': '1500',
 'Loopback0': '1514'}

Цей прийом буде досить часто корисним, оскільки виведення команд, загалом, організовано дуже схожим чином.

Вкладений словник

Якщо з виведення команди треба отримати кілька параметрів, дуже зручно використовувати словник із вкладеним словником.

Наприклад, з висновку `sh ip interface` потрібно отримати два параметри: IP-адресу та MTU. Для початку, виведення інформації:

Ethernet0/0 is up, line protocol is up
  Internet address is 192.168.100.1/24
  Broadcast address is 255.255.255.255
  Address determined by non-volatile memory
  MTU is 1500 bytes
  Helper address is not set
  ...
Ethernet0/1 is up, line protocol is up
  Internet address is 192.168.200.1/24
  Broadcast address is 255.255.255.255
  Address determined by non-volatile memory
  MTU is 1500 bytes
  Helper address is not set
  ...
Ethernet0/2 is up, line protocol is up
  Internet address is 19.1.1.1/24
  Broadcast address is 255.255.255.255
  Address determined by non-volatile memory
  MTU is 1500 bytes
  Helper address is not set
  ...

На першому етапі кожне значення запам’ятовується в змінну, а потім виводяться всі три значення. Значення виводяться, коли зустрівся рядок з MTU, тому що він йде останнім:

In [2]: with open('sh_ip_interface.txt') as f:
   ...:     for line in f:
   ...:         if 'line protocol' in line:
   ...:             interface = line.split()[0]
   ...:         elif 'Internet address' in line:
   ...:             ip_address = line.split()[-1]
   ...:         elif 'MTU' in line:
   ...:             mtu = line.split()[-2]
   ...:             print('{:15}{:17}{}'.format(interface, ip_address, mtu))
   ...:
Ethernet0/0    192.168.100.1/24 1500
Ethernet0/1    192.168.200.1/24 1500
Ethernet0/2    19.1.1.1/24      1500
Ethernet0/3    192.168.230.1/24 1500
Loopback0      4.4.4.4/32       1514

Тут використовується такий самий прийом, як у попередньому прикладі, але додається ще одна вкладеність словника:

result = {}

with open('sh_ip_interface.txt') as f:
    for line in f:
        if 'line protocol' in line:
            interface = line.split()[0]
            result[interface] = {}
        elif 'Internet address' in line:
            ip_address = line.split()[-1]
            result[interface]['ip'] = ip_address
        elif 'MTU' in line:
            mtu = line.split()[-2]
            result[interface]['mtu'] = mtu

print(result)

Щоразу, коли зустрічається інтерфейс, у словнику ‘result’ створюється ключ з ім’ям інтерфейсу, якому відповідає порожній словник. Ця заготівля потрібна для того, щоб на момент, коли зустрінеться IP-адреса або MTU, можна було записати параметр у вкладений словник відповідного інтерфейсу.

Результатом виконання скрипта буде такий словник (тут він розбитий на пари ключ-значення для зручності, у реальному висновку скрипта словник відображатиметься в один рядок):

{'Ethernet0/0': {'ip': '192.168.100.1/24', 'mtu': '1500'},
 'Ethernet0/1': {'ip': '192.168.200.1/24', 'mtu': '1500'},
 'Ethernet0/2': {'ip': '19.1.1.1/24', 'mtu': '1500'},
 'Ethernet0/3': {'ip': '192.168.230.1/24', 'mtu': '1500'},
 'Loopback0': {'ip': '4.4.4.4/32', 'mtu': '1514'}}

Висновок із порожніми значеннями

Іноді, у висновку траплятимуться секції з порожніми значеннями. Наприклад, у випадку висновку , можуть траплятися інтерфейси, які виглядають так:`sh ip interface`.

Ethernet0/1 is up, line protocol is up
  Internet protocol processing disabled
Ethernet0/2 is administratively down, line protocol is down
  Internet protocol processing disabled
Ethernet0/3 is administratively down, line protocol is down
  Internet protocol processing disabled

Відповідно, тут немає MTU або IP-адреси.

І якщо виконати попередній скрипт для файлу з такими інтерфейсами, результат буде таким (висновок для файлу sh_ip_interface2.txt):

{'Ethernet0/0': {'ip': '192.168.100.2/24', 'mtu': '1500'},
 'Ethernet0/1': {},
 'Ethernet0/2': {},
 'Ethernet0/3': {},
 'Loopback0': {'ip': '2.2.2.2/32', 'mtu': '1514'}}

Якщо необхідно додавати інтерфейси до словника лише, коли на інтерфейсі призначено IP-адресу, треба перенести створення ключа з ім’ям інтерфейсу на момент, коли зустрічається рядок з IP-адресою (файл working_with_dict_example_4.py):

result = {}

with open('sh_ip_interface2.txt') as f:
    for line in f:
        if 'line protocol' in line:
            interface = line.split()[0]
        elif 'Internet address' in line:
            ip_address = line.split()[-1]
            result[interface] = {}
            result[interface]['ip'] = ip_address
        elif 'MTU' in line:
            mtu = line.split()[-2]
            result[interface]['mtu'] = mtu

print(result)

У цьому випадку результатом буде такий словник:

{'Ethernet0/0': {'ip': '192.168.100.2/24', 'mtu': '1500'},
 'Loopback0': {'ip': '2.2.2.2/32', 'mtu': '1514'}}

Висновок

Розділ дає базові, але фундаментальні знання для впевненої роботи з текстовими файлами в Python. Через практичні приклади пояснюється, як зчитувати, записувати й обробляти конфігураційні дані з реальних мережевих сценаріїв, що є необхідним для ефективної автоматизації та аналізу мереж.

Інші статті по темі
Знайшли помилку?
Якщо ви знайшли помилку, зробіть скріншот і надішліть його боту.