Дескриптор — это не один конкретный объект, а общий технический термин для сущности, которая описывает ресурс или даёт программе управляемый доступ к нему. В Linux и других Unix-подобных системах чаще всего говорят о файловых дескрипторах, в Windows близкую роль играют handles, а в Python дескриптором называют механизм управления доступом к атрибутам объектов.

Дескриптор простыми словами
Слово descriptor буквально можно перевести как «описатель». В программировании оно обычно означает небольшой идентификатор, структуру или объект, через который программа обращается к чему-то более сложному.
Удобная аналогия — номерок в гардеробе. Сам номерок не является курткой и не содержит её внутри. Он лишь позволяет системе понять, какой именно объект связан с владельцем номерка. Примерно так же программа может хранить не весь системный объект, а компактную ссылку на него.
Из-за этого термин «дескриптор» встречается в разных контекстах и означает немного разные вещи.
| Контекст | Что называют дескриптором | Для чего он нужен |
| Linux / Unix | Небольшое целое число | Обращение к открытому файлу, сокету, каналу и другим ресурсам |
| Windows | Обычно используется термин handle | Доступ к файлам, процессам, потокам, событиям и другим объектам ОС |
| Python | Объект с __get__(), __set__() или __delete__() | Управление чтением, записью и удалением атрибутов |
| Системное программирование | Идентификатор или структура, описывающая ресурс | Передача ресурса между уровнями программы без прямого доступа к его внутреннему устройству |
Поэтому фраза «дескриптор — это число» верна только в определённом контексте. Для Unix-файлового дескриптора — да. Для Python-дескриптора — уже нет.
Файловый дескриптор в Linux и Unix
В Linux файловый дескриптор — это небольшое неотрицательное целое число, которое служит индексом в таблице открытых дескрипторов конкретного процесса.
Когда программа вызывает open(), ядро открывает файл и возвращает программе номер. Дальнейшие операции read(), write(), lseek() и другие используют именно этот номер.
Упрощённо цепочка выглядит так:
Программа
↓
fd = 3
↓
Таблица файловых дескрипторов процесса
↓
Описание открытого файла
↓
Файл / сокет / канал / устройствоНапример:
int fd = open("example.txt", O_RDONLY);Если вызов прошёл успешно, переменная fd может получить значение 3.
Число 3 не является адресом файла на диске. Оно лишь сообщает ядру, к какой записи таблицы открытых ресурсов относится следующий системный вызов.
Почему часто встречаются 0, 1 и 2
В Unix-подобных системах первые три файловых дескриптора традиционно заняты стандартными потоками:
| Дескриптор | Назначение |
0 | стандартный ввод — stdin |
1 | стандартный вывод — stdout |
2 | стандартный поток ошибок — stderr |
Поэтому первый файл, который программа открывает самостоятельно, часто получает дескриптор 3, если до этого другие ресурсы не были открыты.
Это хорошо видно в командной строке Linux. Конструкция:
command > output.txtперенаправляет стандартный вывод программы, то есть файловый дескриптор 1, в файл output.txt.
А команда:
command 2> errors.txtнаправляет поток ошибок с дескриптора 2 в отдельный файл.
Дескриптор — это не обязательно файл
Название «файловый дескриптор» иногда сбивает с толку. В Unix-подобных системах через один и тот же интерфейс могут обслуживаться разные типы ресурсов.
Файловый дескриптор может ссылаться, например, на:
- обычный файл;
- каталог;
- сетевой сокет;
- pipe;
- FIFO;
- терминал;
- устройство;
- некоторые специальные интерфейсы ядра.
Именно поэтому сетевой сервер в Linux может использовать функции вроде select(), poll() или epoll() для работы сразу с большим количеством соединений: каждое открытое соединение представлено файловым дескриптором.
Операционная система скрывает внутреннее устройство ресурса, а приложение взаимодействует с ним через унифицированный идентификатор.
Что происходит после open()
В Linux вызов open() создаёт не просто число.
Ядро формирует запись, которую документация Linux называет open file description. В ней хранятся сведения об открытом ресурсе, в том числе текущая позиция чтения и некоторые флаги состояния.
Файловый дескриптор процесса ссылается на эту запись.
Это различие важно.
fd 3 ──┐
├──> open file description ──> файл
fd 7 ──┘Два разных дескриптора могут ссылаться на одно и то же описание открытого файла. Например, такое происходит после dup() или при наследовании открытых дескрипторов дочерним процессом.
В этом случае дескрипторы разные, но состояние открытого файла частично общее — например, они могут использовать одну текущую позицию чтения.
Почему дескрипторы нужно закрывать
После завершения работы с ресурсом файловый дескриптор обычно закрывают:
close(fd);У процесса есть ограничение на количество одновременно открытых файловых дескрипторов. Если программа постоянно открывает файлы или соединения и не закрывает их, возникает утечка дескрипторов.
Типичный сценарий:
1. Сервер принимает соединение.
2. Для него создаётся новый файловый дескриптор.
3. Клиент отключается.
4. Программа забывает закрыть fd.
5. Ситуация повторяется тысячи раз.
6. Процесс достигает лимита открытых дескрипторов.
7. Новые файлы или соединения открыть уже нельзя.В Linux подобная ошибка часто проявляется сообщением:
Too many open filesПроверить открытые файловые дескрипторы процесса можно через каталог:
/proc/<PID>/fd/Например:
ls -l /proc/1234/fd/В нём будут записи 0, 1, 2, 3 и далее, соответствующие открытым дескрипторам процесса.
Файловый дескриптор и handle в Windows — в чём разница
В Windows чаще используется термин handle — «дескриптор» или «описатель объекта» в русскоязычной технической литературе.
Handle позволяет приложению обращаться к системному объекту через непрозрачное значение типа HANDLE. Такой объект может представлять:
- файл;
- процесс;
- поток;
- событие;
- ключ реестра;
- объект синхронизации;
- другие ресурсы Windows.
Логика похожа на Unix:
Программа → handle → системный объектНо считать Windows handle и Unix file descriptor полностью одинаковыми нельзя.
Unix-файловый дескриптор обычно представляет собой небольшое целое число, индексирующее таблицу открытых дескрипторов процесса. Windows API использует непрозрачный тип HANDLE, внутреннее значение которого приложение не должно трактовать самостоятельно.
Для разработчика принцип один: операционная система отдаёт программе управляемую ссылку на ресурс, а сама внутренняя структура объекта остаётся скрытой.
Что такое дескриптор в Python
В Python слово «дескриптор» означает уже другой механизм.
Согласно официальной документации Python, дескриптором считается объект, который определяет хотя бы один из методов:
__get__()
__set__()
__delete__()Такой объект может перехватывать доступ к атрибуту класса.
Простейший пример:
class Positive:
def __get__(self, obj, objtype=None):
return obj._value
def __set__(self, obj, value):
if value < 0:
raise ValueError("Значение не может быть отрицательным")
obj._value = value
class Product:
price = Positive()
def __init__(self, price):
self.price = priceТеперь:
item = Product(100)
print(item.price)вернёт 100.
А попытка:
item.price = -50вызовет исключение.
Дескриптор в этом случае становится промежуточным слоем между выражением:
item.priceи фактическим хранением значения.
Где Python использует дескрипторы внутри языка
Дескрипторный протокол — не редкая экзотика. На нём основаны привычные механизмы Python.
К ним относятся:
- методы объектов;
property;classmethod;staticmethod;super();- часть поведения
__slots__.
Например:
class User:
@property
def name(self):
return self._nameproperty работает как дескриптор и определяет, что именно произойдёт при обращении к user.name.
Поэтому изучение дескрипторов особенно полезно при разработке библиотек, ORM, систем валидации, фреймворков и собственных механизмов управления атрибутами.
Data descriptor и non-data descriptor в Python
Python различает два основных типа дескрипторов.
Data descriptor
Объект считается data descriptor, если определяет __set__() или __delete__().
Например:
class Field:
def __get__(self, obj, objtype=None):
...
def __set__(self, obj, value):
...Такой дескриптор имеет более высокий приоритет при поиске атрибута, чем одноимённое значение в словаре экземпляра.
Non-data descriptor
Если объект определяет только __get__(), он относится к non-data descriptors.
Обычные методы класса — один из наиболее известных примеров такого поведения.
Разница становится важной, когда у экземпляра и класса существуют одноимённые атрибуты: Python использует установленный порядок поиска, а тип дескриптора влияет на то, какое значение победит.
Почему одно слово означает разные вещи
Все варианты термина объединяет одна идея: дескриптор находится между программой и объектом, к которому она обращается.
Но форма этого посредника зависит от системы.
Linux:
процесс → число fd → открытый ресурс
Windows:
процесс → HANDLE → объект ОС
Python:
экземпляр → атрибут класса-дескриптор → логика чтения/записиПоэтому при чтении документации сначала нужно понять контекст.
Фраза:
«Закройте дескриптор после использования»
скорее всего относится к системному ресурсу.
А фраза:
«Реализуйте метод
__get__()в дескрипторе»
однозначно относится к Python.
Дескриптор, указатель и идентификатор — не одно и то же
Эти термины часто смешивают, хотя они решают разные задачи.
| Термин | Что представляет | Можно ли напрямую обращаться к объекту |
| Дескриптор | Управляемую ссылку или механизм доступа | Обычно нет, доступ идёт через API или протокол |
| Указатель | Адрес или значение, позволяющее обратиться к области памяти | Да, в языках с соответствующей моделью памяти |
| ID | Уникальный или условно уникальный номер объекта | Зависит от системы |
| Handle | Непрозрачную ссылку на объект, особенно в Windows API | Через функции API |
У файлового дескриптора число 3 само по себе ничего не говорит о расположении файла в памяти или на диске. Оно имеет смысл только внутри соответствующего процесса и его таблицы открытых дескрипторов.
Это одно из главных отличий дескриптора от указателя.
Где разработчик сталкивается с дескрипторами на практике
Даже если приложение написано на языке высокого уровня, дескрипторы постоянно работают под капотом.
В серверной разработке
Каждое сетевое соединение может занимать файловый дескриптор. Поэтому для высоконагруженного сервера имеют значение системные лимиты и корректное закрытие сокетов.
При работе с файлами
Открытый файл в Python, C, Go, Rust или другом языке в конечном счёте связан с механизмами операционной системы. Высокоуровневый объект скрывает низкоуровневый файловый дескриптор, но сам ресурс остаётся системным.
При диагностике утечек
Если приложение постепенно перестаёт открывать файлы или принимать новые соединения, одной из причин может быть утечка файловых дескрипторов.
При разработке на Python
Дескрипторы позволяют создать единое правило для множества атрибутов — например, проверять тип, диапазон значения, формат строки или автоматически преобразовывать данные.
Вместо повторения одинаковой логики в десятках классов её можно вынести в один дескриптор.
Частые ошибки в понимании термина
«Дескриптор — это адрес объекта»
Не обязательно. Unix-файловый дескриптор — индекс в таблице процесса, а не адрес объекта в памяти.
«Дескриптор всегда является числом»
Нет. Файловый дескриптор Unix — число, но Python-дескриптор — объект, реализующий специальный протокол.
«Файловый дескриптор бывает только у файлов»
Нет. В Unix-подобной системе файловые дескрипторы используются и для сокетов, каналов и ряда других ресурсов.
«Windows handle и Linux fd полностью одинаковы»
Нет. Они решают похожую задачу — дают программе ссылку на системный ресурс, — но реализованы по-разному и используются через разные API.
«О закрытии дескриптора можно не думать»
Для ресурсов операционной системы это опасная практика. Незакрытые дескрипторы могут накапливаться и исчерпать лимит процесса.
Как запомнить смысл дескриптора
Самая полезная формулировка:
Дескриптор — это посредник между кодом и некоторым объектом или ресурсом.
Дальше нужно только уточнить контекст.
Если речь о Linux — чаще всего это номер открытого ресурса.
Если о Windows — обычно имеется в виду handle.
Если о Python — объект, управляющий поведением атрибута.
Такое определение точнее, чем попытка свести все варианты термина к одному типу данных.
Что нужно понимать о дескрипторах
Дескриптор не имеет единственного универсального определения для всех языков и операционных систем. Общий смысл термина — предоставить программе контролируемый способ идентифицировать ресурс, описывать его или управлять доступом к нему.
Для системного программирования особенно важно различать три случая:
- Unix/Linux: файловый дескриптор — небольшой неотрицательный целочисленный идентификатор открытого ресурса внутри процесса.
- Windows: для доступа к системным объектам широко используются handles — непрозрачные значения, передаваемые функциям Windows API.
- Python: descriptor — объект с
__get__(),__set__()или__delete__(), который может изменять стандартное поведение доступа к атрибутам.
Если в документации встречается слово «дескриптор», его смысл почти всегда можно определить по соседним терминам: open(), read(), socket указывают на файловые дескрипторы Unix; HANDLE и CloseHandle() — на Windows; __get__() и property — на Python.