ipaddress.md
1> **Источник:** https://python-all.ru/3.3/howto/ipaddress.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Введение в модуль ipaddress89| автор: | Peter Moody |10| --- | --- |11| автор: | Nick Coghlan |1213Обзор1415Цель этого документа – дать простое введение в модуль [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress). Он предназначен в первую очередь для пользователей, которые ещё не знакомы с терминологией IP-сетей, но также может быть полезен сетевым инженерам, желающим получить обзор того, как [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) представляет концепции IP-адресации.1617## Создание объектов адресов/сетей/интерфейсов1819Поскольку [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) – это модуль для проверки и управления IP-адресами, первое, что захочется сделать, – создать несколько объектов. С помощью [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) можно создавать объекты из строк и целых чисел.2021### Замечание о версиях IP2223Для читателей, не особо знакомых с IP-адресацией, важно знать, что в настоящее время происходит переход Интернет-протокола с версии 4 на версию 6. Этот переход происходит главным образом потому, что версия 4 протокола не предоставляет достаточного количества адресов для удовлетворения потребностей всего мира, особенно с учетом растущего числа устройств, имеющих прямое подключение к интернету.2425Объяснение деталей различий между двумя версиями протокола выходит за рамки данного введения, но читатели должны, по крайней мере, знать, что эти две версии существуют, и иногда может потребоваться принудительно использовать одну или другую версию.2627### IP-адреса хостов2829Адреса, часто называемые «адресами хостов», – это самая базовая единица при работе с IP-адресацией. Самый простой способ создать адрес – использовать фабричную функцию [`ipaddress.ip_address()`](https://python-all.ru/3.3/library/ipaddress.html#ipaddress.ip_address), которая автоматически определяет, создавать ли адрес IPv4 или IPv6, на основе переданного значения:3031```python32>>> ipaddress.ip_address('192.0.2.1')33IPv4Address('192.0.2.1')34>>> ipaddress.ip_address('2001:DB8::1')35IPv6Address('2001:db8::1')36```3738Адреса также можно создавать непосредственно из целых чисел. Значения, помещающиеся в 32 бита, считаются IPv4-адресами:3940```python41>>> ipaddress.ip_address(3221225985)42IPv4Address('192.0.2.1')43>>> ipaddress.ip_address(42540766411282592856903984951653826561)44IPv6Address('2001:db8::1')45```4647Чтобы принудительно использовать IPv4 или IPv6 адреса, соответствующие классы можно вызвать напрямую. Это особенно полезно для принудительного создания IPv6 адресов из небольших целых чисел:4849```python50>>> ipaddress.ip_address(1)51IPv4Address('0.0.0.1')52>>> ipaddress.IPv4Address(1)53IPv4Address('0.0.0.1')54>>> ipaddress.IPv6Address(1)55IPv6Address('::1')56```5758### Определение сетей5960Адреса хостов обычно группируются в IP-сети, поэтому [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) предоставляет способ создавать, просматривать и управлять определениями сетей. Объекты IP-сетей создаются из строк, которые определяют диапазон адресов хостов, входящих в эту сеть. Простейшая форма такой информации – пара «адрес сети/префикс сети», где префикс определяет количество старших битов, которые сравниваются для определения, является ли адрес частью сети, а адрес сети определяет ожидаемое значение этих битов.6162Как и для адресов, предусмотрена фабричная функция, которая автоматически определяет правильную версию IP:6364```python65>>> ipaddress.ip_network('192.0.2.0/24')66IPv4Network('192.0.2.0/24')67>>> ipaddress.ip_network('2001:db8::0/96')68IPv6Network('2001:db8::/96')69```7071Объекты сетей не могут иметь установленных битов хоста. Практический эффект этого заключается в том, что `192.0.2.1/24` не описывает сеть. Такие определения называются объектами интерфейсов, поскольку нотация «ip-на-сети» обычно используется для описания сетевых интерфейсов компьютера в заданной сети; они описываются далее в следующем разделе.7273По умолчанию попытка создать сетевой объект с установленными битами хоста приведёт к возбуждению [`ValueError`](https://python-all.ru/3.3/library/exceptions.html#ValueError). Чтобы вместо этого запросить приведение дополнительных битов к нулю, в конструктор можно передать флаг `strict=False`:7475```python76>>> ipaddress.ip_network('192.0.2.1/24')77Traceback (most recent call last):78 ...79ValueError: 192.0.2.1/24 has host bits set80>>> ipaddress.ip_network('192.0.2.1/24', strict=False)81IPv4Network('192.0.2.0/24')82```8384Хотя строковая форма предоставляет значительно большую гибкость, сети также можно определять с помощью целых чисел, как и адреса хостов. В этом случае сеть считается содержащей только единственный адрес, заданный целым числом, поэтому префикс сети включает весь сетевой адрес:8586```python87>>> ipaddress.ip_network(3221225984)88IPv4Network('192.0.2.0/32')89>>> ipaddress.ip_network(42540766411282592856903984951653826560)90IPv6Network('2001:db8::/128')91```9293Как и в случае с адресами, создание сети определённого типа можно принудительно выполнить, вызвав конструктор класса напрямую, а не используя фабричную функцию.9495### Интерфейсы хостов9697Как уже упоминалось выше, если нужно описать адрес в конкретной сети, ни класс адреса, ни класс сети по отдельности не подходят. Обозначение вида `192.0.2.1/24` обычно используется сетевыми инженерами и разработчиками инструментов для межсетевых экранов и маршрутизаторов как сокращение для «адрес хоста `192.0.2.1` в сети `192.0.2.0/24`». Соответственно, [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) предоставляет набор гибридных классов, которые связывают адрес с конкретной сетью. Интерфейс создания этих объектов идентичен интерфейсу определения сетевых объектов, за исключением того, что часть адреса не обязана быть сетевым адресом.9899```python100>>> ipaddress.ip_interface('192.0.2.1/24')101IPv4Interface('192.0.2.1/24')102>>> ipaddress.ip_interface('2001:db8::1/96')103IPv6Interface('2001:db8::1/96')104```105106Целочисленные входные данные принимаются (как и для сетей), а использование определённой версии IP можно принудительно задать, напрямую вызвав соответствующий конструктор.107108## Просмотр объектов Address/Network/Interface109110Вы потрудились создать объект IPv(4|6)(Address|Network|Interface), поэтому, скорее всего, захотите получить о нём информацию. [`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) старается сделать это простым и интуитивно понятным.111112Извлечение версии IP:113114```python115>>> addr4 = ipaddress.ip_address('192.0.2.1')116>>> addr6 = ipaddress.ip_address('2001:db8::1')117>>> addr6.version1186119>>> addr4.version1204121```122123Получение сети из интерфейса:124125```python126>>> host4 = ipaddress.ip_interface('192.0.2.1/24')127>>> host4.network128IPv4Network('192.0.2.0/24')129>>> host6 = ipaddress.ip_interface('2001:db8::1/96')130>>> host6.network131IPv6Network('2001:db8::/96')132```133134Определение количества отдельных адресов в сети:135136```python137>>> net4 = ipaddress.ip_network('192.0.2.0/24')138>>> net4.num_addresses139256140>>> net6 = ipaddress.ip_network('2001:db8::0/96')141>>> net6.num_addresses1424294967296143```144145Перебор «используемых» адресов в сети:146147```python148>>> net4 = ipaddress.ip_network('192.0.2.0/24')149>>> for x in net4.hosts():150... print(x) 151192.0.2.1152192.0.2.2153192.0.2.3154192.0.2.4155...156192.0.2.252157192.0.2.253158192.0.2.254159```160161Получение маски сети (т.е. битов, установленных в соответствии с префиксом сети) или маски хоста (все биты, не входящие в маску сети):162163```python164>>> net4 = ipaddress.ip_network('192.0.2.0/24')165>>> net4.netmask166IPv4Address('255.255.255.0')167>>> net4.hostmask168IPv4Address('0.0.0.255')169>>> net6 = ipaddress.ip_network('2001:db8::0/96')170>>> net6.netmask171IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::')172>>> net6.hostmask173IPv6Address('::ffff:ffff')174```175176Развёртывание или сжатие адреса:177178```python179>>> addr6.exploded180'2001:0db8:0000:0000:0000:0000:0000:0001'181>>> addr6.compressed182'2001:db8::1'183>>> net6.exploded184'2001:0db8:0000:0000:0000:0000:0000:0000/96'185>>> net6.compressed186'2001:db8::/96'187```188189Хотя IPv4 не поддерживает развёртывание или сжатие, соответствующие объекты всё равно предоставляют соответствующие свойства, чтобы код, не зависящий от версии, мог легко обеспечить использование самой краткой или самой полной формы для IPv6-адресов, при этом корректно обрабатывая IPv4-адреса.190191## Сети как списки адресов192193Иногда бывает полезно рассматривать сети как списки. Это означает, что их можно индексировать, например, так:194195```python196>>> net4[1]197IPv4Address('192.0.2.1')198>>> net4[-1]199IPv4Address('192.0.2.255')200>>> net6[1]201IPv6Address('2001:db8::1')202>>> net6[-1]203IPv6Address('2001:db8::ffff:ffff')204```205206Это также означает, что сетевые объекты можно использовать с синтаксисом проверки принадлежности к списку, например, так:207208```python209if address in network:210 # выполнить действие211```212213Проверка принадлежности выполняется эффективно на основе префикса сети:214215```python216>>> addr4 = ipaddress.ip_address('192.0.2.1')217>>> addr4 in ipaddress.ip_network('192.0.2.0/24')218True219>>> addr4 in ipaddress.ip_network('192.0.3.0/24')220False221```222223## Сравнения224225[`ipaddress`](https://python-all.ru/3.3/library/ipaddress.html#module-ipaddress) предоставляет несколько простых, надеемся, интуитивных способов сравнения объектов, когда это имеет смысл:226227```python228>>> ipaddress.ip_address('192.0.2.1') < ipaddress.ip_address('192.0.2.2')229True230```231232Исключение [`TypeError`](https://python-all.ru/3.3/library/exceptions.html#TypeError) возбуждается при попытке сравнить объекты разных версий или разных типов.233234## Использование IP-адресов с другими модулями235236Другие модули, использующие IP-адреса (например, [`socket`](https://python-all.ru/3.3/library/socket.html#module-socket)), обычно не принимают объекты этого модуля напрямую. Вместо этого их необходимо преобразовать в целое число или строку, которые другой модуль сможет принять:237238```python239>>> addr4 = ipaddress.ip_address('192.0.2.1')240>>> str(addr4)241'192.0.2.1'242>>> int(addr4)2433221225985244```245246## Получение более подробной информации при сбое создания экземпляра247248When creating address/network/interface objects using the version-agnostic factory functions, any errors will be reported as [`ValueError`](https://python-all.ru/3.3/library/exceptions.html#ValueError) with a generic error message that simply says the passed in value was not recognized as an object of that type. The lack of a specific error is because it’s necessary to know whether the value is *supposed* to be IPv4 or IPv6 in order to provide more detail on why it has been rejected.249250Для поддержки случаев, когда полезно иметь доступ к этой дополнительной информации, отдельные конструкторы классов фактически возбуждают подклассы [`ValueError`](https://python-all.ru/3.3/library/exceptions.html#ValueError) – [`ipaddress.AddressValueError`](https://python-all.ru/3.3/library/ipaddress.html#ipaddress.AddressValueError) и [`ipaddress.NetmaskValueError`](https://python-all.ru/3.3/library/ipaddress.html#ipaddress.NetmaskValueError) – чтобы указать, какая именно часть определения не была разобрана правильно.251252Сообщения об ошибках становятся значительно более подробными при прямом использовании конструкторов классов. Например:253254```python255>>> ipaddress.ip_address("192.168.0.256")256Traceback (most recent call last):257 ...258ValueError: '192.168.0.256' does not appear to be an IPv4 or IPv6 address259>>> ipaddress.IPv4Address("192.168.0.256")260Traceback (most recent call last):261 ...262ipaddress.AddressValueError: Octet 256 (> 255) not permitted in '192.168.0.256'263264>>> ipaddress.ip_network("192.168.0.1/64")265Traceback (most recent call last):266 ...267ValueError: '192.168.0.1/64' does not appear to be an IPv4 or IPv6 network268>>> ipaddress.IPv4Network("192.168.0.1/64")269Traceback (most recent call last):270 ...271ipaddress.NetmaskValueError: '64' is not a valid netmask272```273274Однако оба специфических для модуля исключения имеют [`ValueError`](https://python-all.ru/3.3/library/exceptions.html#ValueError) в качестве родительского класса, так что если вас не волнует конкретный тип ошибки, вы по-прежнему можете писать код следующим образом:275276```python277try:278 network = ipaddress.IPv4Network(address)279except ValueError:280 print('address/netmask is invalid for IPv4:', address)281```282