Викиучебник ruwikibooks https://ru.wikibooks.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0 MediaWiki 1.47.0-wmf.24 first-letter Медиа Служебная Обсуждение Участник Обсуждение участника Викиучебник Обсуждение Викиучебника Файл Обсуждение файла MediaWiki Обсуждение MediaWiki Шаблон Обсуждение шаблона Справка Обсуждение справки Категория Обсуждение категории Полка Обсуждение полки Импортировано Обсуждение импортированного Рецепт Обсуждение рецепта Задача Обсуждение задачи TimedText TimedText talk Модуль Обсуждение модуля Event Event talk Викиучебник:Общий форум 4 1253 270413 270407 2026-10-26T14:01:17Z MediaWiki message delivery 37025 /* Переключение сервера: ваш вики-проект скоро на короткое время будет доступен в режиме «только для чтения» */ новая тема 270413 wikitext text/x-wiki {{Участник:Kylaixbot/ArchiveConfig |archive = Викиучебник:Общий форум/Архив/%(year)d |algo = old(60d) |counter = 1 }} {{Форум}} {{Архив-П |2005-2007|2008|2009-2010|2011-2012|2013|2014|2015|2016|2018|2019|2020|2021|2022|2023|2024|2025}} {{Актуально}} == Что тут == Тут есть кто живой? — [[Участник:Medyanowsky|Medyanowsky]] ([[Обсуждение участника:Medyanowsky|обсуждение]]) 08:12, 13 октября 2026 (UTC) :В чем вопрос? [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 17:07, 13 октября 2026 (UTC) :Все живы! [[Участник:Erokhin|Erokhin]] ([[Обсуждение участника:Erokhin|обсуждение]]) 03:45, 25 октября 2026 (UTC) Ну, тут Leksey и Kylain Aixter активны, я особо не редактирую, но на сообщения отвечаю. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 13:00, 14 октября 2026 (UTC) == Извинения, что задержался == Извиняюсь, что закопался, но я чет своего бота @[[Участник:Kylaixbot|Kylaixbot]] не могу починить из-за приколов Тулфорджа. Они там обновили политику venv и у меня никак не получается нормально запустить моего бота. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:52, 14 июня 2026 (UTC) :Я оказался достаточно оперативен и бот заработал [[Участник:Kylaixbot|Kylaixbot]] ([[Обсуждение участника:Kylaixbot|обсуждение]]) 14:27, 26 июля 2026 (UTC) ::Чем сейчас занят ваш бот? [[Участник:Erokhin|Erokhin]] ([[Обсуждение участника:Erokhin|обсуждение]]) 03:44, 25 октября 2026 (UTC) == Шаблон может быть улучшен == По определению, большинство учебников пишут по книгам; шаблон Книга работает здесь безупречно. По стечению обстоятельств пришлось использовать шаблон Статья. Видимо, он не точно соответствует этому шаблону в википедии: ISSN (и отчасти PMID и PMC) работает не так, как в википедии. А в [[Шаблон:Статья/Документация| документации]] не написано, что есть отличия (issn): фрагмент кода: . . . место=Москва|год=2016|номер=8|issn=0131-2618|страницы=74—79|pmid=24006620|pmc=PMC1234567}} ISSN 0131-2618, PMID 24006620</ref> его отображение: Москва, 2016. — № 8. — С. 74—79. — ISSN Шаблон:ISSN search link. — Шаблон:PMID. — Шаблон:PMC. ISSN 0131-2618, PMID 24006620 + сообщения ниже красным шрифтом: Шаблон:ISSN search link (править) ... Шаблон:PMID (править) ... Шаблон:PMC (править) Если можно без больших трудозатрат устранить отличия в шаблонах от википедии, прошу Вас это сделать, как сможете. Спасибо [[Служебная:Вклад/&#126;2026-31604-77|&#126;2026-31604-77]] ([[Обсуждение участника:&#126;2026-31604-77|обс.]]) 17:46, 29 мая 2026 (UTC) : А можете где-то им воспользоваться и пингануть меня плиз? Я поправлю шаблон<br> P.s.: последний раз, судя по истории, я его и его подшаблоны импортировал в феврале 2025 года. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:50, 14 июня 2026 (UTC) == Тип блюда (P8431 course) == в элементе викиданных, связанном со страницей рецепта, можно добавить поле Тип блюда (P8431 course). в викиданных данное свойство имеет ограниченное количество значений: закуска, первое блюдо, суп, салат, рыба, второе блюдо, десерт, соус, завтрак, пирог, гарнир... после указания в поле нужного значения, рецепт будет размещен в аналогичной категории. но у нас в кулинарной книге есть аналогичные категории, только во множественном числе, например, Закуски, Вторые блюда, Салаты... в результате получается двойная категоризация и двойное отображение в кулинарной книге. есть идеи, что с этим можно сделать? переименовать в викиданных эти значения - перевести во множественное число? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 16:00, 26 мая 2026 (UTC) : Я не знаю [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:46, 28 мая 2026 (UTC) : Оооо да! Я давно заметил это и в прошлых темах предлагал к обсуждению этот вопрос. Я сторонник стандарта Викиданных, банально потому что это стандартизировано под Википедию. Но вот другие что об этом думают? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:47, 14 июня 2026 (UTC) :: Я за викиданные, но что делать - переименовывать или нет - не знаю. Есть возможсноть оставить в единственном числе в ВД, а категории иметь в множественном? [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 16:53, 15 июня 2026 (UTC) ::: Кажется нет. Это невозможно будет автоматизировать <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 00:09, 16 июня 2026 (UTC) == Полки в Кулинарной книге == можно ли в кулинарной книге сделать еще одну корневую полку и как? например, полку Кулинарные процессы, аналогично Ингредиенты — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 13:59, 26 мая 2026 (UTC) : И на этот вопрос я не знаю ответа [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:46, 28 мая 2026 (UTC) : эээээ, можно...<br> но что там будет? Примерно? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:44, 14 июня 2026 (UTC) == [[Викиучебник:Каталог учебников/Список]] == не обновляется — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 08:36, 22 мая 2026 (UTC) : тэкс, значит бот мой сломался. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 13:34, 22 мая 2026 (UTC) == [[Шаблон:К быстрому удалению|Шаблон:КБУ]] == как часто удаляются страницы, помеченные этим шаблоном? их удаляет бот или админ вручную? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 07:28, 22 мая 2026 (UTC) : Админ. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:48, 22 мая 2026 (UTC) :кто-то из админов или подводящих итоги может пройтись и удалить [https://ru.wikibooks.org/wiki/Служебная:Ссылки_сюда?target=Шаблон%3AК+быстрому+удалению&namespace=&limit=500 статьи с данным шаблоном] в основном пространстве и пространстве полок? частично это нужно, чтобы переименовать другие страницы + пустые страницы/полки. [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 08:25, 23 мая 2026 (UTC) :: Ну, я не админ, надо Лексея пингануть @[[Участник:Leksey|Leksey]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 14:17, 24 мая 2026 (UTC) :: Удалил! :: @[[Участник:Kylaix|Kylaix]] посмотри, плиз, почему в категорию включило статьи, где только ссылка на шаблон. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 21:49, 25 мая 2026 (UTC) :::не могу переименовать [[Введение в дифференциальные уравнения]] в Дифференциальные уравнения - "Переименование невозможно: страница с таким именем уже существует". но я не нашла такой страницы [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:56, 28 мая 2026 (UTC) :::: Она в перенаправлении <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 17:12, 28 мая 2026 (UTC) ::::: [[Дифференциальные уравнения]] удалена и нет на этом месте перенаправления [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:42, 28 мая 2026 (UTC) ::::: там СО была и она мешала [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:44, 28 мая 2026 (UTC) :::: переименовал [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:45, 28 мая 2026 (UTC) :::аналогично не могу переименовать [[Постулат Бертрана]] в Теория чисел/Постулат Бертрана [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:57, 28 мая 2026 (UTC) :::: переименовал [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:44, 28 мая 2026 (UTC) ::: @[[Участник:Leksey|Leksey]] Если в Ссылки сюда нажать кнопки Скрыть ссылки и Скрыть перенаправления , то будет показываться только включения, то есть только страницы которые надо удалить. Вот ссылка: https://ru.wikibooks.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D0%B8_%D1%81%D1%8E%D0%B4%D0%B0?target=%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%3A%D0%9A+%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%BC%D1%83+%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D1%8E&namespace=&hidelinks=1&hideredirs=1&limit=50 [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:11, 29 мая 2026 (UTC) == Сколько уровней полок поддерживается? == например, в [[Викиучебник:Каталог учебников/Список]]? Сейчас только два уровня, например, Языки - Языки Европы. А может быть 3-й, 4-й и т.д уровни? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 17:13, 21 мая 2026 (UTC) : По идее - да, там вроде бесконечная вложенность, главное только правильно оформлять полки. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:50, 14 июня 2026 (UTC) == [[Полка:Компьютеры]] == все доп. полки почему-то задублированы, например, Программирование фигурирует дважды — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:50, 21 мая 2026 (UTC) :исправила через Править код [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 10:22, 21 мая 2026 (UTC) : О, спасибо что убрали. Ранее они просто добавлялись в ручную. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 13:36, 22 мая 2026 (UTC) == Не обновляются Полки == 1. Дополнительные полки: [[Полка:Теория чисел]], на ней лежит учебник [https://ru.wikibooks.org/wiki/Теория_чисел Теория чисел], но в учебнике в шаблоне Название учебника указана категория не Теория чисел, а Математика (я ее сделала доп. полкой на основной полке Формальные науки). почему учебник таки находится на данной полке? из-за того, что у него внизу указана категория Теория чисел? аналогично [[Полка:Дифференциальные уравнения]], [[Полка:Математический анализ]], [[Полка:Алгебра]], [[Полка:Занимательная математика]]. 2. Основные полки: [[Полка:Компьютеры]], [[Полка:Естественные науки]], [[Полка:Языки]], [[Полка:Досуг]], [[Полка:Техника]], [[Полка:Гуманитарные науки]] существует ли бот, который обновляет полки? уже прошло несколько дней, но полки не обновились, кнопка Очистить кэш не помогает — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 07:55, 21 мая 2026 (UTC) == [[Теория музыки для математиков]] == в шаблоне Название учебника две Категории - Музыка, Математика но на полке [[Полка:Математика|Математика]] он не появляется почему? потому что это Основная полка? нужно указать вместо нее Дополнительную полку в шаблоне? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:24, 20 мая 2026 (UTC) : Последнее верно. Это основная полка а требуется дополнительная полка. Я правда не знаю как ее можно было назвать, но раздел бы стоило создать. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:11, 20 мая 2026 (UTC) == КУ == [[Викиучебник:К удалению/Май 2026]] Прошу всех обратить внимание. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:31, 20 мая 2026 (UTC) :создала в вики страницу [[w:Биографический_метод|Биографический метод]] :может, их связать? и поставить в учебнике шаблон, что это заготовка. может, кто заинтересуется и начнет наполнять учебник? [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:36, 20 мая 2026 (UTC) == Полка и категория == чем отличается [[Полка:Математика]] от [https://ru.wikibooks.org/wiki/Категория:Математика Категория:Математика]? зачем нужны полки? почему не ограничиться только категориями? например, сгласно полкам учебных пособий 2 шт, согласно категориям находится еще 100 шт учебных пособий ... — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:26, 19 мая 2026 (UTC) : Категорию проставляют в статьях, на полке же список статей. К тому же, зачем традиции ломать? [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:32, 20 мая 2026 (UTC) ::выглядит, как дублирующий инструмент ::тем паче, что рецепты на категориях строятся [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:21, 20 мая 2026 (UTC) ::: Иронично что вы оба правы. Категории, по сути, помогают работе шаблонов и модулей для организации каталога учебников. А каталог учебников кажется сейчас наиболее удобным средством для поиска нужных книг. Было бы круто не использовать категории, но к сожалению иначе организовать полки было бы невозможно или, как минимум, труднее на порядок. Ну и да, + это еще и дань традициям - в Википедии, к примеру, они до сих пор используются. ::: Кстати, напоминаю, что категории в статьях проставляются через {{tl|Название учебника}} и для рецептов через {{tl|Рецепт}}. Касательно разницы в полках и категориях: просто те 98 учебников еще не обработаны через эти шаблоны. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:08, 20 мая 2026 (UTC) == Страницы учебника на полке == на полке [[Полка:Математика|Математика]] есть полка [[Полка:Теория чисел|Теория чисел]] на ней лежит учебник [[Теория чисел]] и страница из учебника [[Теория чисел/Постулат Бертрана]] что не есть правильно - на полке должны быть только учебники аналогично на полке [[Полка:Дифференциальные уравнения|Дифференциальные уравнения]] как удалить страницы учебника с полки? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 07:03, 19 мая 2026 (UTC) : Привет.<br> Я пока не знаю причину, ищу ошибку в шаблонах. Тем не менее, большая просьба либо создавать эти учебники уже на существующих полках, либо же переименовать их так, чтобы не совпадали с названием полки. Это может быть одной из причин. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 07:40, 19 мая 2026 (UTC) :: Подтверждаю. Учебники не стоит называть одинаково с названием полки. Более того, не стоит создавать отдельные полки для каждого учебника. Я оставил лишь полку с теорией чисел, учебник про диффуры перенес в полку матанализа. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 08:01, 19 мая 2026 (UTC) :::спасибо! :::но дифференециальные уравнения - это не матан, это отдельный [[w:Разделы_математики#Математика_как_учебная_дисциплина|учебный раздел математики]] :::поэтому для него была создана своя полка :::иначе можно обойтись вообще без полок и все учебники размещать на полке Математика [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:05, 19 мая 2026 (UTC) :::: Ну, я понимаю что его в целом выделяют, но тут проблема именно Викиучебника. У нас пока* мало книг и имеет смысл их пока отводить в гораздо более крупные разделы, чем это делается в науке.<br> <nowiki>*</nowiki>надеюсь все же мы сможем хотя бы перевести достаточное количество книг, а еще лучше написать сами в ближайшее время. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 09:27, 19 мая 2026 (UTC) :::::тогда можно сделать полку Другие разделы :::::в нее отнести все, что не Алгебра и не Геометрия [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:30, 19 мая 2026 (UTC) :::::: Хорошо, сделаю. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 09:41, 19 мая 2026 (UTC) :::::::я все перенесла в Алгебру/Геометрию [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 13:05, 19 мая 2026 (UTC) :::::::ненужные страницы пометила КБУ в пространствах - Основное, Полка [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 13:55, 19 мая 2026 (UTC) == Как привязать учебник к другой полке? == например, [[Дифференциальные уравнения]] к полке [[Полка:Дифференциальные уравнения|Дифференциальные уравнения]]— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 17:46, 17 мая 2026 (UTC) : @[[Участник:Kylaix|Kylaix]] ответишь? [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:50, 17 мая 2026 (UTC) :или достаточно в учебнике в шаблоне "Название учебника" указать нужные значения в Категория? и бот привяжет учебник, куда нужно? в какой время отрабатывает бот? явно, сразу не после правки Категория [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 10:02, 18 мая 2026 (UTC) :: Да да да, в категорию просто вписываете полку и бот пройдет (один раз в день делает проходку) и ваша книга попадет на полку. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 14:44, 18 мая 2026 (UTC) == CAPTCHA == при сохранении правок возникает: CAPTCHA: Для редактирования страницы, пожалуйста, введите буквы, которые видны на изображении ниже это из-за того, что я новичок? или так всегда будет?— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 16:29, 17 мая 2026 (UTC) : Никогда такого не видел. Конечно пройдет. : А можете кинуть на почту скриншот leksey@ya.ru<br> Интересно посмотреть даже. : Я посмотрю, может вам можно статус подкрутить руками, но вроде я такого не видел. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:49, 17 мая 2026 (UTC) : Попытался поменять вам группу, но все что мне дает это. Наверное, когда вы попадете в группу "Автоподтвержденные", то отпустит. Как это работает - я не знаю. У вас же по идее глобальный аккаунт и специально в Учебнике вы вчера условно не регились? : {{Цитата|Группы, которые вы можете изменять<ul><li>исключение из IP-блокировок</li><li>организаторка мероприятий</li></ul>}} [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:55, 17 мая 2026 (UTC) : Посмотрел у себя - я состою в неяавной группе [[Викиучебник:Автоподтверждённые участники]] : 4 дня стажа хочет после отдельной регистрации в Викиучебнике : {{Цитата|В случае регистрации [[w:Википедия:Единая_учётная_запись|в другом проекте]] фонда [[w:Викимедиа|Викимедиа]] и стаж, и правки отсчитываются в нашем разделе отдельно: эти статусы в разных проектах между собой не связаны.}} [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:57, 17 мая 2026 (UTC) :: Вот и настройка, что за это отвечает https://noc.wikimedia.org/wiki.php?wiki=ruwikibooks#wgAutoConfirmAge [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 18:01, 17 мая 2026 (UTC) : Пропала у вас капча? [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 19:01, 19 мая 2026 (UTC) == [[Теория чисел]] == создала [[Полка:Теория чисел]], и учебник [[Теория чисел]] но они не связаны, как их связать?— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 19:47, 15 мая 2026 (UTC) :уже связались [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 10:03, 18 мая 2026 (UTC) == [[Полка:Теория чисел]] == создала [[Полка:Теория чисел]], но она не появилась визуально внутри [[Полка:Математика]] что делать?— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 19:45, 15 мая 2026 (UTC) :Неудачно попробовал, может появится кто-то из админов. Подозреваю, что, возможно, там используются викиданные для этого, надо уточнить. [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 11:01, 16 мая 2026 (UTC) :Как-то коряво добавил, список определяется страницей [[Викиучебник:Каталог учебников/Список]]. [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 11:18, 16 мая 2026 (UTC) :: Список определяется ботом в проходке, лучше его не трогать (по возможности, конечно же)<br> Там вся суть в кэше, часто после добавления чего-либо теперь в каталоге или где-либо еще надо обновить кэш, чтобы заработало. В целом, все полки кажется появились, хотя там есть некоторые странности с тем, что некоторые полки не существуют. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 14:42, 18 мая 2026 (UTC) :::Да, там вроде сутки прошли после добавления перед моими правками, но бот не стал добавлять в список. [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 20:42, 18 мая 2026 (UTC) :::: Что странно. Надо будет мне весь код проверить, и кажется я в свое время не все там доработал. Может быть из-за этого. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 07:40, 19 мая 2026 (UTC) == Флаг бота == Прошу присвоить флаг бота [[Участник:Taratarussia's Bot|моему боту]]. Бот будет откатывать мат в статьях Викиучебника. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:39, 11 мая 2026 (UTC) : @[[Участник:Leksey|Leksey]] @[[Участник:Kylaix|Kylaix]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:39, 11 мая 2026 (UTC) :: @[[Участник:Валерий Стариков|Валерий Стариков]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:46, 11 мая 2026 (UTC) :: Я не знаю как это делать, но, наверное, разберусь. :: Но я не уверен, что такой бот нужен. Вроде нет проблемы с матом как таковой. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:33, 11 мая 2026 (UTC) ::: Я тоже так думаю, но, НО, пока он будет мат откатывать, а позже я расширю функционал. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:27, 12 мая 2026 (UTC) : Привет. Код хороший, но насколько актуально использовать это, если есть фильтры? И еще вопрос: вы его с консоли хотите использовать? Я бы рекомендовал для ботов использовать Toolforge <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 17:27, 11 мая 2026 (UTC) :: Я только знаю как запускать с консоли [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 17:53, 11 мая 2026 (UTC) ::: @[[Участник:Kylaix|Kylaix]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 17:53, 11 мая 2026 (UTC) ::: Не переживайте за это, я могу вам помочь перенести на toolforge, это не сложно. Вопрос только состоит в актуальности <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:56, 11 мая 2026 (UTC) :::: @[[Участник:Kylaix|Kylaix]] Спасибо за помощь, я готов перенести, время есть. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:29, 12 мая 2026 (UTC) ::::: @[[Участник:Leksey|Leksey]] что думаешь? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 14:14, 12 мая 2026 (UTC) :::::: @[[Участник:Kylaix|Kylaix]] Я зарегистрировался на Toolforge и подал заявку на участие. Краткое описание написал на русском языке. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 15:10, 12 мая 2026 (UTC) ::::::: А вы на нейронке пишете бота? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 16:53, 12 мая 2026 (UTC) :::::::: В общем, да. Я не умею учебники писать, а пользу проекту приносить хочу. Единственный выход — боты. Но питон я не знаю, поэтому использую нейросети. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:55, 12 мая 2026 (UTC) ::::::::: Я сам ботовод, подумаю что вам придумать в задачи. Сам хотя и знаю питон, писал @[[Участник:Kylaixbot|Kylaixbot]] при помощи ИИ <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:00, 12 мая 2026 (UTC) ::::::::: Мне кажется, проекту нужны авторы. Остальное все пока нет авторов - несущественно и не нужно. А авторы вряд ли появятся так как проект не закрывает какие-то насущные задачи людей. Или же людй вполне устраивают другие платформы и способы обучения. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 19:01, 12 мая 2026 (UTC) :::::::::: У меня нет телеграма. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:16, 13 мая 2026 (UTC) ::::::::::: Раз важны статьи, я могу заняться переводами с других проектов. Но думаю, что лучше чтобы был бот, так на фоне, если вдруг что будет, то сможет откатить. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:24, 13 мая 2026 (UTC) :::::::::::: Я не уверен, что переводы автоматические нужны. Сейчас любой сам может себе что угодно перевести одним или тремя нажатиями. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:17, 13 мая 2026 (UTC) :::::: Я думаю, что нам это не надо. Так как я не вижу пробемы вандализма с матом конкретно. :::::: Актуален вопрос отката всего вклада вандала "одним нажатием", но скрипт из Википедии у нас тут не работает. Вот его бы заставить работать. :::::: Также имеет смысл уведомлять администратора (через СО или через телеграм) о самих фактах вандализма, чтобы он пришел и откатил все. Той самой одной кнопкой. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 18:31, 12 мая 2026 (UTC) ::::::: Можно попробовать сделать бота, который будет откатывать все правки заблокированных участников. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:16, 13 мая 2026 (UTC) :::::::: Трудновато. Не всегда вклад негативный. Можно конечно по причине блокировки ловить (вандализм). Было бы круто если бы попробовали написать бота, а я гляну его, вот тогда стоит дать флаг. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:51, 13 мая 2026 (UTC) ::::::::: Опишите подробнее что хотите, и попробую что-либо сделать. С уважением, [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 18:53, 13 мая 2026 (UTC) :::::::: Я предпочту откатывать скриптом вручную, но надо чтобы он заработал. Есть JS-скрипт, который в Викиучебнике не работает.<br> А вот о необходимости прийти и откатить уведомление бы не помешало. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:15, 13 мая 2026 (UTC) ::::::::: Не могли бы вы скинуть ссылку на скрипт, я попробую оптимизировать. Возможно, дело в ограничениях в скрипте, или в расширениях которых нет в ВУ. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:27, 14 мая 2026 (UTC) :::::::::: Пожалуйста [[Участник:Leksey/common.js]] :::::::::: Вот обсуждение [[w:Служебная:GoToComment/c-Leksey-20260402155500-Вопрос_по_администрированию_Викиучебника]] [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 16:11, 14 мая 2026 (UTC) :::::::::: Вот тут я перечислил административные средства имеющиеся сейчас [[Викиучебник:Инструменты_администратора]] [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 16:17, 14 мая 2026 (UTC) :::::::::: Вот еще с такой проблемой столкнулся [[Обсуждение шаблона:Цитата#Не работает свойство "Источник"]]. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:48, 14 мая 2026 (UTC) ::::::::::: Шаблон починил, любуйтесь. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:23, 15 мая 2026 (UTC) :::::::::::: @[[Участник:Leksey|Leksey]] Вот исправный код (хотя я не знаю у меня не проверяется, у меня нет кнопок откатить:))<br> // Mass Rollback for MediaWiki<br> // Универсальная версия для Википедии, Викиучебника и других вики :::::::::::: if (typeof wkRollbackPortlet === "undefined") {<br> var wkRollbackPortlet = "p-tb";<br> } :::::::::::: // Откат одной правки<br> function rollbackOneThingWKMR(edit, rbMetadata) { :::::::::::: var userName; :::::::::::: // Для IP-участников<br> if (rbMetadata.userName === null) { :::::::::::: userName = $(edit)<br> .parents("li:first")<br> .find("a.mw-anonuserlink")<br> .first()<br> .text(); :::::::::::: } else { :::::::::::: userName = rbMetadata.userName; :::::::::::: } :::::::::::: var titleMatch = /title=([^&]+)/.exec(edit.href); :::::::::::: if (!titleMatch) {<br> console.error("Не удалось определить страницу");<br> return;<br> } :::::::::::: var pageTitle = decodeURIComponent(titleMatch[1]); :::::::::::: var params = {}; :::::::::::: if (rbMetadata.editSummary !== "") {<br> params.summary = rbMetadata.editSummary;<br> } :::::::::::: rbMetadata.api.rollback(pageTitle, userName, params) :::::::::::: .done(function () { :::::::::::: console.log("Откат:", pageTitle); :::::::::::: $(edit).after(<br> '<span style="color:green;font-weight:bold;"> [откачено]</span>'<br> ); :::::::::::: $(edit).remove(); :::::::::::: }) :::::::::::: .fail(function (code, data) { :::::::::::: console.error("Ошибка rollback:", code, data); :::::::::::: $(edit).after(<br> '<span style="color:red;font-weight:bold;"> [ошибка]</span>'<br> ); :::::::::::: });<br> } :::::::::::: // Откат всех<br> function rollbackEverythingWKMR(editSummary) { :::::::::::: if (editSummary === null) {<br> return false;<br> } :::::::::::: if (<br> mw.config.get("wgRelevantUserName") ===<br> mw.config.get("wgUserName")<br> ) { :::::::::::: if (<br> !confirm(<br> "Вы собираетесь откатить ВСЕ свои правки. Продолжить?"<br> )<br> ) {<br> return false;<br> }<br> } :::::::::::: mw.loader.using(["mediawiki.api"]).done(function () { :::::::::::: var rbMetadata = {}; :::::::::::: rbMetadata.api = new mw.Api(); :::::::::::: rbMetadata.userName =<br> mw.config.get("wgRelevantUserName"); :::::::::::: rbMetadata.editSummary = editSummary; :::::::::::: $("a[href*='action=rollback']").each(function (ind, el) { :::::::::::: rollbackOneThingWKMR(el, rbMetadata); :::::::::::: }); :::::::::::: }); :::::::::::: return false;<br> } :::::::::::: // Откат выбранных<br> function rollbackSomeThingsWKMR(editSummary) { :::::::::::: if (editSummary === null) {<br> return false;<br> } :::::::::::: mw.loader.using(["mediawiki.api"]).done(function () { :::::::::::: var rbMetadata = {}; :::::::::::: rbMetadata.api = new mw.Api(); :::::::::::: rbMetadata.userName =<br> mw.config.get("wgRelevantUserName"); :::::::::::: rbMetadata.editSummary = editSummary; :::::::::::: var rollbackList = $("input.revdelIds:checked")<br> .parents("li")<br> .find("a[href*='action=rollback']"); :::::::::::: if (rollbackList.length <= 0) { :::::::::::: mw.notify("Не выбрано ни одной правки."); :::::::::::: return;<br> } :::::::::::: rollbackList.each(function (ind, el) { :::::::::::: rollbackOneThingWKMR(el, rbMetadata); :::::::::::: }); :::::::::::: }); :::::::::::: return false;<br> } :::::::::::: // Главная часть<br> mw.loader.using([<br> "mediawiki.util",<br> "mediawiki.api"<br> ]).done(function () { :::::::::::: mw.hook('wikipage.content').add(function () { :::::::::::: // Только на странице вкладов<br> if (<br> mw.config.get("wgCanonicalSpecialPageName") !==<br> "Contributions"<br> ) {<br> return;<br> } :::::::::::: // Уже добавлено<br> if ($("#ca-rollbackeverything").length) {<br> return;<br> } :::::::::::: // Проверяем наличие rollback<br> if ($("a[href*='action=rollback']").length <= 0) { :::::::::::: console.log("Rollback ссылки не найдены"); :::::::::::: return;<br> } :::::::::::: console.log("MassRollback загружен"); :::::::::::: // Добавляем чекбоксы<br> $("ul.mw-contributions-list li").each(function () { :::::::::::: // Уже есть чекбокс<br> if ($(this).find("input.revdelIds").length) {<br> return;<br> } :::::::::::: var rollbackLink = $(this)<br> .find("a[href*='action=rollback']"); :::::::::::: if (rollbackLink.length > 0) { :::::::::::: $(this)<br> .find("a.mw-changeslist-date")<br> .first()<br> .before(<br> "<input type='checkbox' class='revdelIds' style='margin-right:5px;'>"<br> );<br> }<br> }); :::::::::::: // Кнопка Rollback all<br> mw.util.addPortletLink(<br> wkRollbackPortlet,<br> "#",<br> "Rollback all",<br> "ca-rollbackeverything",<br> "Откатить все правки"<br> ); :::::::::::: // Кнопка Rollback selected<br> mw.util.addPortletLink(<br> wkRollbackPortlet,<br> "#",<br> "Rollback selected",<br> "ca-rollbacksome",<br> "Откатить выбранные правки"<br> ); :::::::::::: // Обработка кнопки ALL<br> $("#ca-rollbackeverything").click(function (event) { :::::::::::: event.preventDefault(); :::::::::::: rollbackEverythingWKMR(<br> prompt(<br> "Введите комментарий отката:"<br> )<br> ); :::::::::::: }); :::::::::::: // Обработка кнопки SELECTED<br> $("#ca-rollbacksome").click(function (event) { :::::::::::: event.preventDefault(); :::::::::::: rollbackSomeThingsWKMR(<br> prompt(<br> "Введите комментарий отката:"<br> )<br> ); :::::::::::: }); :::::::::::: }); :::::::::::: }); [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:10, 15 мая 2026 (UTC) ::::::::::::: Блин. Мне стремно выполнять непонятный JS. Можете диф показать как-нить или объяснить что за правка была сделана. ::::::::::::: Да и идея править ИИ мне конечно не нравится, но других предложений нет. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:52, 17 мая 2026 (UTC) :::::::::::: Починилось, спасибо! [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:50, 17 мая 2026 (UTC) Прекрасно, если понадобится помощь — обращайтесь на мою СО. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 19:52, 17 мая 2026 (UTC) Если не работает, вот это попробуйте: <pre>if (typeof wkContribsCheckboxInit === "undefined") { wkContribsCheckboxInit = false; } if (typeof wkRollbackPortlet === "undefined") { wkRollbackPortlet = "p-cactions"; } function getContributionItem(el) { return $(el).closest("li, tr, .mw-contribs-list-item"); } function getRollbackLinks(scope) { return scope.find("a[href*='action=rollback']"); } function rollbackEverythingWKMR(editSummary) { if (editSummary === null) { return false; } if (mw.config.get("wgRelevantUserName") === mw.config.get("wgUserName")) { if (!confirm("You are about to roll back *all* of *your own* edits. Please note that this will be very difficult to undo. Are you *ABSOLUTELY SURE* you want to do this?")) { return false; } } mw.loader.using("mediawiki.api").done(function () { var rbMetadata = {}; rbMetadata.api = new mw.Api(); rbMetadata.userName = mw.config.get("wgRelevantUserName"); rbMetadata.ipRange = (rbMetadata.userName === null); rbMetadata.titleRegex = /title=([^&]+)/; rbMetadata.editSummary = editSummary; $("a[href*='action=rollback']").each(function (ind, el) { rollbackOneThingWKMR(el, rbMetadata); }); }); return false; } function rollbackSomeThingsWKMR(editSummary) { if (editSummary === null) { return false; } mw.loader.using("mediawiki.api").done(function () { var rbMetadata = {}; rbMetadata.api = new mw.Api(); rbMetadata.userName = mw.config.get("wgRelevantUserName"); rbMetadata.titleRegex = /title=([^&]+)/; rbMetadata.editSummary = editSummary; var rollbackList = $("input.revdelIds:checked").each(function () { var item = getContributionItem(this); item.find("a[href*='action=rollback']").each(function (ind, el) { rollbackOneThingWKMR(el, rbMetadata); }); }); if ($("input.revdelIds:checked").length <= 0) { mw.notify("You didn't select any edits that could be rolled back!"); return; } }); return false; } function rollbackOneThingWKMR(edit, rbMetadata) { var userName; var item = getContributionItem(edit); if (rbMetadata.userName === null) { userName = item.find("a.mw-anonuserlink").not(".mw-contributions-title").first().text(); } else { userName = rbMetadata.userName; } if (!userName) { return; } var params = {}; if (rbMetadata.editSummary != '') { params.summary = rbMetadata.editSummary; } var titleMatch = rbMetadata.titleRegex.exec(edit.href); if (!titleMatch) { return; } rbMetadata.api.rollback(decodeURIComponent(titleMatch[1]), userName, params).done(function () { $(edit).after("reverted"); $(edit).remove(); }); } $(document).ready(function () { if (mw.config.get("wgCanonicalSpecialPageName") == "Contributions" && $("a[href*='action=rollback']").length > 0) { mw.loader.using("mediawiki.util").done(function () { mw.util.addPortletLink(wkRollbackPortlet, '#', "Rollback all", "ca-rollbackeverything", "rollback all edits displayed here"); if (!wkContribsCheckboxInit) { if ($("input.revdelIds").length === 0) { $("a[href*='action=rollback']").each(function (ind, el) { var item = getContributionItem(el); item.find("a").first().before("<input type='checkbox' class='revdelIds'>&nbsp;"); item.find("input.revdelIds").data("index", ind); }); } else { $("input.revdelIds").each(function (ind, el) { $(el).data("index", ind); }); } wkContribsCheckboxInit = true; } mw.util.addPortletLink(wkRollbackPortlet, '#', "Rollback selected", "ca-rollbacksome", "rollback selected edits"); $("#ca-rollbackeverything").click(function (event) { event.preventDefault(); mw.loader.load("mediawiki.api"); return rollbackEverythingWKMR(prompt("Rollback all edits: Enter an edit summary, or leave blank to use the default (or hit Cancel to cancel the rollback entirely)")); }); $("#ca-rollbacksome").click(function (event) { event.preventDefault(); mw.loader.load("mediawiki.api"); return rollbackSomeThingsWKMR(prompt("Rollback selected edits: Enter an edit summary, or leave blank to use the default (or hit Cancel to cancel the rollback entirely)")); }); $("#ca-rollbacksome").data("lastSelectedIndex", -1); $("input.revdelIds").off("click").click(function (ev) { var lastSelectedRevdel = $("#ca-rollbacksome").data("lastSelectedIndex"); var newIndex = $(this).data("index"); if (ev.shiftKey && lastSelectedRevdel >= 0) { var checkboxArray = $("input.revdelIds"); var start = lastSelectedRevdel; var stop = newIndex; if (start < stop) { for (var i = start; i < stop; i++) { if (i != lastSelectedRevdel) { $(checkboxArray[i]).prop("checked", !($(checkboxArray[i]).prop("checked"))); } } } else { for (var i = start; i > stop; i--) { if (i != lastSelectedRevdel) { $(checkboxArray[i]).prop("checked", !($(checkboxArray[i]).prop("checked"))); } } } } $("#ca-rollbacksome").data("lastSelectedIndex", newIndex); }); }); } });</pre> [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 18:13, 15 мая 2026 (UTC) === Итог === * Флаг не присвоен, но зато починен скрипт и шаблон. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 15:52, 18 мая 2026 (UTC) == Изменение шаблона «Родственные проекты» == К сожалению, Викиновости полностью закрылись на всех языках решением Фонда Викимедиа. Поэтому, считаю целесообразным убрать Викиновости из шаблона, как уже сделали на https://meta.wikimedia.org/wiki/Main_Page/ru. Сам я не могу, поэтому прошу местных администраторов сделать. С уважением, СССР (обсуждение) 16:07, 8 мая 2026 (UTC) : @[[Участник:Leksey|Leksey]] сможете поправить шаблон? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:21, 13 мая 2026 (UTC) :: Сделал. И предлагаю на ты. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:20, 13 мая 2026 (UTC) == Вопрос с [[ВУ:КУ]] == Я тут ставил цель в прошлом году закончить с КУ, но кажется там у меня небольшой тупик с этим. И я вспомнил почему я хотел побыстрее с этим покончить: я хотел переделать КУ, чтобы там можно было удобнее все это просматривать и, если надо - автоматизировать. Я конечно не предлагаю вести ежедневный КУ (да и от ежемесячного тоже думал бы отказаться, так как все равно небольшие неудобства) а перейти на годовой (то есть одна страница чисто для 2026) и возможно, оставлять ее сразу на [[ВУ:КУ]]. Думаю, номинаций много не будет в скором времени, поэтому есть время об этом подумать и реализовать (если, конечно, будет согласие) <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 00:04, 3 января 2026 (UTC) Я вижу, вы тут снесли что-то 1Сное, а [[Служебная:Неиспользуемые файлы|несвободные файлы удалить забыли]].<br> Файлы Хедина в Цивилизции оформлены неправильно: должны быть переоформлены или удалены по [[ВУ:КДИ]]#10а и в. Он не является "автором или правообладателем", а "иллюстрирование" не является валидной причиной для содержания несвободного файла. А после переоформления около трети должна быть удалена по 8 пункту.<br> И, раз уж написал, примерно половину статей господина Пинчука снесли на enКнигах в прошлом году. — Ирука<sup>[[u:Iruka13|13]]</sup> 18:44, 10 января 2026 (UTC) : ээ, вроде 1сное не сносил особо, кроме каких-то 2-3 файлов, с согласия других (надо поискать в КУ). До несвободных файлов рука не добралась, там вообще желательно обсуждение.<br>Ровно так же как и с Цивой, потому что иллюстрирование в играх по КДИ, как мне кажется, у нас под вопросом. Я замечал случаи, где иллюстрирование необходимо как в руководствах Хедина, поэтому тут под вопросом. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:41, 15 января 2026 (UTC) == Категории кулинарной книги == <s>Коль ниже нас похоронили, решу немного покопаться в гробу</s>. Касательно категорий: нам надо их слегка вложить друг в друга чтобы это отображалось цивильно, да и для удобства поиска. Например: категории огурцы, помидоры и баклажан стоило бы вложить в овощи, а китайская, японская, корейская кухня в восточно-азиатские кухни и т.д. Хотелось бы услышать мнения касательно данного действа. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:42, 28 декабря 2025 (UTC) : @[[Участник:Leksey|Leksey]] @[[Участник:Heffalump1974|Heffalump1974]] @[[Участник:Erokhin|Erokhin]] <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:42, 28 декабря 2025 (UTC) :Можно на примерах показать? [[Участник:Erokhin|Erokhin]] ([[Обсуждение участника:Erokhin|обсуждение]]) 22:11, 28 декабря 2025 (UTC) :: См. [[Кулинарная книга]], спускаемся ниже до [[:Категория:Европейская кухня]] и там видим подкухни, которые я ранее посчитал европейскими. Если бы их там не было, то кухни бы догнали список ингредиентов на странице кулинарной книги по длине. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:38, 29 декабря 2025 (UTC) ::: ? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:55, 15 января 2026 (UTC) ::::Соглашусь, хорошо бы перетасовать предлагаемым образом. ::::Сам не возьмусь, пока без компьютера. [[Участник:Heffalump1974|Heffalump1974]] ([[Обсуждение участника:Heffalump1974|обсуждение]]) 14:03, 5 мая 2026 (UTC) ::::: Категоризировал, и стало теперь приятнее смотреть на не слишком длинные списки. Оценка за вами, @[[Участник:Leksey|Leksey]], @[[Участник:Heffalump1974|Heffalump1974]] :)<br> Там единственное есть дубляжи (Баклажан и баклажаны, орех и орехи) надо бы определиться в каком числе категоризировать их. Мне кажется лучше в единственном числе, потому что так будет логично. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:26, 13 мая 2026 (UTC) :::::: А куда смотреть? Я уже забыл все [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:18, 13 мая 2026 (UTC) ::::::: [[Викиучебник:Кулинарная книга]] и туда снизу. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:23, 13 мая 2026 (UTC) ::::::зависит от того, как этот объект назван в элементе викиданных, если Баклажан, то и у нас должно быть также [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:03, 17 мая 2026 (UTC) <!-- Сообщение отправил Участник:Keegan (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == <span lang="en" dir="ltr">Vote now in the 2026 U4C election</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Eligible voters are asked to participate in the 2026 [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] election. More information–including an eligibility check, voting process information, candidate information, and a link to the vote–are available on Meta at the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|2026 Election information page]]. The vote closes on 2 June 2026 at [https://zonestamp.toolforge.org/1780358400 00:00 UTC]. Please vote if your account is eligible. Results will be available by 14 June 2026. -- In cooperation with the U4C,<section end="announcement-content" /> </div> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 17:14, 27 мая 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Keegan (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == RFC about AI-generated content in Wikimedia Commons == <bdi lang="en" dir="ltr">Apologies for writing in English, please help translate this message to your language. You are invited to participate in a [[c:Commons:Requests for comment/Policy update for AI content|request for comment on Wikimedia Commons about a policy update for AI content]]. This may affect files that are uploaded to Wikimedia Commons for use on this project. Thank you. [[m:User:Codename Noreste|Codename Noreste]] ([[m:User talk:Codename Noreste|обсуждение]])</bdi> 17:11, 23 июня 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Codename Noreste@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == Размещение ссылок на контакты по вопросам права и безопасности в нижнем колонтитуле вашего вики-проекта == <section begin="Message"/> '''Контакты по вопросам права и безопасности''' Дорогие участники сообщества, Фонд Викимедиа сформировал [[wmf:Special:MyLanguage/Legal:Wikimedia Foundation Legal and Safety Contact Information|единую страницу с контактами по вопросам права и безопасности]] для размещения в нижних колонтитулах ваших проектов соответствующих ссылок на нее, чтобы обеспечить доступ к достоверной юридической информации. Это нормативное требование. Мы уже разместили эти ссылки в английском, немецком, итальянском, испанском и других проектах Википедии, и мы также скоро добавим это и в ваш вики-проект. [[m:Special:MyLanguage/Wikimedia_Foundation_Legal_and_Safety_Contacts_FAQ|Пожалуйста, ознакомьтесь более подробно на странице проекта]] и оставляйте любые комментарии в этой ветке или на [[m:Special:MyLanguage/Talk:Wikimedia Foundation Legal and Safety Contacts FAQ|странице обсуждений]]. <section end="Message"/> -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 13:30, 25 июня 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Sannita (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=30731267 --> == Request for comment (the future of Abstract Wikipedia) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies if this has not yet been translated into your wiki's language. {{int:Please-translate}} You are invited to voice your opinions in a [[:m:Requests for comment/The future of Abstract Wikipedia|request for comment about the future of Abstract Wikipedia]]. {{Int:Feedback-thanks-title}} [[:m:User:Kowal2701|Kowal2701]] ([[:m:User talk:Kowal2701|talk]]) 12:24, 24 июля 2026 (UTC) </bdi> (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:DreamRimmer@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == Переключение сервера: ваш вики-проект скоро на короткое время будет доступен в режиме «только для чтения» == <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Прочитать это сообщение на другом языке]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] [[foundation:|Фонд Викимедиа]] будет переключать трафик между своими центрами обработки данных. Это гарантирует, что Википедия и другие вики-проекты Викимедиа смогут оставаться доступными даже после катастрофы. Весь трафик будет переключен '''{{#time:j xg|2026-09-23|ru}}'''. Переключение начнётся в '''[https://zonestamp.toolforge.org/{{#time:U|2026-09-23T14:00|en}} {{#time:H:i e|2026-09-23T14:00}}]'''. К сожалению, ввиду некоторых ограничений движка [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], редактирование будет остановлено в течение этих двух переключений. Приносим свои извинения за задержку в работе. Мы работаем над тем, чтобы сократить такие работы в будущем. За 30 минут до начала переноса во всех проектах будет показан баннер-предупреждение. Этот баннер будет оставаться видимым до окончания операции. Вы можете внести вклад в [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate перевод или вычитку] этого текста баннера. '''В течение короткого промежутка времени вы сможете читать, но не сможете редактировать все вики-сайты.''' * День переключения — {{#time:l j xg Y|2026-09-23|ru}}. Оно продлится не более часа. * При попытке отредактировать или сохранить страницы в течение этого времени вы увидите сообщение об ошибке. Мы надеемся, что правки в этот период не будут потеряны, но не можем этого гарантировать. Если вы увидите сообщение об ошибке, пожалуйста, подождите, пока всё не восстановится. После этого вы сможете сохранить свою правку. Но на всякий случай мы рекомендуем вам сделать копию ваших изменений. ''Побочные эффекты'': * Фоновые задания будут выполняться замедленно, а некоторые могут быть отклонены. Красные ссылки могут также обновляться с замедлением. Если вы создаёте статью, на которую уже есть ссылки откуда-то, то такие ссылки будут оставаться красными дольше, чем обычно. Некоторые долго выполняющиеся скрипты необходимо будет остановить. * Мы ожидаем, что развёртывание кода произойдет так же, как и на любой другой неделе. Однако могут происходить некоторые зависания кода, если впоследствии этого потребует данная операция. * [[mw:Special:MyLanguage/GitLab|GitLab]] будет недоступен примерно 90 минут. При необходимости эти планы могут быть отложены. Вы можете [[wikitech:Switch_Datacenter|посмотреть расписание на wikitech.wikimedia.org]]. О любых изменениях будет сообщено в расписании. '''Пожалуйста, поделитесь этой информацией с вашим сообществом.'''</div><section end="server-switch"/> [[m:user:Trizek (WMF)|Trizek (WMF)]] 12:58, 15 сентября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Trizek (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=30513874 --> == Your feedback wanted: Remove ''(Language link added:) and similar'' edits from Special:RecentChanges == ''(Apologies for posting in English. You can help by translating it)'' Hello, I’m Danny from [[:en:w:Wikimedia_Deutschland|Wikimedia Deutschland’s]] [[m:Wikidata_For_Wikimedia_Projects|Wikidata For Wikimedia Projects]] team.<br/> We have been investigating and examining how Wikidata’s use in the [[Special:RecentChanges]] and [[Special:Watchlist]] pages can be made to be more useful, or less ‘noisy’ (fewer edits that have little value to the reader). We are currently exploring to make a change in the volume and the type of Wikidata edits that appear in these pages, and '''we need your feedback''' to help us ensure this is a positive change for the Wikis and won’t disrupt your workflows.<br/> Language links are also known as sitelinks or interlanguage links and describe when a Wikidata item is connected to a Wiki, adding it to the language dropdown tool for other connected Wikis. [[File:Types of Lang Link changes.png|x350px|frame|A variety of "Language Link" edits as seen in the Recent Changes feed]] The request for feedback is whether you support the removal of these language link edits from the Recent Changes and Watchlist feed, or would you oppose such a change and if so, why? Please share you thoughts on the dedicated '''[[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|metawiki Talk page]]'''. Further information about this change: [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|m:Wikidata_For_Wikimedia_Projects/Hide_Language_Link_edits]] Thank you for any participation or feedback you give, -- [[m:User:Danny_Benjafield_(WMDE)|User:Danny Benjafield (WMDE)]] 11:46, 25 сентября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Danny Benjafield (WMDE)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31080832 --> == Wikidata Sitelink changes in Recent Changes and Watchlist == ''(Apologies for cross-posting in English, translating it will help spread the message)'' Editors on group 1 wikis, including Wikiquote, Wikibooks, Wikiversity, Wikivoyage, and Wikisource, will no longer see notifications on [[Special:RecentChanges|Recent Changes]] and [[Special:Watchlist|Watchlist]] when a link to ''another'' language version of a page is added, removed, or changed in its Wikidata item. This change will begin on '''October 5 at 07:00 UTC''' as a two-week trial to reduce high-volume, low-value notifications and make higher-value changes easier to identify. Editors who rely on these notifications should be aware of the change and can share feedback or concerns on the [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|project]] or [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|talk page]].<br/>Please reach out if you have any questions, thank you! -- [[User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] ([[User_talk:Danny_Benjafield_(WMDE)|talk]]) sent via [[Участник:MediaWiki message delivery|MediaWiki message delivery]] ([[Обсуждение участника:MediaWiki message delivery|обсуждение]]) 12:42, 1 октября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Danny Benjafield (WMDE)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31106967 --> == Переключение сервера: ваш вики-проект скоро на короткое время будет доступен в режиме «только для чтения» == <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Прочитать это сообщение на другом языке]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] [[foundation:|Фонд Викимедиа]] будет переключать трафик между своими центрами обработки данных. Это гарантирует, что Википедия и другие вики-проекты Викимедиа смогут оставаться доступными даже в случае катастрофы. Весь трафик будет переключён '''{{#time:j xg|2026-10-28|ru}}'''. Переключение начнётся в '''[https://zonestamp.toolforge.org/{{#time:U|2026-10-28T15:00|en}} {{#time:H:i e|2026-10-28T15:00}}]'''. К сожалению, ввиду некоторых ограничений движка [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], редактирование будет остановлено в течение этих двух переключений. Приносим свои извинения за задержку. Мы стараемся сократить такие заминки в будущем. За 30 минут до начала переноса во всех проектах будет показан баннер-предупреждение. Этот баннер будет оставаться видимым до окончания работ. Вы можете помочь [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate с переводом или вычиткой] этого текста. '''В течение короткого промежутка времени вы сможете читать, но не сможете редактировать все вики-сайты.''' * День переключения — {{#time:l j xg Y|2026-10-28|ru}}. Оно продлится не более часа. * При попытке отредактировать или сохранить страницы в течение этого времени будет показано сообщение об ошибке. Мы надеемся, что правки в этот период не будут потеряны, но не можем этого гарантировать. Если вы увидите сообщение об ошибке, пожалуйста, подождите, пока всё не восстановится. После этого вы сможете сохранить свою правку. Но на всякий случай мы рекомендуем сделать копию ваших изменений. ''Побочные эффекты'': * Фоновые задания будут выполняться замедленно, а некоторые могут быть отклонены. Красные ссылки могут также обновляться с замедлением. Если вы создаёте статью, на которую уже есть ссылки, то они будут оставаться красными дольше, чем обычно. Некоторые долго выполняющиеся скрипты необходимо будет остановить. * Мы ожидаем, что развёртывание нового кода произойдёт как обычно. Однако в отдельных случаях код могут частично замораживать, если это потребуется для работ. * [[mw:Special:MyLanguage/GitLab|GitLab]] будет недоступен примерно 90 минут. При необходимости планы по переключению серверов могут быть отложены. Расписание работ [[wikitech:Switch_Datacenter|см. на wikitech.wikimedia.org]]. Там же будет сообщаться о всех изменениях. '''Пожалуйста, поделитесь этой информацией с вашим сообществом.'''</div><section end="server-switch"/> [[user:Trizek_(WMF)|Trizek_(WMF)]] 14:01, 26 октября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Trizek (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=30513874 --> ppj93xmlig1q3dm0wicsujobt93hpsn 270417 270413 2026-10-27T07:02:16Z Jcb 79968 270417 wikitext text/x-wiki {{Участник:Kylaixbot/ArchiveConfig |archive = Викиучебник:Общий форум/Архив/%(year)d |algo = old(60d) |counter = 1 }} {{Форум}} {{Архив-П |2005-2007|2008|2009-2010|2011-2012|2013|2014|2015|2016|2018|2019|2020|2021|2022|2023|2024|2025}} {{Актуально}} == Что тут == Тут есть кто живой? — [[Участник:Medyanowsky|Medyanowsky]] ([[Обсуждение участника:Medyanowsky|обсуждение]]) 08:12, 13 октября 2026 (UTC) :В чем вопрос? [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 17:07, 13 октября 2026 (UTC) :Все живы! [[Участник:Erokhin|Erokhin]] ([[Обсуждение участника:Erokhin|обсуждение]]) 03:45, 25 октября 2026 (UTC) Ну, тут Leksey и Kylain Aixter активны, я особо не редактирую, но на сообщения отвечаю. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 13:00, 14 октября 2026 (UTC) == Извинения, что задержался == Извиняюсь, что закопался, но я чет своего бота @[[Участник:Kylaixbot|Kylaixbot]] не могу починить из-за приколов Тулфорджа. Они там обновили политику venv и у меня никак не получается нормально запустить моего бота. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:52, 14 июня 2026 (UTC) :Я оказался достаточно оперативен и бот заработал [[Участник:Kylaixbot|Kylaixbot]] ([[Обсуждение участника:Kylaixbot|обсуждение]]) 14:27, 26 июля 2026 (UTC) ::Чем сейчас занят ваш бот? [[Участник:Erokhin|Erokhin]] ([[Обсуждение участника:Erokhin|обсуждение]]) 03:44, 25 октября 2026 (UTC) == Шаблон может быть улучшен == По определению, большинство учебников пишут по книгам; шаблон Книга работает здесь безупречно. По стечению обстоятельств пришлось использовать шаблон Статья. Видимо, он не точно соответствует этому шаблону в википедии: ISSN (и отчасти PMID и PMC) работает не так, как в википедии. А в [[Шаблон:Статья/Документация| документации]] не написано, что есть отличия (issn): фрагмент кода: . . . место=Москва|год=2016|номер=8|issn=0131-2618|страницы=74—79|pmid=24006620|pmc=PMC1234567}} ISSN 0131-2618, {{PMID|24006620}}</ref> его отображение: Москва, 2016. — № 8. — С. 74—79. — ISSN Шаблон:ISSN search link. — Шаблон:PMID. — Шаблон:PMC. ISSN 0131-2618, {{PMID|24006620}} + сообщения ниже красным шрифтом: Шаблон:ISSN search link (править) ... Шаблон:PMID (править) ... Шаблон:PMC (править) Если можно без больших трудозатрат устранить отличия в шаблонах от википедии, прошу Вас это сделать, как сможете. Спасибо [[Служебная:Вклад/&#126;2026-31604-77|&#126;2026-31604-77]] ([[Обсуждение участника:&#126;2026-31604-77|обс.]]) 17:46, 29 мая 2026 (UTC) : А можете где-то им воспользоваться и пингануть меня плиз? Я поправлю шаблон<br> P.s.: последний раз, судя по истории, я его и его подшаблоны импортировал в феврале 2025 года. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:50, 14 июня 2026 (UTC) == Тип блюда (P8431 course) == в элементе викиданных, связанном со страницей рецепта, можно добавить поле Тип блюда (P8431 course). в викиданных данное свойство имеет ограниченное количество значений: закуска, первое блюдо, суп, салат, рыба, второе блюдо, десерт, соус, завтрак, пирог, гарнир... после указания в поле нужного значения, рецепт будет размещен в аналогичной категории. но у нас в кулинарной книге есть аналогичные категории, только во множественном числе, например, Закуски, Вторые блюда, Салаты... в результате получается двойная категоризация и двойное отображение в кулинарной книге. есть идеи, что с этим можно сделать? переименовать в викиданных эти значения - перевести во множественное число? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 16:00, 26 мая 2026 (UTC) : Я не знаю [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:46, 28 мая 2026 (UTC) : Оооо да! Я давно заметил это и в прошлых темах предлагал к обсуждению этот вопрос. Я сторонник стандарта Викиданных, банально потому что это стандартизировано под Википедию. Но вот другие что об этом думают? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:47, 14 июня 2026 (UTC) :: Я за викиданные, но что делать - переименовывать или нет - не знаю. Есть возможсноть оставить в единственном числе в ВД, а категории иметь в множественном? [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 16:53, 15 июня 2026 (UTC) ::: Кажется нет. Это невозможно будет автоматизировать <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 00:09, 16 июня 2026 (UTC) == Полки в Кулинарной книге == можно ли в кулинарной книге сделать еще одну корневую полку и как? например, полку Кулинарные процессы, аналогично Ингредиенты — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 13:59, 26 мая 2026 (UTC) : И на этот вопрос я не знаю ответа [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:46, 28 мая 2026 (UTC) : эээээ, можно...<br> но что там будет? Примерно? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:44, 14 июня 2026 (UTC) == [[Викиучебник:Каталог учебников/Список]] == не обновляется — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 08:36, 22 мая 2026 (UTC) : тэкс, значит бот мой сломался. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 13:34, 22 мая 2026 (UTC) == [[Шаблон:К быстрому удалению|Шаблон:КБУ]] == как часто удаляются страницы, помеченные этим шаблоном? их удаляет бот или админ вручную? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 07:28, 22 мая 2026 (UTC) : Админ. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:48, 22 мая 2026 (UTC) :кто-то из админов или подводящих итоги может пройтись и удалить [https://ru.wikibooks.org/wiki/Служебная:Ссылки_сюда?target=Шаблон%3AК+быстрому+удалению&namespace=&limit=500 статьи с данным шаблоном] в основном пространстве и пространстве полок? частично это нужно, чтобы переименовать другие страницы + пустые страницы/полки. [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 08:25, 23 мая 2026 (UTC) :: Ну, я не админ, надо Лексея пингануть @[[Участник:Leksey|Leksey]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 14:17, 24 мая 2026 (UTC) :: Удалил! :: @[[Участник:Kylaix|Kylaix]] посмотри, плиз, почему в категорию включило статьи, где только ссылка на шаблон. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 21:49, 25 мая 2026 (UTC) :::не могу переименовать [[Введение в дифференциальные уравнения]] в Дифференциальные уравнения - "Переименование невозможно: страница с таким именем уже существует". но я не нашла такой страницы [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:56, 28 мая 2026 (UTC) :::: Она в перенаправлении <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 17:12, 28 мая 2026 (UTC) ::::: [[Дифференциальные уравнения]] удалена и нет на этом месте перенаправления [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:42, 28 мая 2026 (UTC) ::::: там СО была и она мешала [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:44, 28 мая 2026 (UTC) :::: переименовал [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:45, 28 мая 2026 (UTC) :::аналогично не могу переименовать [[Постулат Бертрана]] в Теория чисел/Постулат Бертрана [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:57, 28 мая 2026 (UTC) :::: переименовал [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:44, 28 мая 2026 (UTC) ::: @[[Участник:Leksey|Leksey]] Если в Ссылки сюда нажать кнопки Скрыть ссылки и Скрыть перенаправления , то будет показываться только включения, то есть только страницы которые надо удалить. Вот ссылка: https://ru.wikibooks.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D0%B8_%D1%81%D1%8E%D0%B4%D0%B0?target=%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%3A%D0%9A+%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%BC%D1%83+%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D1%8E&namespace=&hidelinks=1&hideredirs=1&limit=50 [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:11, 29 мая 2026 (UTC) == Сколько уровней полок поддерживается? == например, в [[Викиучебник:Каталог учебников/Список]]? Сейчас только два уровня, например, Языки - Языки Европы. А может быть 3-й, 4-й и т.д уровни? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 17:13, 21 мая 2026 (UTC) : По идее - да, там вроде бесконечная вложенность, главное только правильно оформлять полки. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:50, 14 июня 2026 (UTC) == [[Полка:Компьютеры]] == все доп. полки почему-то задублированы, например, Программирование фигурирует дважды — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:50, 21 мая 2026 (UTC) :исправила через Править код [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 10:22, 21 мая 2026 (UTC) : О, спасибо что убрали. Ранее они просто добавлялись в ручную. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 13:36, 22 мая 2026 (UTC) == Не обновляются Полки == 1. Дополнительные полки: [[Полка:Теория чисел]], на ней лежит учебник [https://ru.wikibooks.org/wiki/Теория_чисел Теория чисел], но в учебнике в шаблоне Название учебника указана категория не Теория чисел, а Математика (я ее сделала доп. полкой на основной полке Формальные науки). почему учебник таки находится на данной полке? из-за того, что у него внизу указана категория Теория чисел? аналогично [[Полка:Дифференциальные уравнения]], [[Полка:Математический анализ]], [[Полка:Алгебра]], [[Полка:Занимательная математика]]. 2. Основные полки: [[Полка:Компьютеры]], [[Полка:Естественные науки]], [[Полка:Языки]], [[Полка:Досуг]], [[Полка:Техника]], [[Полка:Гуманитарные науки]] существует ли бот, который обновляет полки? уже прошло несколько дней, но полки не обновились, кнопка Очистить кэш не помогает — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 07:55, 21 мая 2026 (UTC) == [[Теория музыки для математиков]] == в шаблоне Название учебника две Категории - Музыка, Математика но на полке [[Полка:Математика|Математика]] он не появляется почему? потому что это Основная полка? нужно указать вместо нее Дополнительную полку в шаблоне? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:24, 20 мая 2026 (UTC) : Последнее верно. Это основная полка а требуется дополнительная полка. Я правда не знаю как ее можно было назвать, но раздел бы стоило создать. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:11, 20 мая 2026 (UTC) == КУ == [[Викиучебник:К удалению/Май 2026]] Прошу всех обратить внимание. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:31, 20 мая 2026 (UTC) :создала в вики страницу [[w:Биографический_метод|Биографический метод]] :может, их связать? и поставить в учебнике шаблон, что это заготовка. может, кто заинтересуется и начнет наполнять учебник? [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:36, 20 мая 2026 (UTC) == Полка и категория == чем отличается [[Полка:Математика]] от [https://ru.wikibooks.org/wiki/Категория:Математика Категория:Математика]? зачем нужны полки? почему не ограничиться только категориями? например, сгласно полкам учебных пособий 2 шт, согласно категориям находится еще 100 шт учебных пособий ... — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:26, 19 мая 2026 (UTC) : Категорию проставляют в статьях, на полке же список статей. К тому же, зачем традиции ломать? [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:32, 20 мая 2026 (UTC) ::выглядит, как дублирующий инструмент ::тем паче, что рецепты на категориях строятся [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:21, 20 мая 2026 (UTC) ::: Иронично что вы оба правы. Категории, по сути, помогают работе шаблонов и модулей для организации каталога учебников. А каталог учебников кажется сейчас наиболее удобным средством для поиска нужных книг. Было бы круто не использовать категории, но к сожалению иначе организовать полки было бы невозможно или, как минимум, труднее на порядок. Ну и да, + это еще и дань традициям - в Википедии, к примеру, они до сих пор используются. ::: Кстати, напоминаю, что категории в статьях проставляются через {{tl|Название учебника}} и для рецептов через {{tl|Рецепт}}. Касательно разницы в полках и категориях: просто те 98 учебников еще не обработаны через эти шаблоны. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:08, 20 мая 2026 (UTC) == Страницы учебника на полке == на полке [[Полка:Математика|Математика]] есть полка [[Полка:Теория чисел|Теория чисел]] на ней лежит учебник [[Теория чисел]] и страница из учебника [[Теория чисел/Постулат Бертрана]] что не есть правильно - на полке должны быть только учебники аналогично на полке [[Полка:Дифференциальные уравнения|Дифференциальные уравнения]] как удалить страницы учебника с полки? — [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 07:03, 19 мая 2026 (UTC) : Привет.<br> Я пока не знаю причину, ищу ошибку в шаблонах. Тем не менее, большая просьба либо создавать эти учебники уже на существующих полках, либо же переименовать их так, чтобы не совпадали с названием полки. Это может быть одной из причин. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 07:40, 19 мая 2026 (UTC) :: Подтверждаю. Учебники не стоит называть одинаково с названием полки. Более того, не стоит создавать отдельные полки для каждого учебника. Я оставил лишь полку с теорией чисел, учебник про диффуры перенес в полку матанализа. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 08:01, 19 мая 2026 (UTC) :::спасибо! :::но дифференециальные уравнения - это не матан, это отдельный [[w:Разделы_математики#Математика_как_учебная_дисциплина|учебный раздел математики]] :::поэтому для него была создана своя полка :::иначе можно обойтись вообще без полок и все учебники размещать на полке Математика [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:05, 19 мая 2026 (UTC) :::: Ну, я понимаю что его в целом выделяют, но тут проблема именно Викиучебника. У нас пока* мало книг и имеет смысл их пока отводить в гораздо более крупные разделы, чем это делается в науке.<br> <nowiki>*</nowiki>надеюсь все же мы сможем хотя бы перевести достаточное количество книг, а еще лучше написать сами в ближайшее время. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 09:27, 19 мая 2026 (UTC) :::::тогда можно сделать полку Другие разделы :::::в нее отнести все, что не Алгебра и не Геометрия [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 09:30, 19 мая 2026 (UTC) :::::: Хорошо, сделаю. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 09:41, 19 мая 2026 (UTC) :::::::я все перенесла в Алгебру/Геометрию [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 13:05, 19 мая 2026 (UTC) :::::::ненужные страницы пометила КБУ в пространствах - Основное, Полка [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 13:55, 19 мая 2026 (UTC) == Как привязать учебник к другой полке? == например, [[Дифференциальные уравнения]] к полке [[Полка:Дифференциальные уравнения|Дифференциальные уравнения]]— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 17:46, 17 мая 2026 (UTC) : @[[Участник:Kylaix|Kylaix]] ответишь? [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:50, 17 мая 2026 (UTC) :или достаточно в учебнике в шаблоне "Название учебника" указать нужные значения в Категория? и бот привяжет учебник, куда нужно? в какой время отрабатывает бот? явно, сразу не после правки Категория [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 10:02, 18 мая 2026 (UTC) :: Да да да, в категорию просто вписываете полку и бот пройдет (один раз в день делает проходку) и ваша книга попадет на полку. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 14:44, 18 мая 2026 (UTC) == CAPTCHA == при сохранении правок возникает: CAPTCHA: Для редактирования страницы, пожалуйста, введите буквы, которые видны на изображении ниже это из-за того, что я новичок? или так всегда будет?— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 16:29, 17 мая 2026 (UTC) : Никогда такого не видел. Конечно пройдет. : А можете кинуть на почту скриншот leksey@ya.ru<br> Интересно посмотреть даже. : Я посмотрю, может вам можно статус подкрутить руками, но вроде я такого не видел. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:49, 17 мая 2026 (UTC) : Попытался поменять вам группу, но все что мне дает это. Наверное, когда вы попадете в группу "Автоподтвержденные", то отпустит. Как это работает - я не знаю. У вас же по идее глобальный аккаунт и специально в Учебнике вы вчера условно не регились? : {{Цитата|Группы, которые вы можете изменять<ul><li>исключение из IP-блокировок</li><li>организаторка мероприятий</li></ul>}} [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:55, 17 мая 2026 (UTC) : Посмотрел у себя - я состою в неяавной группе [[Викиучебник:Автоподтверждённые участники]] : 4 дня стажа хочет после отдельной регистрации в Викиучебнике : {{Цитата|В случае регистрации [[w:Википедия:Единая_учётная_запись|в другом проекте]] фонда [[w:Викимедиа|Викимедиа]] и стаж, и правки отсчитываются в нашем разделе отдельно: эти статусы в разных проектах между собой не связаны.}} [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:57, 17 мая 2026 (UTC) :: Вот и настройка, что за это отвечает https://noc.wikimedia.org/wiki.php?wiki=ruwikibooks#wgAutoConfirmAge [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 18:01, 17 мая 2026 (UTC) : Пропала у вас капча? [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 19:01, 19 мая 2026 (UTC) == [[Теория чисел]] == создала [[Полка:Теория чисел]], и учебник [[Теория чисел]] но они не связаны, как их связать?— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 19:47, 15 мая 2026 (UTC) :уже связались [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 10:03, 18 мая 2026 (UTC) == [[Полка:Теория чисел]] == создала [[Полка:Теория чисел]], но она не появилась визуально внутри [[Полка:Математика]] что делать?— [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 19:45, 15 мая 2026 (UTC) :Неудачно попробовал, может появится кто-то из админов. Подозреваю, что, возможно, там используются викиданные для этого, надо уточнить. [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 11:01, 16 мая 2026 (UTC) :Как-то коряво добавил, список определяется страницей [[Викиучебник:Каталог учебников/Список]]. [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 11:18, 16 мая 2026 (UTC) :: Список определяется ботом в проходке, лучше его не трогать (по возможности, конечно же)<br> Там вся суть в кэше, часто после добавления чего-либо теперь в каталоге или где-либо еще надо обновить кэш, чтобы заработало. В целом, все полки кажется появились, хотя там есть некоторые странности с тем, что некоторые полки не существуют. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 14:42, 18 мая 2026 (UTC) :::Да, там вроде сутки прошли после добавления перед моими правками, но бот не стал добавлять в список. [[Участник:Def2010|Def2010]] ([[Обсуждение участника:Def2010|обсуждение]]) 20:42, 18 мая 2026 (UTC) :::: Что странно. Надо будет мне весь код проверить, и кажется я в свое время не все там доработал. Может быть из-за этого. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 07:40, 19 мая 2026 (UTC) == Флаг бота == Прошу присвоить флаг бота [[Участник:Taratarussia's Bot|моему боту]]. Бот будет откатывать мат в статьях Викиучебника. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:39, 11 мая 2026 (UTC) : @[[Участник:Leksey|Leksey]] @[[Участник:Kylaix|Kylaix]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:39, 11 мая 2026 (UTC) :: @[[Участник:Валерий Стариков|Валерий Стариков]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:46, 11 мая 2026 (UTC) :: Я не знаю как это делать, но, наверное, разберусь. :: Но я не уверен, что такой бот нужен. Вроде нет проблемы с матом как таковой. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 22:33, 11 мая 2026 (UTC) ::: Я тоже так думаю, но, НО, пока он будет мат откатывать, а позже я расширю функционал. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:27, 12 мая 2026 (UTC) : Привет. Код хороший, но насколько актуально использовать это, если есть фильтры? И еще вопрос: вы его с консоли хотите использовать? Я бы рекомендовал для ботов использовать Toolforge <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 17:27, 11 мая 2026 (UTC) :: Я только знаю как запускать с консоли [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 17:53, 11 мая 2026 (UTC) ::: @[[Участник:Kylaix|Kylaix]] [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 17:53, 11 мая 2026 (UTC) ::: Не переживайте за это, я могу вам помочь перенести на toolforge, это не сложно. Вопрос только состоит в актуальности <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:56, 11 мая 2026 (UTC) :::: @[[Участник:Kylaix|Kylaix]] Спасибо за помощь, я готов перенести, время есть. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:29, 12 мая 2026 (UTC) ::::: @[[Участник:Leksey|Leksey]] что думаешь? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 14:14, 12 мая 2026 (UTC) :::::: @[[Участник:Kylaix|Kylaix]] Я зарегистрировался на Toolforge и подал заявку на участие. Краткое описание написал на русском языке. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 15:10, 12 мая 2026 (UTC) ::::::: А вы на нейронке пишете бота? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 16:53, 12 мая 2026 (UTC) :::::::: В общем, да. Я не умею учебники писать, а пользу проекту приносить хочу. Единственный выход — боты. Но питон я не знаю, поэтому использую нейросети. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 16:55, 12 мая 2026 (UTC) ::::::::: Я сам ботовод, подумаю что вам придумать в задачи. Сам хотя и знаю питон, писал @[[Участник:Kylaixbot|Kylaixbot]] при помощи ИИ <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:00, 12 мая 2026 (UTC) ::::::::: Мне кажется, проекту нужны авторы. Остальное все пока нет авторов - несущественно и не нужно. А авторы вряд ли появятся так как проект не закрывает какие-то насущные задачи людей. Или же людй вполне устраивают другие платформы и способы обучения. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 19:01, 12 мая 2026 (UTC) :::::::::: У меня нет телеграма. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:16, 13 мая 2026 (UTC) ::::::::::: Раз важны статьи, я могу заняться переводами с других проектов. Но думаю, что лучше чтобы был бот, так на фоне, если вдруг что будет, то сможет откатить. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:24, 13 мая 2026 (UTC) :::::::::::: Я не уверен, что переводы автоматические нужны. Сейчас любой сам может себе что угодно перевести одним или тремя нажатиями. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:17, 13 мая 2026 (UTC) :::::: Я думаю, что нам это не надо. Так как я не вижу пробемы вандализма с матом конкретно. :::::: Актуален вопрос отката всего вклада вандала "одним нажатием", но скрипт из Википедии у нас тут не работает. Вот его бы заставить работать. :::::: Также имеет смысл уведомлять администратора (через СО или через телеграм) о самих фактах вандализма, чтобы он пришел и откатил все. Той самой одной кнопкой. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 18:31, 12 мая 2026 (UTC) ::::::: Можно попробовать сделать бота, который будет откатывать все правки заблокированных участников. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:16, 13 мая 2026 (UTC) :::::::: Трудновато. Не всегда вклад негативный. Можно конечно по причине блокировки ловить (вандализм). Было бы круто если бы попробовали написать бота, а я гляну его, вот тогда стоит дать флаг. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:51, 13 мая 2026 (UTC) ::::::::: Опишите подробнее что хотите, и попробую что-либо сделать. С уважением, [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 18:53, 13 мая 2026 (UTC) :::::::: Я предпочту откатывать скриптом вручную, но надо чтобы он заработал. Есть JS-скрипт, который в Викиучебнике не работает.<br> А вот о необходимости прийти и откатить уведомление бы не помешало. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:15, 13 мая 2026 (UTC) ::::::::: Не могли бы вы скинуть ссылку на скрипт, я попробую оптимизировать. Возможно, дело в ограничениях в скрипте, или в расширениях которых нет в ВУ. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:27, 14 мая 2026 (UTC) :::::::::: Пожалуйста [[Участник:Leksey/common.js]] :::::::::: Вот обсуждение [[w:Служебная:GoToComment/c-Leksey-20260402155500-Вопрос_по_администрированию_Викиучебника]] [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 16:11, 14 мая 2026 (UTC) :::::::::: Вот тут я перечислил административные средства имеющиеся сейчас [[Викиучебник:Инструменты_администратора]] [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 16:17, 14 мая 2026 (UTC) :::::::::: Вот еще с такой проблемой столкнулся [[Обсуждение шаблона:Цитата#Не работает свойство "Источник"]]. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:48, 14 мая 2026 (UTC) ::::::::::: Шаблон починил, любуйтесь. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 11:23, 15 мая 2026 (UTC) :::::::::::: @[[Участник:Leksey|Leksey]] Вот исправный код (хотя я не знаю у меня не проверяется, у меня нет кнопок откатить:))<br> // Mass Rollback for MediaWiki<br> // Универсальная версия для Википедии, Викиучебника и других вики :::::::::::: if (typeof wkRollbackPortlet === "undefined") {<br> var wkRollbackPortlet = "p-tb";<br> } :::::::::::: // Откат одной правки<br> function rollbackOneThingWKMR(edit, rbMetadata) { :::::::::::: var userName; :::::::::::: // Для IP-участников<br> if (rbMetadata.userName === null) { :::::::::::: userName = $(edit)<br> .parents("li:first")<br> .find("a.mw-anonuserlink")<br> .first()<br> .text(); :::::::::::: } else { :::::::::::: userName = rbMetadata.userName; :::::::::::: } :::::::::::: var titleMatch = /title=([^&]+)/.exec(edit.href); :::::::::::: if (!titleMatch) {<br> console.error("Не удалось определить страницу");<br> return;<br> } :::::::::::: var pageTitle = decodeURIComponent(titleMatch[1]); :::::::::::: var params = {}; :::::::::::: if (rbMetadata.editSummary !== "") {<br> params.summary = rbMetadata.editSummary;<br> } :::::::::::: rbMetadata.api.rollback(pageTitle, userName, params) :::::::::::: .done(function () { :::::::::::: console.log("Откат:", pageTitle); :::::::::::: $(edit).after(<br> '<span style="color:green;font-weight:bold;"> [откачено]</span>'<br> ); :::::::::::: $(edit).remove(); :::::::::::: }) :::::::::::: .fail(function (code, data) { :::::::::::: console.error("Ошибка rollback:", code, data); :::::::::::: $(edit).after(<br> '<span style="color:red;font-weight:bold;"> [ошибка]</span>'<br> ); :::::::::::: });<br> } :::::::::::: // Откат всех<br> function rollbackEverythingWKMR(editSummary) { :::::::::::: if (editSummary === null) {<br> return false;<br> } :::::::::::: if (<br> mw.config.get("wgRelevantUserName") ===<br> mw.config.get("wgUserName")<br> ) { :::::::::::: if (<br> !confirm(<br> "Вы собираетесь откатить ВСЕ свои правки. Продолжить?"<br> )<br> ) {<br> return false;<br> }<br> } :::::::::::: mw.loader.using(["mediawiki.api"]).done(function () { :::::::::::: var rbMetadata = {}; :::::::::::: rbMetadata.api = new mw.Api(); :::::::::::: rbMetadata.userName =<br> mw.config.get("wgRelevantUserName"); :::::::::::: rbMetadata.editSummary = editSummary; :::::::::::: $("a[href*='action=rollback']").each(function (ind, el) { :::::::::::: rollbackOneThingWKMR(el, rbMetadata); :::::::::::: }); :::::::::::: }); :::::::::::: return false;<br> } :::::::::::: // Откат выбранных<br> function rollbackSomeThingsWKMR(editSummary) { :::::::::::: if (editSummary === null) {<br> return false;<br> } :::::::::::: mw.loader.using(["mediawiki.api"]).done(function () { :::::::::::: var rbMetadata = {}; :::::::::::: rbMetadata.api = new mw.Api(); :::::::::::: rbMetadata.userName =<br> mw.config.get("wgRelevantUserName"); :::::::::::: rbMetadata.editSummary = editSummary; :::::::::::: var rollbackList = $("input.revdelIds:checked")<br> .parents("li")<br> .find("a[href*='action=rollback']"); :::::::::::: if (rollbackList.length <= 0) { :::::::::::: mw.notify("Не выбрано ни одной правки."); :::::::::::: return;<br> } :::::::::::: rollbackList.each(function (ind, el) { :::::::::::: rollbackOneThingWKMR(el, rbMetadata); :::::::::::: }); :::::::::::: }); :::::::::::: return false;<br> } :::::::::::: // Главная часть<br> mw.loader.using([<br> "mediawiki.util",<br> "mediawiki.api"<br> ]).done(function () { :::::::::::: mw.hook('wikipage.content').add(function () { :::::::::::: // Только на странице вкладов<br> if (<br> mw.config.get("wgCanonicalSpecialPageName") !==<br> "Contributions"<br> ) {<br> return;<br> } :::::::::::: // Уже добавлено<br> if ($("#ca-rollbackeverything").length) {<br> return;<br> } :::::::::::: // Проверяем наличие rollback<br> if ($("a[href*='action=rollback']").length <= 0) { :::::::::::: console.log("Rollback ссылки не найдены"); :::::::::::: return;<br> } :::::::::::: console.log("MassRollback загружен"); :::::::::::: // Добавляем чекбоксы<br> $("ul.mw-contributions-list li").each(function () { :::::::::::: // Уже есть чекбокс<br> if ($(this).find("input.revdelIds").length) {<br> return;<br> } :::::::::::: var rollbackLink = $(this)<br> .find("a[href*='action=rollback']"); :::::::::::: if (rollbackLink.length > 0) { :::::::::::: $(this)<br> .find("a.mw-changeslist-date")<br> .first()<br> .before(<br> "<input type='checkbox' class='revdelIds' style='margin-right:5px;'>"<br> );<br> }<br> }); :::::::::::: // Кнопка Rollback all<br> mw.util.addPortletLink(<br> wkRollbackPortlet,<br> "#",<br> "Rollback all",<br> "ca-rollbackeverything",<br> "Откатить все правки"<br> ); :::::::::::: // Кнопка Rollback selected<br> mw.util.addPortletLink(<br> wkRollbackPortlet,<br> "#",<br> "Rollback selected",<br> "ca-rollbacksome",<br> "Откатить выбранные правки"<br> ); :::::::::::: // Обработка кнопки ALL<br> $("#ca-rollbackeverything").click(function (event) { :::::::::::: event.preventDefault(); :::::::::::: rollbackEverythingWKMR(<br> prompt(<br> "Введите комментарий отката:"<br> )<br> ); :::::::::::: }); :::::::::::: // Обработка кнопки SELECTED<br> $("#ca-rollbacksome").click(function (event) { :::::::::::: event.preventDefault(); :::::::::::: rollbackSomeThingsWKMR(<br> prompt(<br> "Введите комментарий отката:"<br> )<br> ); :::::::::::: }); :::::::::::: }); :::::::::::: }); [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 12:10, 15 мая 2026 (UTC) ::::::::::::: Блин. Мне стремно выполнять непонятный JS. Можете диф показать как-нить или объяснить что за правка была сделана. ::::::::::::: Да и идея править ИИ мне конечно не нравится, но других предложений нет. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:52, 17 мая 2026 (UTC) :::::::::::: Починилось, спасибо! [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 17:50, 17 мая 2026 (UTC) Прекрасно, если понадобится помощь — обращайтесь на мою СО. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 19:52, 17 мая 2026 (UTC) Если не работает, вот это попробуйте: <pre>if (typeof wkContribsCheckboxInit === "undefined") { wkContribsCheckboxInit = false; } if (typeof wkRollbackPortlet === "undefined") { wkRollbackPortlet = "p-cactions"; } function getContributionItem(el) { return $(el).closest("li, tr, .mw-contribs-list-item"); } function getRollbackLinks(scope) { return scope.find("a[href*='action=rollback']"); } function rollbackEverythingWKMR(editSummary) { if (editSummary === null) { return false; } if (mw.config.get("wgRelevantUserName") === mw.config.get("wgUserName")) { if (!confirm("You are about to roll back *all* of *your own* edits. Please note that this will be very difficult to undo. Are you *ABSOLUTELY SURE* you want to do this?")) { return false; } } mw.loader.using("mediawiki.api").done(function () { var rbMetadata = {}; rbMetadata.api = new mw.Api(); rbMetadata.userName = mw.config.get("wgRelevantUserName"); rbMetadata.ipRange = (rbMetadata.userName === null); rbMetadata.titleRegex = /title=([^&]+)/; rbMetadata.editSummary = editSummary; $("a[href*='action=rollback']").each(function (ind, el) { rollbackOneThingWKMR(el, rbMetadata); }); }); return false; } function rollbackSomeThingsWKMR(editSummary) { if (editSummary === null) { return false; } mw.loader.using("mediawiki.api").done(function () { var rbMetadata = {}; rbMetadata.api = new mw.Api(); rbMetadata.userName = mw.config.get("wgRelevantUserName"); rbMetadata.titleRegex = /title=([^&]+)/; rbMetadata.editSummary = editSummary; var rollbackList = $("input.revdelIds:checked").each(function () { var item = getContributionItem(this); item.find("a[href*='action=rollback']").each(function (ind, el) { rollbackOneThingWKMR(el, rbMetadata); }); }); if ($("input.revdelIds:checked").length <= 0) { mw.notify("You didn't select any edits that could be rolled back!"); return; } }); return false; } function rollbackOneThingWKMR(edit, rbMetadata) { var userName; var item = getContributionItem(edit); if (rbMetadata.userName === null) { userName = item.find("a.mw-anonuserlink").not(".mw-contributions-title").first().text(); } else { userName = rbMetadata.userName; } if (!userName) { return; } var params = {}; if (rbMetadata.editSummary != '') { params.summary = rbMetadata.editSummary; } var titleMatch = rbMetadata.titleRegex.exec(edit.href); if (!titleMatch) { return; } rbMetadata.api.rollback(decodeURIComponent(titleMatch[1]), userName, params).done(function () { $(edit).after("reverted"); $(edit).remove(); }); } $(document).ready(function () { if (mw.config.get("wgCanonicalSpecialPageName") == "Contributions" && $("a[href*='action=rollback']").length > 0) { mw.loader.using("mediawiki.util").done(function () { mw.util.addPortletLink(wkRollbackPortlet, '#', "Rollback all", "ca-rollbackeverything", "rollback all edits displayed here"); if (!wkContribsCheckboxInit) { if ($("input.revdelIds").length === 0) { $("a[href*='action=rollback']").each(function (ind, el) { var item = getContributionItem(el); item.find("a").first().before("<input type='checkbox' class='revdelIds'>&nbsp;"); item.find("input.revdelIds").data("index", ind); }); } else { $("input.revdelIds").each(function (ind, el) { $(el).data("index", ind); }); } wkContribsCheckboxInit = true; } mw.util.addPortletLink(wkRollbackPortlet, '#', "Rollback selected", "ca-rollbacksome", "rollback selected edits"); $("#ca-rollbackeverything").click(function (event) { event.preventDefault(); mw.loader.load("mediawiki.api"); return rollbackEverythingWKMR(prompt("Rollback all edits: Enter an edit summary, or leave blank to use the default (or hit Cancel to cancel the rollback entirely)")); }); $("#ca-rollbacksome").click(function (event) { event.preventDefault(); mw.loader.load("mediawiki.api"); return rollbackSomeThingsWKMR(prompt("Rollback selected edits: Enter an edit summary, or leave blank to use the default (or hit Cancel to cancel the rollback entirely)")); }); $("#ca-rollbacksome").data("lastSelectedIndex", -1); $("input.revdelIds").off("click").click(function (ev) { var lastSelectedRevdel = $("#ca-rollbacksome").data("lastSelectedIndex"); var newIndex = $(this).data("index"); if (ev.shiftKey && lastSelectedRevdel >= 0) { var checkboxArray = $("input.revdelIds"); var start = lastSelectedRevdel; var stop = newIndex; if (start < stop) { for (var i = start; i < stop; i++) { if (i != lastSelectedRevdel) { $(checkboxArray[i]).prop("checked", !($(checkboxArray[i]).prop("checked"))); } } } else { for (var i = start; i > stop; i--) { if (i != lastSelectedRevdel) { $(checkboxArray[i]).prop("checked", !($(checkboxArray[i]).prop("checked"))); } } } } $("#ca-rollbacksome").data("lastSelectedIndex", newIndex); }); }); } });</pre> [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 18:13, 15 мая 2026 (UTC) === Итог === * Флаг не присвоен, но зато починен скрипт и шаблон. [[Участник:Taratarussia|СССР]] ([[Обсуждение участника:Taratarussia|обсуждение]]) 15:52, 18 мая 2026 (UTC) == Изменение шаблона «Родственные проекты» == К сожалению, Викиновости полностью закрылись на всех языках решением Фонда Викимедиа. Поэтому, считаю целесообразным убрать Викиновости из шаблона, как уже сделали на https://meta.wikimedia.org/wiki/Main_Page/ru. Сам я не могу, поэтому прошу местных администраторов сделать. С уважением, СССР (обсуждение) 16:07, 8 мая 2026 (UTC) : @[[Участник:Leksey|Leksey]] сможете поправить шаблон? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:21, 13 мая 2026 (UTC) :: Сделал. И предлагаю на ты. [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:20, 13 мая 2026 (UTC) == Вопрос с [[ВУ:КУ]] == Я тут ставил цель в прошлом году закончить с КУ, но кажется там у меня небольшой тупик с этим. И я вспомнил почему я хотел побыстрее с этим покончить: я хотел переделать КУ, чтобы там можно было удобнее все это просматривать и, если надо - автоматизировать. Я конечно не предлагаю вести ежедневный КУ (да и от ежемесячного тоже думал бы отказаться, так как все равно небольшие неудобства) а перейти на годовой (то есть одна страница чисто для 2026) и возможно, оставлять ее сразу на [[ВУ:КУ]]. Думаю, номинаций много не будет в скором времени, поэтому есть время об этом подумать и реализовать (если, конечно, будет согласие) <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 00:04, 3 января 2026 (UTC) Я вижу, вы тут снесли что-то 1Сное, а [[Служебная:Неиспользуемые файлы|несвободные файлы удалить забыли]].<br> Файлы Хедина в Цивилизции оформлены неправильно: должны быть переоформлены или удалены по [[ВУ:КДИ]]#10а и в. Он не является "автором или правообладателем", а "иллюстрирование" не является валидной причиной для содержания несвободного файла. А после переоформления около трети должна быть удалена по 8 пункту.<br> И, раз уж написал, примерно половину статей господина Пинчука снесли на enКнигах в прошлом году. — Ирука<sup>[[u:Iruka13|13]]</sup> 18:44, 10 января 2026 (UTC) : ээ, вроде 1сное не сносил особо, кроме каких-то 2-3 файлов, с согласия других (надо поискать в КУ). До несвободных файлов рука не добралась, там вообще желательно обсуждение.<br>Ровно так же как и с Цивой, потому что иллюстрирование в играх по КДИ, как мне кажется, у нас под вопросом. Я замечал случаи, где иллюстрирование необходимо как в руководствах Хедина, поэтому тут под вопросом. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:41, 15 января 2026 (UTC) == Категории кулинарной книги == <s>Коль ниже нас похоронили, решу немного покопаться в гробу</s>. Касательно категорий: нам надо их слегка вложить друг в друга чтобы это отображалось цивильно, да и для удобства поиска. Например: категории огурцы, помидоры и баклажан стоило бы вложить в овощи, а китайская, японская, корейская кухня в восточно-азиатские кухни и т.д. Хотелось бы услышать мнения касательно данного действа. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:42, 28 декабря 2025 (UTC) : @[[Участник:Leksey|Leksey]] @[[Участник:Heffalump1974|Heffalump1974]] @[[Участник:Erokhin|Erokhin]] <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:42, 28 декабря 2025 (UTC) :Можно на примерах показать? [[Участник:Erokhin|Erokhin]] ([[Обсуждение участника:Erokhin|обсуждение]]) 22:11, 28 декабря 2025 (UTC) :: См. [[Кулинарная книга]], спускаемся ниже до [[:Категория:Европейская кухня]] и там видим подкухни, которые я ранее посчитал европейскими. Если бы их там не было, то кухни бы догнали список ингредиентов на странице кулинарной книги по длине. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:38, 29 декабря 2025 (UTC) ::: ? <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 15:55, 15 января 2026 (UTC) ::::Соглашусь, хорошо бы перетасовать предлагаемым образом. ::::Сам не возьмусь, пока без компьютера. [[Участник:Heffalump1974|Heffalump1974]] ([[Обсуждение участника:Heffalump1974|обсуждение]]) 14:03, 5 мая 2026 (UTC) ::::: Категоризировал, и стало теперь приятнее смотреть на не слишком длинные списки. Оценка за вами, @[[Участник:Leksey|Leksey]], @[[Участник:Heffalump1974|Heffalump1974]] :)<br> Там единственное есть дубляжи (Баклажан и баклажаны, орех и орехи) надо бы определиться в каком числе категоризировать их. Мне кажется лучше в единственном числе, потому что так будет логично. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 19:26, 13 мая 2026 (UTC) :::::: А куда смотреть? Я уже забыл все [[Участник:Leksey|Leksey]] ([[Обсуждение участника:Leksey|обсуждение]]) 20:18, 13 мая 2026 (UTC) ::::::: [[Викиучебник:Кулинарная книга]] и туда снизу. <span style="font-family:TimesNewRoman;">[[Участник:Kylaix|'''''Kylain Aixter''''' ]] ([[Обсуждение участника:Kylaix|СО]]) </span> 20:23, 13 мая 2026 (UTC) ::::::зависит от того, как этот объект назван в элементе викиданных, если Баклажан, то и у нас должно быть также [[Участник:AllaBuraya|AllaBuraya]] ([[Обсуждение участника:AllaBuraya|обсуждение]]) 18:03, 17 мая 2026 (UTC) <!-- Сообщение отправил Участник:Keegan (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == <span lang="en" dir="ltr">Vote now in the 2026 U4C election</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Eligible voters are asked to participate in the 2026 [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] election. More information–including an eligibility check, voting process information, candidate information, and a link to the vote–are available on Meta at the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|2026 Election information page]]. The vote closes on 2 June 2026 at [https://zonestamp.toolforge.org/1780358400 00:00 UTC]. Please vote if your account is eligible. Results will be available by 14 June 2026. -- In cooperation with the U4C,<section end="announcement-content" /> </div> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 17:14, 27 мая 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Keegan (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == RFC about AI-generated content in Wikimedia Commons == <bdi lang="en" dir="ltr">Apologies for writing in English, please help translate this message to your language. You are invited to participate in a [[c:Commons:Requests for comment/Policy update for AI content|request for comment on Wikimedia Commons about a policy update for AI content]]. This may affect files that are uploaded to Wikimedia Commons for use on this project. Thank you. [[m:User:Codename Noreste|Codename Noreste]] ([[m:User talk:Codename Noreste|обсуждение]])</bdi> 17:11, 23 июня 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Codename Noreste@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == Размещение ссылок на контакты по вопросам права и безопасности в нижнем колонтитуле вашего вики-проекта == <section begin="Message"/> '''Контакты по вопросам права и безопасности''' Дорогие участники сообщества, Фонд Викимедиа сформировал [[wmf:Special:MyLanguage/Legal:Wikimedia Foundation Legal and Safety Contact Information|единую страницу с контактами по вопросам права и безопасности]] для размещения в нижних колонтитулах ваших проектов соответствующих ссылок на нее, чтобы обеспечить доступ к достоверной юридической информации. Это нормативное требование. Мы уже разместили эти ссылки в английском, немецком, итальянском, испанском и других проектах Википедии, и мы также скоро добавим это и в ваш вики-проект. [[m:Special:MyLanguage/Wikimedia_Foundation_Legal_and_Safety_Contacts_FAQ|Пожалуйста, ознакомьтесь более подробно на странице проекта]] и оставляйте любые комментарии в этой ветке или на [[m:Special:MyLanguage/Talk:Wikimedia Foundation Legal and Safety Contacts FAQ|странице обсуждений]]. <section end="Message"/> -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 13:30, 25 июня 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Sannita (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=30731267 --> == Request for comment (the future of Abstract Wikipedia) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies if this has not yet been translated into your wiki's language. {{int:Please-translate}} You are invited to voice your opinions in a [[:m:Requests for comment/The future of Abstract Wikipedia|request for comment about the future of Abstract Wikipedia]]. {{Int:Feedback-thanks-title}} [[:m:User:Kowal2701|Kowal2701]] ([[:m:User talk:Kowal2701|talk]]) 12:24, 24 июля 2026 (UTC) </bdi> (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:DreamRimmer@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == Переключение сервера: ваш вики-проект скоро на короткое время будет доступен в режиме «только для чтения» == <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Прочитать это сообщение на другом языке]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] [[foundation:|Фонд Викимедиа]] будет переключать трафик между своими центрами обработки данных. Это гарантирует, что Википедия и другие вики-проекты Викимедиа смогут оставаться доступными даже после катастрофы. Весь трафик будет переключен '''{{#time:j xg|2026-09-23|ru}}'''. Переключение начнётся в '''[https://zonestamp.toolforge.org/{{#time:U|2026-09-23T14:00|en}} {{#time:H:i e|2026-09-23T14:00}}]'''. К сожалению, ввиду некоторых ограничений движка [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], редактирование будет остановлено в течение этих двух переключений. Приносим свои извинения за задержку в работе. Мы работаем над тем, чтобы сократить такие работы в будущем. За 30 минут до начала переноса во всех проектах будет показан баннер-предупреждение. Этот баннер будет оставаться видимым до окончания операции. Вы можете внести вклад в [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate перевод или вычитку] этого текста баннера. '''В течение короткого промежутка времени вы сможете читать, но не сможете редактировать все вики-сайты.''' * День переключения — {{#time:l j xg Y|2026-09-23|ru}}. Оно продлится не более часа. * При попытке отредактировать или сохранить страницы в течение этого времени вы увидите сообщение об ошибке. Мы надеемся, что правки в этот период не будут потеряны, но не можем этого гарантировать. Если вы увидите сообщение об ошибке, пожалуйста, подождите, пока всё не восстановится. После этого вы сможете сохранить свою правку. Но на всякий случай мы рекомендуем вам сделать копию ваших изменений. ''Побочные эффекты'': * Фоновые задания будут выполняться замедленно, а некоторые могут быть отклонены. Красные ссылки могут также обновляться с замедлением. Если вы создаёте статью, на которую уже есть ссылки откуда-то, то такие ссылки будут оставаться красными дольше, чем обычно. Некоторые долго выполняющиеся скрипты необходимо будет остановить. * Мы ожидаем, что развёртывание кода произойдет так же, как и на любой другой неделе. Однако могут происходить некоторые зависания кода, если впоследствии этого потребует данная операция. * [[mw:Special:MyLanguage/GitLab|GitLab]] будет недоступен примерно 90 минут. При необходимости эти планы могут быть отложены. Вы можете [[wikitech:Switch_Datacenter|посмотреть расписание на wikitech.wikimedia.org]]. О любых изменениях будет сообщено в расписании. '''Пожалуйста, поделитесь этой информацией с вашим сообществом.'''</div><section end="server-switch"/> [[m:user:Trizek (WMF)|Trizek (WMF)]] 12:58, 15 сентября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Trizek (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=30513874 --> == Your feedback wanted: Remove ''(Language link added:) and similar'' edits from Special:RecentChanges == ''(Apologies for posting in English. You can help by translating it)'' Hello, I’m Danny from [[:en:w:Wikimedia_Deutschland|Wikimedia Deutschland’s]] [[m:Wikidata_For_Wikimedia_Projects|Wikidata For Wikimedia Projects]] team.<br/> We have been investigating and examining how Wikidata’s use in the [[Special:RecentChanges]] and [[Special:Watchlist]] pages can be made to be more useful, or less ‘noisy’ (fewer edits that have little value to the reader). We are currently exploring to make a change in the volume and the type of Wikidata edits that appear in these pages, and '''we need your feedback''' to help us ensure this is a positive change for the Wikis and won’t disrupt your workflows.<br/> Language links are also known as sitelinks or interlanguage links and describe when a Wikidata item is connected to a Wiki, adding it to the language dropdown tool for other connected Wikis. [[File:Types of Lang Link changes.png|x350px|frame|A variety of "Language Link" edits as seen in the Recent Changes feed]] The request for feedback is whether you support the removal of these language link edits from the Recent Changes and Watchlist feed, or would you oppose such a change and if so, why? Please share you thoughts on the dedicated '''[[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|metawiki Talk page]]'''. Further information about this change: [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|m:Wikidata_For_Wikimedia_Projects/Hide_Language_Link_edits]] Thank you for any participation or feedback you give, -- [[m:User:Danny_Benjafield_(WMDE)|User:Danny Benjafield (WMDE)]] 11:46, 25 сентября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Danny Benjafield (WMDE)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31080832 --> == Wikidata Sitelink changes in Recent Changes and Watchlist == ''(Apologies for cross-posting in English, translating it will help spread the message)'' Editors on group 1 wikis, including Wikiquote, Wikibooks, Wikiversity, Wikivoyage, and Wikisource, will no longer see notifications on [[Special:RecentChanges|Recent Changes]] and [[Special:Watchlist|Watchlist]] when a link to ''another'' language version of a page is added, removed, or changed in its Wikidata item. This change will begin on '''October 5 at 07:00 UTC''' as a two-week trial to reduce high-volume, low-value notifications and make higher-value changes easier to identify. Editors who rely on these notifications should be aware of the change and can share feedback or concerns on the [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|project]] or [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|talk page]].<br/>Please reach out if you have any questions, thank you! -- [[User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] ([[User_talk:Danny_Benjafield_(WMDE)|talk]]) sent via [[Участник:MediaWiki message delivery|MediaWiki message delivery]] ([[Обсуждение участника:MediaWiki message delivery|обсуждение]]) 12:42, 1 октября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Danny Benjafield (WMDE)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31106967 --> == Переключение сервера: ваш вики-проект скоро на короткое время будет доступен в режиме «только для чтения» == <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Прочитать это сообщение на другом языке]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] [[foundation:|Фонд Викимедиа]] будет переключать трафик между своими центрами обработки данных. Это гарантирует, что Википедия и другие вики-проекты Викимедиа смогут оставаться доступными даже в случае катастрофы. Весь трафик будет переключён '''{{#time:j xg|2026-10-28|ru}}'''. Переключение начнётся в '''[https://zonestamp.toolforge.org/{{#time:U|2026-10-28T15:00|en}} {{#time:H:i e|2026-10-28T15:00}}]'''. К сожалению, ввиду некоторых ограничений движка [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], редактирование будет остановлено в течение этих двух переключений. Приносим свои извинения за задержку. Мы стараемся сократить такие заминки в будущем. За 30 минут до начала переноса во всех проектах будет показан баннер-предупреждение. Этот баннер будет оставаться видимым до окончания работ. Вы можете помочь [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate с переводом или вычиткой] этого текста. '''В течение короткого промежутка времени вы сможете читать, но не сможете редактировать все вики-сайты.''' * День переключения — {{#time:l j xg Y|2026-10-28|ru}}. Оно продлится не более часа. * При попытке отредактировать или сохранить страницы в течение этого времени будет показано сообщение об ошибке. Мы надеемся, что правки в этот период не будут потеряны, но не можем этого гарантировать. Если вы увидите сообщение об ошибке, пожалуйста, подождите, пока всё не восстановится. После этого вы сможете сохранить свою правку. Но на всякий случай мы рекомендуем сделать копию ваших изменений. ''Побочные эффекты'': * Фоновые задания будут выполняться замедленно, а некоторые могут быть отклонены. Красные ссылки могут также обновляться с замедлением. Если вы создаёте статью, на которую уже есть ссылки, то они будут оставаться красными дольше, чем обычно. Некоторые долго выполняющиеся скрипты необходимо будет остановить. * Мы ожидаем, что развёртывание нового кода произойдёт как обычно. Однако в отдельных случаях код могут частично замораживать, если это потребуется для работ. * [[mw:Special:MyLanguage/GitLab|GitLab]] будет недоступен примерно 90 минут. При необходимости планы по переключению серверов могут быть отложены. Расписание работ [[wikitech:Switch_Datacenter|см. на wikitech.wikimedia.org]]. Там же будет сообщаться о всех изменениях. '''Пожалуйста, поделитесь этой информацией с вашим сообществом.'''</div><section end="server-switch"/> [[user:Trizek_(WMF)|Trizek_(WMF)]] 14:01, 26 октября 2026 (UTC) (This message was sent to [[:Викиучебник:Форум]] and is being posted here due to a redirect.) <!-- Сообщение отправил Участник:Trizek (WMF)@metawiki, используя список на странице https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=30513874 --> azdwls03c3z05e8kc7w59o4s3zuf1rb Си++ 0 1351 270434 258294 2026-10-27T07:37:47Z Jcb 79968 270434 wikitext text/x-wiki {{Название учебника |Категория = Программирование |Готовность = 75% |Тип = Многостраничный }} {{wikipedia|Си++}} Это — вводный курс по [[Объектно-ориентированное программирование|объектно-ориентированному]] [[Программирование|программированию]] на языке [[w:C++|Си++]]. Материал изложения примерно соответствует части курса ООП ФИТ НГУ ([[w:Новосибирский государственный университет|Новосибирский государственный университет]]) за третий семестр, касающейся Си++, а также классическим книгам Страуструп/Эллис (около 1990) и Саттер/Александреску (около 2000). Смотрите [http://ccfit.nsu.ru/~rylov/oop.html список тем к экзамену]. == Введение == Язык C++ сравнивается с С, который считается уже известным читателю. За отправную точку принят стандарт C89 (он же C90). По следующим причинам: * Стандарт C99 не реализован полностью ни в [[w:GCC|GCC]] [http://gcc.gnu.org/c99status.html], ни [[w:Visual C++|Visual C++]] [http://stackoverflow.com/questions/146381/visual-studio-support-for-new-c-c-standards]. * В учебнике брать за исходную точку следует стандарт, который реализован полностью и уже давно, а не тот, работа по реализации которого ещё не закончена. Си++ - и без того довольно сложный язык, чтобы ещё запутывать читателя подробностями о том, какие свойства C99 где реализованы. Некоторые конструкции («два слеша») и inline давно реализованы во многих компиляторах Си. Это не делает их частью стандартa C99. == Содержание == * [[/Препроцессорные директивы/]] * [[/Основные отличия Си++ от Си/]] * [[/Объектно-ориентированное программирование/]] * [[/Обобщённое программирование/]] * [[/Стандартная библиотека/]] * [[/Разные вопросы/]] * [[/DLL]] == Эпилог == Некоторые люди интересовались, откуда берутся так часто употребляемые ''метасинтатические переменные'' <tt>foo</tt>, <tt>bar</tt> и тому подобные. На английском происхождение данных слов очень хорошо описано в {{RFC|3092}}. (Также, если вы знаете английский, см. [http://klubkev.org/~ksulliva/rfc-april1/ полный список первоапрельских RFC].) Если Вы возьмётесь править этот викиучебник, пожалуйста, соблюдайте правила русской [[w:Типографика|типографики]]. О том, как это делается см. [[w:Википедия:Специальные символы|Википедия: Специальные символы]]. == См. также == * [[Реализации алгоритмов]] === C === * [[Язык Си в примерах]] * [[w:Си (язык программирования)|Си]]/[[w:ANSI C|ANSI C]]/[[w:C99|C99]]/[[w:C11|C11]] * [[:w:Категория:Статьи с примерами кода Си|Категория: Статьи с примерами кода Си]] === C++ === * [[w:C++|C++]]/[[w:C++11|C++11]]/[[w:C++14|C++14]]/[[w:C++17|C++17]] * [[w:Boost|Boost]] * [[:w:Категория:Статьи с примерами кода C++|Категория: Статьи с примерами кода C++]] == Ссылки == * [https://my-specialist.ru/chto-takoe-c-tendencii-i-spros-na-razrabotchikov-etot-yazyk-programmirovaniya/ Что такое C++? Тенденции и спрос разработчиков на этот язык программирования] * [https://isocpp.org/ News, Status & Discussion about Standard C++] * [http://www.cplusplus.com/ The C++ Resources Network] * [http://www.books.ru/cc-9001536/ Книги C/C++ (584) Books.ru] * [http://kak-tot.narod.ru/ru/otd-bs2e/index.htm Книга Б. Страуструпа "Язык программирования С++"] * {{dmoz|Computers/Programming/Languages/C%2B%2B/|C++}} 917by28dlg3hlcndpqaei7jy4mv1pub Семейство стандартов SNMP 0 3266 270432 258859 2026-10-27T07:33:29Z Jcb 79968 270432 wikitext text/x-wiki {{Название учебника|Тип=Одностраничный|Категория=Компьютерные сети,Информационная безопасность}} {{wikipedia|SNMP}} Семейство стандартов простого протокола управления сетями (Simple Network Management Protocol, SNMP) предназначено для управления сетями. Семейство определено сообществом проектирования Интернета (Internet Engineering Task Force, IETF) и является частью семейства стандартов Интернета. == О книге == Первоначальный автор — [[w:Участник:Anrie Nord|Anrie Nord]]. Книга стремится познакомить со стандартами в области управления сетями, а также научить архитектурным принципам семейства стандартов SNMP. Архитектура рассматривается в рамках классификации сетевых программных архитектур<ref name="fielding">Fielding R. T. Architectural Styles and the Design of Network-based Software Architectures. Ph. D. Dissertation. — University of California, Irvine. — 2000. http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm</ref>. Описывается история развития стандартов и даются комментарии по причинам принятия новых версий SNMP. == Стандарты управления сетями == Помимо стандартов SNMP сообщества IETF есть стандарты, принимаемые международными органами стандартизации<ref name="pras">Pras A. Internet Management Protocols Course — University of Twente, 2000. http://www.simpleweb.org/</ref>; вот крупнейшие из них: {| class="wide" ! Организация || Стандарты || Особенности |- | IETF || SNMP || Управление должно быть простым, ориентировано на переменные |- |ISO || CMIP, CMIS || Управление должно быть мощным, объектно-ориентированное |- |ITU-T || TMN || Определяется только архитектура |- |DMTF || WBEM, CIM || Управление сетями и системами, объектно-ориентированное |- |OMG || CORBA || Архитектура удалённых объектов |} Ныне самым успешным семейством стандартов является SNMP<ref name="pras" />; он лидирует по числу управляемых систем (агентов). Управляющие системы (менеджеры) обычно поддерживают множество стандартов, поэтому здесь сложно говорить о лидерстве SNMP. По количеству вложенных денег, возможно, лидирует Telecommunications Management Network (TMN). Показательно проследить зависимость популярности стандартов от среды их применения. В локальных и глобальных сетях передачи данных, использующих Протокол интернета (Internet Protocol, IP) наиболее широко распространён стандарт SNMP. В системах учрежденческих автоматических телефонных станций (УАТС) и в публичных телефонных сетях наиболее часто используются проприетарные решения. В мобильных сетях в основном используются решения на основе стандартов Международной Стандартизационной Организации (ISO). Почти все успехи SNMP связаны с особенностями процесса стандартизации в IETF: * Стандарты бесплатны и свободно распространяемы * Стандарты легко доступны в электронной форме * Быстрое развитие стандартов, продуманные этапы стандартизации * На всех этапах ведётся техническая экспертиза * Рабочие группы возглавляют технические, а не политические лидеры * Прототипы систем на основе стандартов демонстрируют их применимость == Задачи == Функциональные группы задач управления системами определены в стандарте ITU-T X.700: * Управление конфигурацией (Configuration Management) * Обработка ошибок (Fault Management) * Анализ производительности и надёжности (Performance management) * Управление безопасностью (Security Management) * Учёт работы (Accounting Management) Семейство стандартов SNMP создано для решения задач обработки ошибок и анализа производительности и надёжности. ;Обработка ошибок:выявление, определение и устранение последствий сбоев и отказов в работе сети<ref>Олифер В. Г., Олифер Н. А. Компьютерные сети. Принципы, технологии, протоколы. — СПб.: Питер, 2001</ref>. На этом уровне выполняется регистрация сообщений об ошибках, их фильтрация, маршрутизация и анализ на основе некоторой корреляционной модели. ;Анализ производительности и надёжности:оценка на основе статистической информации таких параметров, как время реакции системы, пропускная способность каналов связи, интенсивность трафика в отдельных сегментах сети, вероятность искажения данных, коэффициент готовности служб сети. Результаты такого анализа позволяют контролировать соглашение об уровне обслуживания (Service Level Agreement, SLA). Согласно идеологии SNMP, управление должно быть простым, пусть даже ценой потери мощности, масштабируемости и защищённости<ref name="pras" />. Поэтому при разработке стандартов SNMP учитывались следующие условия: * Повсеместность. Системы под управлением SNMP могут быть любыми и могут быть везде: от принтеров до мейнфреймов * Простота добавления управляющих функций. Управляемая система ограничена в функциональности управления, очень проста и не может контролировать себя. Вместо этого все управляемые системы контролирует сложная управляющая система, функциональность которой можно расширять * Устойчивость в критических ситуациях. Например, при перегрузке и проблемах в сети, т. е. при множественных ошибках == История == Одной из самых первых инициатив по управлению сетями была инициатива ISO Open Systems Interconnection (OSI). Соответствующие группы по стандартизации инфраструктуры управления OSI (OSI Management Framework) были созданы в 1981 году. К концу 1980-х годов сеть Интернет стала достаточно большой и потребовала стандартов управления. Однако группа ISO OSI была далека от завершения работ над семейством стандартов. Поэтому в 1987 году сообществом IETF было принято решение ''временно'' создать набор упрощённых стандартов управления в Интернете на основе наработок ISO OSI. Данные стандарты получили название Simple Network Management Protocol (SNMP). В дальнейшем предполагалось переключиться на стандарты ISO по мере их готовности. Таким образом, многие идеи SNMP были взяты из стандартов ISO: * Концепция «менеджер-агент» * Идея баз управляющей информации (Management Information Bases, MIBs) * Использование синтаксиса Abstract Syntax Notation One (ASN.1) * Часть терминологии Другими проектом стандарта, на базе которого началась разработка SNMP, был проект простого протокола мониторинга шлюзов (Simple Gateway Monitoring Protocol, SGMP) сообщества IETF. В дальнейшем в рамках ISO OSI было предложено много новых идей, в частности, объектно-ориентированный подход. Однако эти идеи уже не вошли в стандарты SNMP. Одно время IETF продолжала инициативу CMIP over TCP (CMOT), которая предполагала использование общего протокола управляющей информации (Common Management Information Protocol, CMIP) стека протоколов ISO OSI в стеке IETF TCP/IP. В 1992 году эта инициатива была прекращена в связи с успехом и распространённостью SNMP. Стандарты SNMP продолжали развиваться на протяжении 1990-х годов. Основным направлением развития было совершенствование вопросов безопасности. Были разработаны следующие версии SNMP: SNMPv1, SNMPv2, SNMPv2c, SNMPv2u и SNMPv3. Их обсуждение будет продолжено в главе «Версии SNMP». == Архитектура == Архитектуру распределённой системы можно описать в терминах обрабатывающих элементов (или компонентов), соединяющих элементов (или соединителей) и элементов данных<ref>Perry D. E., Wolf A. L. Foundations for the Study of Software Architecture // ACM SIGSOFT Software Engineering Notes. — 1992. — #17(4). — pp. 40-52</ref>. Перечислим составные элементы системы управления SNMP<ref name="snmp-arch">Harringson D., et al. An Architecture for Describing SNMP Management Frameworks. IETF STD 62, {{RFC|3411}}. — 2002. http://www.ietf.org/rfc/rfc3411.txt</ref>: * Компоненты ** Агент ** Менеджер * Соединители ** Транспортный протокол ** Протокольные блоки данных (Protocol Data Units, PDU) и сообщения SNMP * Данные ** Управляющая информация MIB Опишем подробнее и проанализируем архитектуру SNMP с позиции достижения поставленных перед SNMP целей. Для этого используем понятие архитектурного стиля сетевого программного обеспечения<ref name="fielding"/>. '''Архитектурный стиль''' — это согласованный набор архитектурных ограничений, накладываемых на роли и особенности архитектурных элементов (компонентов, соединителей и данных) и отношений между ними, проявляющийся в любой архитектуре, которая удовлетворяет этому стилю. === Компоненты === Вначале поговорим об архитектурных компонентах. Архитектура SNMP предполагает построение системы управления по схеме «менеджер-агент», т. е. использование архитектурного стиля «клиент-сервер». Система SNMP содержит множество управляемых узлов, на каждом из которых размещается достаточно простой сервер — агент SNMP, а также, по крайней мере, один узел, содержащий сложного клиента — менеджера SNMP. Менеджер взаимодействует с агентами при помощи протокола SNMP с целью обмена управляющей информацией. В основном, это взаимодействие реализуется в виде ''периодического опроса'' менеджером множества агентов, т. к. агенты всего лишь предоставляют доступ к информации, но не знают, что им с ней делать. Видно, что система, построенная по таким принципам, теряет в масштабируемости, поскольку есть выделенный клиент, занимающийся опросом всех серверов. Зато такая схема обеспечивает простоту реализации систем под управлением SNMP. Для повышения масштабируемости и административной управляемости вводится понятие прокси-агента, который может переправлять операции протокола SNMP, а также понятие менеджера промежуточного уровня, который скрывает несущественные подробности управляющей информации от систем управления сетями верхнего уровня, интегрируя получаемые от агентов данные. Это позволяет создавать многоуровневые системы управления, соответствующие архитектурному стилю «многоуровневый клиент-сервер». Более детальная классификация компонентов по ролям: * Менеджер ** Менеджер промежуточного уровня ** Система управления сетями * Агент ** Минимальный агент ** Прокси-агент ** Менеджер промежуточного уровня Компоненты в SNMP обобщённо называются '''сущностями SNMP'''. === Данные === Теперь рассмотрим данные, которыми манипулируют системы SNMP, т. е. управляющую информацию. В SNMP каждое управляемое устройство, на котором расположен агент, представляет свою управляющую информацию в виде '''переменных'''. Такими переменными могут быть, например, имя системы, время с момента её перезапуска, записи в таблице маршрутизации и т. д. В общем случае переменные можно разделить на: * Скалярные переменные * Таблицы переменных Схема данных описывается структурой управляющей информации (Structure of Management Information, SMI). Схема данных определяет, как выглядит управляющая информация, т. е. описывает её синтаксис. SMI базируется на Abstract Syntax Notation One (ASN.1). Конкретные наборы управляющей информации для разных типов устройств, протоколов и т. д. описываются базами управляющей информации (Management Information Bases, MIBs). Базы MIB определяют, какая управляющая информация существует. Например, для устройства, поддерживающего IP, MIB описывает таблицу маршрутизации, флажок активации функции маршрутизации, число переданных и принятых пакетов, число ошибок различного характера и т. д. Таким образом, каждое устройство содержит набор значений переменных, определённых в некотором количестве MIB, описанных по правилам SMI. Этот набор переменных и является данными, управляющей информацией для протокола SNMP. Важным вопросом является именование переменных. В SNMP каждой переменный присваивается уникальный идентификатор объекта (Object Identifier, OID). Пространство имён OID является иерархическим и контролируется организацией по распределению номеров в Интернете (Internet Assigned Numbers Authority, IANA). Каждый компонент имени является числом. В текстовом виде имена записываются как десятичные числа, разделённые точками, слева направо. Числам могут быть поставлены в соответствие текстовые строки для удобства восприятия. В целом, структура имени похожа на систему доменных имён Интернета (Domain Name System, DNS). Каждая MIB определяет набор переменных, т. е. определённую ветку дерева OID, описывающую управляющую информацию в определённой области. Например, ветка <code>1.3.6.1.2.1.1</code> (мнемонический эквивалент: <code>iso.org.dod.internet.mgmt.mib-2.system</code>) описывает общую информацию о системе. Опишем некоторые переменные из этой ветки: * <code>sysDescr</code> (<code>1.3.6.1.2.1.1.1</code>) — краткое описание системы * <code>sysUpTime</code> (<code>1.3.6.1.2.1.1.3</code>) — время с момента последнего перезапуска * <code>sysName</code> (<code>1.3.6.1.2.1.1.5</code>) — имя системы Переменные и сведения об их типе определены также в MIB. А сами типы переменных — в SMI. Помимо непосредственно данных, необходимо ввести операции над ними. Набор этих операций изменялся и расширялся по мере развития SNMP. Основными операциями являются: * Чтение переменной * Запись переменной * Чтение переменной, следующей за заданной переменной (требуется для просмотра таблиц переменных) Более подробно операции над данными описаны ниже при обсуждении соединителей в архитектуре SNMP. В целом, операции над данными в SNMP похожи на удалённую отладку некоторого приложения: состояние системы описывается неким набором переменных, которые можно просматривать и изменять. === Соединители === Для обмена данными между компонентами используются соединители. В случае SNMP в качестве соединителя используется протокол прикладного уровня Simple Network Management Protocol (SNMP), обычно работающий поверх стека протоколов UDP/IP. Современные стандарты SNMP разрешают использование и других транспортных протоколов. Рассмотрим стек протоколов более подробно, указав привязку протоколов к Open Systems Interconnection Reference Model (OSI RM). {| class="wide" ! # || Протокол || Комментарий |- | 7 || SNMP || Сообщения, PDU, операции |- | 6 || ASN.1 BER || Кодирование данных |- | 5 || — || — |- | 4 || UDP || Транспорт между службами |- | 3 || IP || Связь между узлами сети |} SNMP вводит свой протокол прикладного уровня. Имеются четыре версии данного протокола: SNMPv1, SNMPv2, SNMPv2c и SNMPv3. В процессе развития SNMP расширялись возможные операции, т. е. типы протокольных блоков данных (Protocol Data Units, PDUs), а также вводились новые форматы сообщений SNMP для обеспечения безопасности. Сообщение SNMP содержит номер версии SNMP, информацию о безопасности и протокольный блок данных PDU, который характеризует выполняемую операцию и её параметры. Например, SNMPv1 описывает следующие PDU и соответствующие операции: * <code>Get-Request</code> — запрос на получение значений 1..N переменных * <code>Get-Next-Request</code> — запрос на получение значений 1..N переменных, чьи OID идут следом за OID указанных 1..N переменных * <code>Get-Response</code> — ответ на запросы <code>Get-Request</code>, <code>Get-Next-Request</code> и <code>Set-Request</code> * <code>Set-Request</code> — установка значений 1..N переменных * <code>Trap</code> — ловушка (см. ниже) Описанные PDU, как уже упоминалось, являются частью сообщения SNMP. Сообщения кодируются для передачи по сети при помощи ASN.1 Basic Encoding Rules (BER). Это функция шестого уровня (уровня представления) эталонной модели OSI. Далее закодированные сообщения отправляются одним компонентом SNMP другому при помощи транспортного протокола. Как уже отмечалось, стандарт предусматривает использование различного транспорта для SNMP, но почти что всегда используется протокол пользовательских датаграмм (User Datagram Protocol, UDP). Агенты используют хорошо известный порт UDP 161. Этот протокол предоставляет минимальные транспортные услуги (доставка сообщений от службы к службе и проверка контрольной суммы) и не предполагает организацию сеансов и потоковую передачу данных, как Transmission Control Protocol (TCP). За счёт этого удаётся добиться большой скорости реакции и быстродействия, что соответствует поставленным перед SNMP целям. Для повышения скорости реакции менеджера на срочные события вводится специальный тип операции протокола SNMP, называемый «ловушка» (<code>Trap</code>). Он позволяет агентам асинхронно информировать менеджера (по собственной инициативе) о наступлении ограниченного числа значимых событий. В этом случае агент выступает в необычной для себя роли клиента, а менеджер — в роли сервера. В случае использования транспорта UDP для входящих соединений менеджер использует хорошо известный порт UDP 162. Как мы видим, ни одна из этих операций не предполагает, что агент хранит информацию о сессии с менеджером. Для выполнения операции <code>Trap</code> такая информация хранится статически, т. е. сессия в таком случае статична и перманентна. Помимо этого операции SNMP определяют единые, унифицированные интерфейсы агентов и менеджеров SNMP. Таким образом, SNMP — это протокол без сохранения состояния, который соответствует архитектурному стилю «унифицированный многоуровневый клиент-сервер без сохранения состояния». Опишем некоторые свойства операций SNMP на примере SNMPv1: {| class="wide" ! Имя || Безопасная || Подтверждаемая || Идемпотентная |- | <code>Get-Request</code> || 1 || 1 || 1 |- | <code>Get-Next-Request</code> || 1 || 1 || 1 |- | <code>Get-Response</code> || 1 || 0 || ? |- | <code>Set-Request</code> || 0 || 1 || ? |- | <code>Trap</code> || 1 || 0 || ? |} Таким образом, мы рассмотрели все основные архитектурные особенности SNMP, кроме моделей безопасности. Вопросы, связанные с защитой информации, будут рассмотрены ниже при обсуждении версий стандартов SNMP. == Соответствие архитектурному стилю REST == '''Архитектурный стиль REST''' — это унифицированный многоуровневый кэшируемый клиент-серверный стиль с кодом по запросу и без сохранения состояния (Unified-Layered-Code-on-Demand-Client-Cached-Stateless-Server, ULCODCСSS)<ref name="fielding"/>. Как мы определили в результате анализа архитектуры SNMP, система SNMP определяется унифицированным многоуровневым клиент-серверным стилем без сохранения состояния (Unified-Layered-Client-Stateless-Server, ULCSS). Как мы видим, на SNMP не накладываются ограничения, связанные с репликацией (наличие кэша) и мобильным кодом (применение кода по запросу). В этом смысле стиль SNMP — более свободный, чем REST, т. е. содержит меньше архитектурных особенностей, которые, например, необходимо учитывать при моделировании систем с такой архитектурой. Однако, даже в SNMPv1 есть особая операция <code>Trap</code>, инициируемая агентом асинхронно по отношению к менеджеру. В SNMPv2 вводится операция <code>Inform-Request</code>, которая также выполняется асинхронно, но между двумя менеджерами. При выполнении таких операций клиент и сервер меняются ролями. При этом используется принцип интеграции на основе извещений. Это элементы однорангового стиля взаимодействия (Peer-to-Peer), хотя в данном случае роли клиента и сервера для конкретных типов протокольных операций выражены явно. В этом смысле стиль SNMP — более ограниченный, чем REST. Таким образом, при определённых ограничениях система SNMP может быть рассмотрена как REST-овская распределённая система. == Структура стандартов == Стандарты SNMP описывают аспекты, отражённые ниже<ref name="snmp-arch"/>: * Общая информация * Обработка сообщений (SNMP Messages) ** Привязки к транспорту ** Разбор и диспетчеризация сообщений ** Безопасность (аутентификация, шифрование, своевременность) * Обработка протокольных блоков данных (SNMP PDUs) ** Операции протокола ** Приложения SNMP ** Управление доступом * Информационная модель ** Структура управляющей информации (SMI) ** Текстовые конвенции ** Выражения соответствия * Модули баз управляющей информации (MIB) Изначально в стандартах выделялись не все эти аспекты. Тем не менее, структура стандартов SNMP всех версий вписывается в эту схему. Можно видеть, что рассмотренная нами выше архитектура SNMP даёт представление о многих из этих аспектов. В частности, компоненты SNMP описаны в разделах «Общая информация» и «Приложения SNMP», данные — в разделах «Информационная модель» и «Модули баз управляющей информации», а соединители — в «Обработке сообщений» и «Операциях протокола». Среди важных аспектов, не рассмотренных при анализе архитектуры SNMP, остаётся информационная безопасность, описываемая в разделах «Безопасность» и «Управление доступом». Перейдём к рассмотрению этих вопросов. == Информационная безопасность == Рассмотрим, как учитываются в SNMP основные элементы информационной безопасности: * Конфиденциальность * Целостность * Доступность * Контролируемость В ходе развития стандартов SNMP инфраструктура безопасности подвергалась наибольшим изменениям. Для того, чтобы проследить эти изменения, вначале опишем требования безопасности и угрозы, затем структуру моделей безопасности, после чего рассмотрим использующиеся в различных версиях SNMP модели. === Требования и угрозы безопасности === Опишем требования безопасности в архитектуре SNMP<ref name="snmp-arch"/>. Угрозами безопасности, против которых должна предоставлять защиту любая модель безопасности SNMP, являются: * Первичные угрозы ** Модификация информации ** Маскарад * Вторичные угрозы ** Модификация потока сообщений ** Разглашение '''Угроза модификации информации''' — это возможность того, что некоторая неавторизованная сущность может изменить сообщения SNMP, сгенерированные по запросу авторизованного принципала, на пути их следования таким образом, что это приведёт к неавторизованным операциям управления, включая фальсификацию значения объекта (переменной). '''Угроза маскарада''' — это возможность того, что операции управления, не авторизованные для некоторого принципала, могут быть предприняты при подстановке идентификатора другого принципала, для которого подобные действия авторизованы. '''Угроза модификации потока сообщений''' состоит в следующем. Протокол SNMP обычно основан на транспортной службе без организации соединения. Перестановка, задержка или повторная посылка сообщений может происходить и происходит в ходе обычной эксплуатации сетей с применением таких протоколов. Угроза модификаций потока сообщений — это возможность того, что сообщения могут быть переставлены, задержаны или повторно посланы со злым умыслом с задержками, которые превышают имеющие место задержки при нормальной эксплуатации, с целью выполнения неавторизованных операций управления. '''Угроза разглашения''' — это возможность прослушивания обменов сообщениями между сущностями SNMP. Защита от этой угрозы может требоваться локальной политикой безопасности. Модель безопасности может не бороться с такими угрозами, как, например, отказ в обслуживании, т. к. состояние сетевых сбоев и ошибок (нормальное для SNMP) часто неотличимо от ситуаций отказа в обслуживании. Как мы увидим ниже, на практике не каждая модель безопасности SNMP удовлетворяет требованиям нейтрализации перечисленных угроз. === Структура моделей безопасности === Устоявшаяся структура моделей безопасности была описана в документе по архитектуре SNMP<ref name="snmp-arch"/>. Сущность SNMP содержит две подсистемы: * Подсистема безопасности * Подсистема управления доступом '''Подсистема безопасности''' функционирует на уровне ''сообщений SNMP''. Она отвечает за аутентификацию, шифрование и своевременность. Документ по безопасности описывает модель безопасности, угрозы, против которых она защищает, цели модели безопасности, протоколы, используемые для достижения этих целей, модуль MIB, описывающий соответствующие структуры данных. Такой модуль нужен в том числе и для того, чтобы удалённо конфигурировать параметры безопасности уровня сообщений SNMP. '''Подсистема управления доступом''' функционирует на уровне ''SNMP PDU''. Очевидно, что она отвечает за управление доступом к управляемым объектам (переменным). Документы, описывающие её, также определяют модуль MIB для удалённой настройки параметров. === Модели безопасности === Перечислим основные модели безопасности и соответствующие им инфраструктуры: * SNMPv1 ** SNMPv1 — Community-based Security Model * SNMPv2 ** SNMPv2p — Party-based Security Model ** SNMPv2c — Community-based Security Model ** SNMPv2u — User-based Security Model * SNMPv3 ** SNMPv3 USM User-based Security Model '''Модель безопасности на основе сообществ (Community-based Security Model)''' была первой, самой простой и самой небезопасной. Она подразумевает лишь аутентификацию на основе «строки сообщества», фактически, пароля, передаваемого по сети в теле сообщения SNMP в открытом тексте. Эта модель безопасности не в состоянии бороться ни с одной из угроз информационной безопасности в SNMP. Тем не менее, она часто используется до сих пор в связи со своей простотой, а также благодаря наличию внешних, не связанных с SNMP систем безопасности, например, межсетевых экранов. '''Модель безопасности на основе сторон (Party-based Security Model)''' подразумевает введение понятие стороны. '''Сторона''' — это виртуальное окружение исполнения, в котором набор допустимых операций ограничен административно. Сущность SNMP при обработке сообщения действует как сторона, поэтому ограничена операциями, определёнными для этой стороны. Сторона определяется следующими параметрами: * Уникальный идентификатор стороны * Логический сетевой адрес (область адресов транспортного протокола и адрес транспортного протокола) * Протокол аутентификации и параметры, требующиеся для аутентификации всех сообщений стороны * Протокол шифрования и параметры, требующиеся для шифрования всех сообщений стороны Могут использоваться различные алгоритмы для протоколов аутентификации и шифрования. Обычно в качестве алгоритма для протокола аутентификации используют хэш-функцию Message Digest 5 (MD5), а для протокола шифрования — алгоритм Data Encryption Standard (DES) в режиме Cipher Block Chaining (CBC). Вводятся и другие понятия, используемые для реализации этой модели. Однако здесь они подробно не рассматриваются, так же как и детали функционирования модели. Отметим лишь, что при использовании соответствующих протоколов аутентификации и шифрования модель успешно справляется с описанными выше угрозами безопасности SNMP. Данная модель безопасности не была широко принята, поскольку показалась многим слишком сложной и запутанной. '''Модель безопасности на основе пользователей (User-based Security Model)''' вводит понятие ''пользователя'', от имени которого действует сущность SNMP. Этот пользователь характеризуется именем пользователя, используемыми протоколами аутентификации и шифрования, а также закрытым ключом аутентификации и шифрования. Аутентификация и шифрование являются необязательными. Их наличие описывается одним из параметров модели, качеством обслуживания (Quality of Service, QoS). Модель безопасности во многом похожа на модель на основе сторон, но она упрощает идентификацию пользователей, распределение ключей и проткольные операции. == Версии SNMP == Кратко опишем различия между версиями SNMP и документы, определяющие эти версии. Заметим, что здесь приведены ''первые'' версии RFC каждой из версий SNMP, т. е. почти все из них были замещены более новыми RFC и признаны устаревшими. По состоянию на 2006 год, единственной не устаревшей версией SNMP является SNMPv3, определённая в {{RFC|3411}}-3418. === SNMPv1 === Первые RFC, описывающие стандарты SNMP, появились в 1988 году. Версия 1 подверглась критике за её посредственную модель безопасности на основе сообществ<ref>Simple Network Management Protocol. — Wikipedia, The Free Encyclopedia. 2006-05-07 00:11Z http://en.wikipedia.org/w/index.php?title=Simple_Network_Management_Protocol&oldid=51905318</ref>. В то время безопасность в Интернете не входила в круг первоочередных задач рабочих групп IETF. * Обработка сообщений ** {{RFC|1067}}. A Simple Network Management Protocol * Обработка PDU ** {{RFC|1067}}. A Simple Network Management Protocol * Информационная модель ** Структура управляющей информации *** {{RFC|1065}}. Structure and Identification of Management Information for TCP/IP-based internets * Модули MIB ** {{RFC|1066}}. Management Information Base for Network Management of TCP/IP-based internets === SNMPv2 === Версия 2, известная так же, как Party-based SNMPv2, или SNMPv2p, не получила широкого распространения из-за серьёзных разногласий по поводу инфраструктуры безопасности в стандарте. SNMPv2 улучшал версию 1 в области быстродействия, безопасности, конфиденциальности и взаимодействий «менеджер-менеждер». Он представил новый тип PDU <code>Get-Bulk-Request</code>, альтернативу <code>Get-Next-Request</code> для получения больших объёмов информации при помощи одного запроса. Тем не менее, новая система безопасности на основе сторон выглядела для многих как чересчур сложная и не была широко признана. * Общая информация ** {{RFC|1441}}. Introduction to version 2 of the Internet-standard Network Management Framework ** {{RFC|1452}}. Coexistence between version 1 and version 2 of the Internet-standard Network Management Framework * Обработка сообщений ** Привязки к транспорту *** {{RFC|1448}}. Transport Mappings for SNMPv2 ** Безопасность *** {{RFC|1445}}. Administrative Model for SNMPv2 *** {{RFC|1446}}. Security Protocols for SNMPv2 * Обработка PDU ** Управление доступом *** {{RFC|1445}}. Administrative Model for SNMPv2 ** Протокольные операции *** {{RFC|1448}}. Protocol Operations for SNMPv2 * Информационная модель ** Структура управляющей информации *** {{RFC|1442}}. Structure of Management Information SNMPv2 ** Текстовые конвенции *** {{RFC|1443}}. Textual Conventions for SNMPv2 ** Выражения соответствия *** {{RFC|1444}}. Conformance Statements for SNMPv2 * Модули MIB ** {{RFC|1447}}. Party MIB for SNMPv2 ** {{RFC|1450}}. MIB for SNMPv2 ** {{RFC|1451}}. Manager-to-Manager MIB === SNMPv2c === Community-based SNMPv2, или SNMPv2c, представил SNMPv2 без новой модели безопасности версии 2. Вместо неё предлагалось использовать старую модель безопасности версии 1 на основе сообществ. Соответствующее предложение RFC было принято только как черновик стандарта, однако стало ''де факто'' стандартом SNMPv2. Безопасность SNMP снова оказалась нерешённым вопросом. * Обработка сообщений ** Безопасность *** {{RFC|1901}}. Introduction to Community-based SNMPv2 === SNMPv2u === User-based SNMPv2, или SNMPv2u, является компромиссом между незащищённостью SNMPv1 и чрезмерной сложностью SNMPv2p. Предложенная модель безопасности на основе пользователей была положена в основу SNMPv3. * Обработка сообщений ** Безопасность *** {{RFC|1909}}. An Administrative Infrastructure for SNMPv2 *** {{RFC|1910}}. User-based Security Model for SNMPv2 * Обработка PDU ** Управление доступом *** {{RFC|1909}}. An Administrative Infrastructure for SNMPv2 === SNMPv3 === SNMPv3 наконец-то решил проблемы с безопасностью способом, который многие посчитали приемлемым. Версия 3 SNMP принята IETF как стандарт Интернета (IETF STD 62). Почти все предыдущие RFC признаны устаревшими. * Общая информация ** {{RFC|3411}}. An Architecture for Describing SNMP Management Frameworks * Обработка сообщений ** Привязки к транспорту *** {{RFC|3417}}. Transport Mappings for the SNMP ** Разбор и диспетчеризация сообщений *** {{RFC|3412}}. Message Processing and Dispatching for the SNMP ** Безопасность *** {{RFC|3414}}. User-based Security Model (USM) for SNMPv3 * Обработка PDU ** Операции протокола *** {{RFC|3416}}. Version 2 of the Protocol Operations for SNMP ** Приложения SNMP *** {{RFC|3413}}. SNMP Applications ** Управление доступом *** {{RFC|3415}}. View-based Access Control Model (VACM) for the SNMP * Модули MIB ** {{RFC|3418}}. MIB for the SNMP == Блиц-сравнение с другими технологиями == SNMP похож на WBEM тем, что это семейство стандартов управления распределёнными объектами, построенное по схеме менеджер-агент. SNMP похож на APP тем, что это почти REST-овский протокол, который использует стандартный транспорт (UDP и TCP, соответственно), что использует стандартный формат кодирования информации на 6 уровне OSI (обменивается скорее данными, чем командами: ASN.1 и XML), хотя и использует собственный прикладной протокол (SNMP и HTTP). SNMP похож на ONC RPC тем, что оба используют метаязыки L0, L1, L2 для кодирования передаваемой информации на 6 уровне OSI (XDR Encoding и ASN.1 BER) и L2 для описания формата данных (XDR Language и ASN.1). Ещё раз о метаязыках. Например, в программировании: * L0 — значения переменных Python, <code>"12": 12</code> * L1 — переменные Python, <code>"i = 12; i": 12</code> * L2 — классы Python, <code>"type(i)": &lt;type 'int'&gt;</code> * L3 — метаклассы Python, <code>"type(type(i))": &lt;type 'type'&gt;</code> Например, в распределённых системах: * L0 — данные в RPC, данные в XDR Encoding * L1 — экземпляры переменных в RPC, описатели полей структур в XDR Encoding * L2 — типы данных в RPC, типы полей структур в XDR Encoding, типы XDR Language * L3 — типы типов RPC, формальная спецификация XDR Language SNMP похож на HTTP тем, что вопросы интерфейса между приложениями в основном решаются на уровне сетевого API, т. е. на 7 уровне OSI, а не на уровне программного интерфейса (хотя последующие версии SNMP описывают абстрактный программный API). == Существующие реализации == Поддержка SNMP — во многих значимых системах управления сетями, в частности: * HP Network Node Manager * IBM Tivoli NetView * OpenNMS == Заключение == * SNMP широко используется для управления сетями, особенно IP-сетями * Успех SNMP по сравнению с другими стандартами управления показывает преимущества процесса стандартизации IETF * История развития SNMP показывает важность задач защиты информации * Архитектура SNMP интересна как пример для анализа архитектуры сетевого программного обеспечения; она соответствует поставленным перед SNMP целям * Архитектура SNMP соответствует архитектурному стилю ULCSS сетевого программного обеспечения * В SNMP для решения функций 6 уровня модели OSI RM используется ASN.1, что необычно для стандартов IETF и положительно сказывается на вопросах формализации протоколов, однозначности стандартов, удобства проектирования приложений * Структура стандартов SNMP хорошо продумана и показательна как пример для изучения стандартов * Лишь некоторые модели безопасности SNMP отвечают поставленным перед системой безопасности SNMP целям * SNMP сравним со всеми объектами в мире, а в случае сетевых технологий 4-7 уровня OSI RM это к тому же имеет практический смысл и может иметь теоретический смысл * Агенты и менеджеры SNMP просты в программной реализации, однако всегда нужно помнить об информационной безопасности == Внешние ссылки == * SNMP менеджеры ** [https://plgn.ru/catalog/programmnoe-obespechenie/sistema-upravleniya-setyami-polygon-snmp-manager/ Бесплатная система управления Polygon SNMP Manager на базе протокола SNMP] * Общая информация по SNMP ** [[w:SNMP|SNMP в Википедии]] * Изучение SNMP ** [http://www.simpleweb.org/tutorials/video/ SNMP tutorials in Real format] ** [http://www.simpleweb.org/tutorials/exercises.html SNMP interactive exercises] * Простые реализации SNMP ** [http://www.wtcs.org/snmp4tpc/getif.htm Getif] ** [http://pysnmp.sourceforge.net/ PySNMP] * Сетевое программирование на Python ** [http://www.amk.ca/python/howto/sockets/ Socket Programming HOWTO] ** [http://pyasn1.sourceforge.net/ ASN.1 tools for Python] * Для работы с SNMP ** [http://snmp.ru/doku.php Описание] ** [http://www.mmtools.ru/news.php Tools] ** [http://docsis.dobroe.ru/DOCSIS/ DOCSIS & SNMP] == Примечания == {{примечания}} qgra6ntu61zfxlkxs7an3gu01v0hxkp Сетевой порт/Что такое NAT и как определить, находитесь ли вы за NAT 0 3889 270433 264079 2026-10-27T07:34:31Z Jcb 79968 270433 wikitext text/x-wiki {{wikipedia|NAT}} == Что такое NAT == [[Файл:Network.NAT.png|right]] NAT — Network Address Translation, трансляция сетевых адресов. Оригинал {{RFC|1631}}, {{RFC|3022}}. Перевод http://rfc.com.ru/rfc3022.htm {{RFC|3022}}. Ваш компьютер может быть подключен к Интернету: * '''Напрямую''' — обычно при подключении непосредственно к [[w:Модем|модему]] (DSL, кабельному или обычному аналоговому). * '''Через NAT''' — тогда ваш компьютер или [[w:Модем|модем]] имеет ''локальный''&nbsp; IP-адрес, из Интернета недоступный. Здесь [[w:NAT|NAT]] — это процесс трансляции локальных адресов во внешние. Благодаря этому процессу ваш компьютер получает доступ в Интернет. ''NAT автоматически делает порты вашей машины недоступными из Интернета для прямого входящего соединения''. == Находитесь ли вы за NAT == === IP-адрес компьютера === ; Windows Выберите команду главного меню '''Пуск > Выполнить...''' и наберите команду <code>cmd</code> В появившемся командном окне выполните команду <code>ipconfig</code> {|border=1 |bgcolor=#eeeeee| <pre style="padding: 5px">Windows IP Configuration Ethernet adapter Local Area Connection: IP . . . . . . . . . . . . : 192.168.0.73 Subnet Mask . . . . . . . . . . . : 255.255.224.0 Default Gateway . . . . . . . . . : 192.168.0.1 </pre> |} Первый из этих адресов — это IP-адрес вашего компьютера. Default Gateway — адрес шлюза, он же маршрутизатор (роутер). Subnet Mask определяет, какие адреса являются локальными (к ним компьютер будет обращаться напрямую), а какие нет (к ним обращение будет идти через маршрутизатор). ; Linux Выполните в терминале команду: <syntaxhighlight lang="bash">ifconfig</syntaxhighlight> === Локальный ли? === Три специальных диапазона IP-адресов зарезервированы для локальных сетей и в Интернете не используются: 10. 0. 0. 0 - 10.255.255.255 172. Х. 0. 0 - 172. Х.255.255 (где X - от 16 до 31) 192.168. X. 0 - 192.168. Х.255 (где X - от 0 до 255, обычно 0 или 1) Четвертый диапазон предназначен для самоназначаемых IP-адресов; в случае если на компьютере настроен DHCP-клиент и ему не удалось получить IP-адрес, он берёт случайный адрес из этого диапазона. Эти адреса предназначены для передачи информации только в пределах одной физической сети (так называемые Link-local-адреса, см. {{RFC|3927}}). 169.254. 0. 0 - 169.254.255.255 Если IP-адрес вашего компьютера находится в одном из этих диапазонов, то есть начинается с 10. или с 192.168. или с 172.nn. (где nn — от 16 до 31), то это ''локальный (внутренний)'' адрес и вы точно находитесь '''за NAT'''. === Внешний ли? === Зайдите на любую из этих страниц: [http://www.whatsmyip.org/ whatsmyip.org], [http://myipaddress.com/ myipaddress.com], [https://www.showmyip.com/ showmyip.com], [http://www.radiotoolbox.com/online_tools/whereami.php www.radiotoolbox.com], [http://2ip.ru/ 2ip.ru], [http://myip.ru/ myip.ru], [https://whatismyip.media/ whatismyip.media], [http://internet.yandex.ru/ internet.yandex.ru]. Эти сайты покажут вам адрес, под которым вас видят другие компьютеры в Интернете. Если он совпадает с IP-адресом вашего компьютера, то вы точно подключены к Интернету '''напрямую''' (то есть не за NAT) и дальше вам читать не нужно. === Остальные варианты === В остальных случаях возможны такие варианты: * вы находитесь за NAT, но ваш сетевой администратор зачем-то выбрал нестандартные внутренние адреса для вашей локальной сети * вы выходите в Интернет через прокси-сервер. Его надо настраивать в каждой программе, без этого выход в Интернет невозможен. Во многих случаях вы можете определить, есть ли между вами и Интернетом прокси-сервер, пользуясь, например, сайтом [http://www.lagado.com/proxy-test lagado.com/proxy-test]. <!-- или http://whatismyipaddress.com/staticpages/index.php/advanced-proxy-test --> ''Подключение через прокси в этом руководстве пока не рассматривается''. == Чей это NAT == <!-- Специфика работы NAT такова, что соединения, инициируемые вашим компьютером, прозрачно проходят через NAT-устройство в Интернет. Однако соединения, которые хотели бы с вами установить другие компьютеры из интернета, до вас дойти не могут. --> Если вы за NAT, то следующим шагом надо определить, где именно находится NAT-устройство. === Провайдеры === Такую ситуацию описывают разными словами: * провайдер предоставляет вам доступ в Интернет через NAT * у вас внутренний («серый») IP-адрес * провайдер не даёт вам внешний IP-адрес * вы подключены через локальную сеть провайдера Проще всего позвонить провайдеру и узнать. Или спросить у соседей с таким же подключением. Обычно такой провайдер предоставляет дополнительную услугу — внешний («белый») IP-адрес за отдельную плату. '''Без внешнего IP-адреса сделать себе доступный порт нельзя'''. Если вы находитесь за маршрутизатором в офисе или в многоквартирном доме, то в принципе ситуация такая же, но вы можете попробовать поискать подходы к местному админу. Кроме того, можно также попробовать [[Сетевой порт/Использование UPnP для перенаправления порта|использование UPnP для перенаправления порта (UPnP)]], вдруг в маршрутизаторе оставили его разрешённым. == Дополнительно == === Ваш NAT === В этом случае ваш внешний IP-адрес «принадлежит» вам лично, и вы практически всегда можете ваше NAT-устройство настроить и получить доступный порт. В качестве NAT может выступать компьютер, подключённый к Интернету напрямую; тогда ваш второй компьютер (для которого вам нужно открыть порт) получает доступ к Интернет через него с помощью встроенного в Windows <span title="Internet Connection Sharing - Совместное Использование Интернета" style="border-bottom:2px dashed gray; cursor:help">ICS</span> или сторонней программы, например, WinRoute. Про настройку порта в ICS смотрите [http://www.practicallynetworked.com/sharing/ics/icsconfiguration.htm тут] (ссылка на статью на английском). Но чаще это обычный домашний маршрутизатор, на настройке которого и фокусируется далее это руководство: [[Сетевой порт/Роутер и его настройки]]. === Двойной NAT === К сожалению, иногда бывает и так, что NAT есть и у вас, и у провайдера, то есть ваш компьютер находится за двумя NAT сразу. Это можно проверить, зайдя в настройки маршрутизатора, посмотрев на его внешний (WAN) IP-адрес и далее следуя вышеописанному сценарию (принадлежит ли ''этот'' адрес диапазонам локальных сетей, совпадает ли он с тем адресом, под которым вас видят в Интернете). 9t0tqb61zg9hg7a6mi5hi3hmhxmr99g Ruby/Справочник/Time 0 4466 270438 216972 2026-10-27T07:41:26Z Jcb 79968 270438 wikitext text/x-wiki ==Класс Time== Implements the extensions to the Time class that are described in the documentation for the time.rb library. ---- Extensions to time to allow comparisons with an early time class. ---- '''Примеси''' [[Ruby/Справочник/Comparable|Comparable]] ([[Ruby/Справочник/Comparable#Comparable#&lt;|&lt;]], [[Ruby/Справочник/Comparable#Comparable#&lt;=|&lt;=]], [[Ruby/Справочник/Comparable#Comparable#==|==]], [[Ruby/Справочник/Comparable#Comparable#&gt;|&gt;]], [[Ruby/Справочник/Comparable#Comparable#&gt;=|&gt;=]], [[Ruby/Справочник/Comparable#Comparable#between?|between?]]) '''Константы''' CommonYearMonthDays, LeapYearMonthDays, MonthValue, RFC2822_DAY_NAME, RFC2822_MONTH_NAME, ZoneOffset '''Методы класса''' [[#Time::_load|_load]], [[#Time::apply_offset|apply_offset]], [[#Time::at|at]], [[#Time::gm|gm]], [[#Time::httpdate|httpdate]], [[#Time::local|local]], [[#Time::make_time|make_time]], [[#Time::mktime|mktime]], [[#Time::month_days|month_days]], [[#Time::new|new]], [[#Time::now|now]], [[#Time::parse|parse]], [[#Time::rfc2822|rfc2822]], [[#Time::times|times]], [[#Time::utc|utc]], [[#Time::w3cdtf|w3cdtf]], [[#Time::xmlschema|xmlschema]], [[#Time::yaml_new|yaml_new]], [[#Time::zone_offset|zone_offset]], [[#Time::zone_utc?|zone_utc?]] '''Методы объекта''' [[#Time#+|+]], [[#Time#-|-]], [[#Time#&lt;=&gt;|&lt;=&gt;]], [[#Time#_dump|_dump]], [[#Time#asctime|asctime]], [[#Time#ctime|ctime]], [[#Time#day|day]], [[#Time#dst?|dst?]], [[#Time#eql?|eql?]], [[#Time#getgm|getgm]], [[#Time#getlocal|getlocal]], [[#Time#getutc|getutc]], [[#Time#gmt?|gmt?]], [[#Time#gmt_offset|gmt_offset]], [[#Time#gmtime|gmtime]], [[#Time#gmtoff|gmtoff]], [[#Time#hash|hash]], [[#Time#hour|hour]], [[#Time#httpdate|httpdate]], [[#Time#inspect|inspect]], [[#Time#isdst|isdst]], [[#Time#iso8601|iso8601]], [[#Time#localtime|localtime]], [[#Time#marshal_dump|marshal_dump]], [[#Time#marshal_load|marshal_load]], [[#Time#mday|mday]], [[#Time#min|min]], [[#Time#month|month]], [[#Time#mon|mon]], [[#Time#rfc2822|rfc2822]], [[#Time#rfc822|rfc822]], [[#Time#sec|sec]], [[#Time#strftime|strftime]], [[#Time#succ|succ]], [[#Time#to_a|to_a]], [[#Time#to_f|to_f]], [[#Time#to_i|to_i]], [[#Time#to_s|to_s]], [[#Time#to_yaml|to_yaml]], [[#Time#tv_sec|tv_sec]], [[#Time#tv_usec|tv_usec]], [[#Time#usec|usec]], [[#Time#utc?|utc?]], [[#Time#utc_offset|utc_offset]], [[#Time#utc|utc]], [[#Time#wday|wday]], [[#Time#xmlschema|xmlschema]], [[#Time#yday|yday]], [[#Time#year|year]], [[#Time#zone|zone]] ===Time::_load=== ---- <syntaxhighlight lang="ruby">Time._load(string) #=> time</syntaxhighlight> ---- Unmarshal a dumped <code>Time</code> object. ===Time::apply_offset=== ---- <syntaxhighlight lang="ruby">Time::apply_offset(year, mon, day, hour, min, sec, off)</syntaxhighlight> ---- (нет описания...) ===Time::at=== ---- <syntaxhighlight lang="ruby">Time.at( aTime ) #=> time Time.at( seconds [, microseconds] ) #=> time</syntaxhighlight> ---- Creates a new time object with the value given by <i>aTime</i>, or the given number of <i>seconds</i> (and optional <i>microseconds</i>) from epoch. A non-portable feature allows the offset to be negative on some systems. <syntaxhighlight lang="ruby">Time.at(0) #=> Wed Dec 31 18:00:00 CST 1969 Time.at(946702800) #=> Fri Dec 31 23:00:00 CST 1999 Time.at(-284061600) #=> Sat Dec 31 00:00:00 CST 1960</syntaxhighlight> ===Time::gm=== ---- <tt>Time.utc( year [, month, day, hour, min, sec, usec] ) =&gt; time </tt><tt>Time.utc( sec, min, hour, day, month, year, wday, yday, isdst, </tt><tt>tz ) =&gt; time Time.gm( year [, month, day, hour, min, sec, </tt><tt>usec] ) =&gt; time Time.gm( sec, min, hour, day, month, year, wday, </tt><tt>yday, isdst, tz ) =&gt; time</tt> ---- Creates a time based on given values, interpreted as UTC (GMT). The year must be specified. Other values default to the minimum value for that field (and may be <tt>nil</tt> or omitted). Months may be specified by numbers from 1 to 12, or by the three-letter English month names. Hours are specified on a 24-hour clock (0..23). Raises an <tt>ArgumentError</tt> if any values are out of range. Will also accept ten arguments in the order output by <tt>Time#to_a</tt>. <code>Time.utc(2000,&quot;jan&quot;,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 UTC 2000 Time.gm(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000</code> ===Time::httpdate=== ---- <tt>Time::httpdate(date)</tt> ---- Parses <tt>date</tt> as HTTP-date defined by {{RFC|2616}} and converts it to a Time object. ArgumentError is raised if <tt>date</tt> is not compliant with {{RFC|2616}} or Time class cannot represent specified date. See #httpdate for more information on this format. ===Time::local=== ---- <tt>Time.local( year [, month, day, hour, min, sec, usec] ) =&gt; </tt><tt>time Time.local( sec, min, hour, day, month, year, wday, yday, </tt><tt>isdst, tz ) =&gt; time Time.mktime( year, month, day, hour, min, </tt><tt>sec, usec ) =&gt; time</tt> ---- Same as <tt>Time::gm</tt>, but interprets the values in the local time zone. <code>Time.local(2000,&quot;jan&quot;,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 CST 2000</code> ===Time::make_time=== ---- <tt>Time::make_time(year, mon, day, hour, min, sec, sec_fraction, </tt><tt>zone, now)</tt> ---- (нет описания...) ===Time::mktime=== ---- <tt>Time.local( year [, month, day, hour, min, sec, usec] ) =&gt; </tt><tt>time Time.local( sec, min, hour, day, month, year, wday, yday, </tt><tt>isdst, tz ) =&gt; time Time.mktime( year, month, day, hour, min, </tt><tt>sec, usec ) =&gt; time</tt> ---- Same as <tt>Time::gm</tt>, but interprets the values in the local time zone. <code>Time.local(2000,&quot;jan&quot;,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 CST 2000</code> ===Time::month_days=== ---- <tt>Time::month_days(y, m)</tt> ---- (нет описания...) ===Time::new=== ---- <tt>Time.new -&gt; time</tt> ---- Document-method: now Synonym for <tt>Time.new</tt>. Returns a <tt>Time</tt> object initialized to the current system time. <b>Note:</b> The object created will be created using the resolution available on your system clock, and so may include fractional seconds. <code>a = Time.new #=&gt; Wed Apr 09 08:56:03 CDT 2003 b = Time.new #=> Wed Apr 09 08:56:03 CDT 2003 a == b #=> false "%.6f" % a.to_f #=> "1049896563.230740" "%.6f" % b.to_f #=> "1049896563.231466"</code> ===Time::now=== ---- <tt>Time.now -&gt; time</tt> ---- Synonym for <tt>Time.new</tt>. Returns a <tt>Time</tt> object initialized to the current system time. <b>Note:</b> The object created will be created using the resolution available on your system clock, and so may include fractional seconds. <code>a = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 b = Time.now #=> Wed Apr 09 08:56:03 CDT 2003 a == b #=> True "%.6f" % a.to_f #=> "1049896563.230740" "%.6f" % b.to_f #=> "1049896563.231466"</code> ===Time::parse=== ---- <tt>Time::parse(date, now=Time.now) {|year| ...}</tt> ---- Parses <tt>date</tt> using Date._parse and converts it to a Time object. If a block is given, the year described in <tt>date</tt> is converted by the block. For example: <code>Time.parse(...) {|y| y &lt; 100 ? (y &gt;= 69 ? y + 1900 : y + 2000) : y}</code> If the upper components of the given time are broken or missing, they are supplied with those of <tt>now</tt>. For the lower components, the minimum values (1 or 0) are assumed if broken or missing. For example: <code># Suppose it is &quot;Thu Nov 29 14:33:20 GMT 2001&quot; now and # your timezone is GMT: Time.parse("16:30") #=> Thu Nov 29 16:30:00 GMT 2001 Time.parse("7/23") #=> Mon Jul 23 00:00:00 GMT 2001 Time.parse("Aug 31") #=> Fri Aug 31 00:00:00 GMT 2001</code> Since there are numerous conflicts among locally defined timezone abbreviations all over the world, this method is not made to understand all of them. For example, the abbreviation &quot;CST&quot; is used variously as: <code>-06:00 in America/Chicago, -05:00 in America/Havana, +08:00 in Asia/Harbin, +09:30 in Australia/Darwin, +10:30 in Australia/Adelaide, etc.</code> Based on the fact, this method only understands the timezone abbreviations described in {{RFC|822}} and the system timezone, in the order named. (i.e. a definition in {{RFC|822}} overrides the system timezone definition.) The system timezone is taken from <tt>Time.local(year, 1, 1).zone</tt> and <tt>Time.local(year, 7, 1).zone</tt>. If the extracted timezone abbreviation does not match any of them, it is ignored and the given time is regarded as a local time. ArgumentError is raised if Date._parse cannot extract information from <tt>date</tt> or Time class cannot represent specified date. This method can be used as fail-safe for other parsing methods as: <code>Time.rfc2822(date) rescue Time.parse(date) Time.httpdate(date) rescue Time.parse(date) Time.xmlschema(date) rescue Time.parse(date)</code> A failure for Time.parse should be checked, though. ===Time::rfc2822=== ---- <tt>Time::rfc2822(date)</tt> ---- Parses <tt>date</tt> as date-time defined by {{RFC|2822}} and converts it to a Time object. The format is identical to the date format defined by {{RFC|822}} and updated by {{RFC|1123}}. ArgumentError is raised if <tt>date</tt> is not compliant with {{RFC|2822}} or Time class cannot represent specified date. See #rfc2822 for more information on this format. ===Time::times=== ---- <tt>Time.times =&gt; struct_tms</tt> ---- Deprecated in favor of <tt>Process::times</tt> ===Time::utc=== ---- <tt>Time.utc( year [, month, day, hour, min, sec, usec] ) =&gt; time </tt><tt>Time.utc( sec, min, hour, day, month, year, wday, yday, isdst, </tt><tt>tz ) =&gt; time Time.gm( year [, month, day, hour, min, sec, </tt><tt>usec] ) =&gt; time Time.gm( sec, min, hour, day, month, year, wday, </tt><tt>yday, isdst, tz ) =&gt; time</tt> ---- Creates a time based on given values, interpreted as UTC (GMT). The year must be specified. Other values default to the minimum value for that field (and may be <tt>nil</tt> or omitted). Months may be specified by numbers from 1 to 12, or by the three-letter English month names. Hours are specified on a 24-hour clock (0..23). Raises an <tt>ArgumentError</tt> if any values are out of range. Will also accept ten arguments in the order output by <tt>Time#to_a</tt>. <code>Time.utc(2000,&quot;jan&quot;,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 UTC 2000 Time.gm(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000</code> ===Time::w3cdtf=== ---- <tt>Time::w3cdtf(date)</tt> ---- (нет описания...) ===Time::xmlschema=== ---- <tt>Time::xmlschema(date)</tt> ---- Parses <tt>date</tt> as dateTime defined by XML Schema and converts it to a Time object. The format is restricted version of the format defined by ISO 8601. ArgumentError is raised if <tt>date</tt> is not compliant with the format or Time class cannot represent specified date. See #xmlschema for more information on this format. ===Time::yaml_new=== ---- <tt>Time::yaml_new( klass, tag, val )</tt> ---- (нет описания...) ===Time::zone_offset=== ---- <tt>Time::zone_offset(zone, year=Time.now.year)</tt> ---- (нет описания...) ===Time::zone_utc?=== ---- <tt>Time::zone_utc?(zone)</tt> ---- (нет описания...) ===Time#+=== ---- <tt>time + numeric =&gt; time</tt> ---- Addition---Adds some number of seconds (possibly fractional) to <i>time</i> and returns that value as a new time. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t + (60 * 60 * 24) #=> Thu Apr 10 08:56:03 CDT 2003</code> ===Time#-=== ---- <tt>time - other_time =&gt; float time - numeric =&gt; time</tt> ---- Difference---Returns a new time that represents the difference between two times, or subtracts the given number of seconds in <i>numeric</i> from <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t2 = t + 2592000 #=> Fri May 09 08:56:03 CDT 2003 t2 - t #=> 2592000.0 t2 - 2592000 #=> Wed Apr 09 08:56:03 CDT 2003</code> Более одного метода удовлетворяет вашему запросу. Вы можете уточнить ваш запрос, выбрав один из следующих методов: Time#&lt;=&gt;, Time#&lt;=&gt;===Time#_dump=== ---- <tt>time._dump =&gt; string</tt> ---- Dump <i>time</i> for marshaling. ===Time#asctime=== ---- <tt>time.asctime =&gt; string time.ctime =&gt; string</tt> ---- Returns a canonical string representation of <i>time</i>. <code>Time.now.asctime #=&gt; &quot;Wed Apr 9 08:56:03 2003&quot;</code> ===Time#ctime=== ---- <tt>time.asctime =&gt; string time.ctime =&gt; string</tt> ---- Returns a canonical string representation of <i>time</i>. <code>Time.now.asctime #=&gt; &quot;Wed Apr 9 08:56:03 2003&quot;</code> ===Time#day=== ---- <tt>time.day =&gt; fixnum time.mday =&gt; fixnum</tt> ---- Returns the day of the month (1..n) for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.day #=> 9 t.mday #=> 9</code> ===Time#dst?=== ---- <tt>time.isdst =&gt; true or false time.dst? =&gt; true or false</tt> ---- Returns <tt>true</tt> if <i>time</i> occurs during Daylight Saving Time in its time zone. <code>Time.local(2000, 7, 1).isdst #=&gt; true Time.local(2000, 1, 1).isdst #=> false Time.local(2000, 7, 1).dst? #=> true Time.local(2000, 1, 1).dst? #=> false</code> ===Time#eql?=== ---- <tt>time.eql?(other_time)</tt> ---- Return <tt>true</tt> if <i>time</i> and <i>other_time</i> are both <tt>Time</tt> objects with the same seconds and fractional seconds. ===Time#getgm=== ---- <tt>time.getgm =&gt; new_time time.getutc =&gt; new_time</tt> ---- Returns a new <tt>new_time</tt> object representing <i>time</i> in UTC. <code>t = Time.local(2000,1,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 CST 2000 t.gmt? #=> false y = t.getgm #=> Sun Jan 02 02:15:01 UTC 2000 y.gmt? #=> true t == y #=> true</code> ===Time#getlocal=== ---- <tt>time.getlocal =&gt; new_time</tt> ---- Returns a new <tt>new_time</tt> object representing <i>time</i> in local time (using the local time zone in effect for this process). <code>t = Time.gm(2000,1,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 UTC 2000 t.gmt? #=> true l = t.getlocal #=> Sat Jan 01 14:15:01 CST 2000 l.gmt? #=> false t == l #=> true</code> ===Time#getutc=== ---- <tt>time.getgm =&gt; new_time time.getutc =&gt; new_time</tt> ---- Returns a new <tt>new_time</tt> object representing <i>time</i> in UTC. <code>t = Time.local(2000,1,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 CST 2000 t.gmt? #=> false y = t.getgm #=> Sun Jan 02 02:15:01 UTC 2000 y.gmt? #=> true t == y #=> true</code> ===Time#gmt?=== ---- <tt>time.utc? =&gt; true or false time.gmt? =&gt; true or false</tt> ---- Returns <tt>true</tt> if <i>time</i> represents a time in UTC (GMT). <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t.utc? #=> false t = Time.gm(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000 t.utc? #=> true t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003 t.gmt? #=> false t = Time.gm(2000,1,1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000 t.gmt? #=> true</code> ===Time#gmt_offset=== ---- <tt>time.gmt_offset =&gt; fixnum time.gmtoff =&gt; fixnum </tt><tt>time.utc_offset =&gt; fixnum</tt> ---- Returns the offset in seconds between the timezone of <i>time</i> and UTC. <code>t = Time.gm(2000,1,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 UTC 2000 t.gmt_offset #=> 0 l = t.getlocal #=> Sat Jan 01 14:15:01 CST 2000 l.gmt_offset #=> -21600</code> ===Time#gmtime=== ---- <tt>time.gmtime =&gt; time time.utc =&gt; time</tt> ---- Converts <i>time</i> to UTC (GMT), modifying the receiver. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.gmt? #=> false t.gmtime #=> Wed Apr 09 13:56:03 UTC 2003 t.gmt? #=> true t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003 t.utc? #=> false t.utc #=> Wed Apr 09 13:56:04 UTC 2003 t.utc? #=> true</code> ===Time#gmtoff=== ---- <tt>time.gmt_offset =&gt; fixnum time.gmtoff =&gt; fixnum </tt><tt>time.utc_offset =&gt; fixnum</tt> ---- Returns the offset in seconds between the timezone of <i>time</i> and UTC. <code>t = Time.gm(2000,1,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 UTC 2000 t.gmt_offset #=> 0 l = t.getlocal #=> Sat Jan 01 14:15:01 CST 2000 l.gmt_offset #=> -21600</code> ===Time#hash=== ---- <tt>time.hash =&gt; fixnum</tt> ---- Return a hash code for this time object. ===Time#hour=== ---- <tt>time.hour =&gt; fixnum</tt> ---- Returns the hour of the day (0..23) for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.hour #=> 8</code> ===Time#httpdate=== ---- <tt>httpdate()</tt> ---- Returns a string which represents the time as rfc1123-date of HTTP-date defined by {{RFC|2616}}: <code>day-of-week, DD month-name CCYY hh:mm:ss GMT</code> Note that the result is always UTC (GMT). ===Time#inspect=== ---- <tt>time.inspect =&gt; string time.to_s =&gt; string</tt> ---- Returns a string representing <i>time</i>. Equivalent to calling <tt>Time#strftime</tt> with a format string of ``<tt>%a</tt> <tt>%b</tt> <tt>%d</tt> <tt>%H:%M:%S</tt> <tt>%Z</tt> <tt>%Y</tt>''. <code>Time.now.to_s #=&gt; &quot;Wed Apr 09 08:56:04 CDT 2003&quot;</code> ===Time#isdst=== ---- <tt>time.isdst =&gt; true or false time.dst? =&gt; true or false</tt> ---- Returns <tt>true</tt> if <i>time</i> occurs during Daylight Saving Time in its time zone. <code>Time.local(2000, 7, 1).isdst #=&gt; true Time.local(2000, 1, 1).isdst #=> false Time.local(2000, 7, 1).dst? #=> true Time.local(2000, 1, 1).dst? #=> false</code> ===Time#iso8601=== ---- <tt>iso8601(fraction_digits=0)</tt> ---- Alias for #xmlschema ===Time#localtime=== ---- <tt>time.localtime =&gt; time</tt> ---- Converts <i>time</i> to local time (using the local time zone in effect for this process) modifying the receiver. <code>t = Time.gm(2000, &quot;jan&quot;, 1, 20, 15, 1) t.gmt? #=> true t.localtime #=> Sat Jan 01 14:15:01 CST 2000 t.gmt? #=> false</code> ===Time#marshal_dump=== ---- <tt>marshal_dump()</tt> ---- undocumented ===Time#marshal_load=== ---- <tt>marshal_load(p1)</tt> ---- undocumented ===Time#mday=== ---- <tt>time.day =&gt; fixnum time.mday =&gt; fixnum</tt> ---- Returns the day of the month (1..n) for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.day #=> 9 t.mday #=> 9</code> ===Time#min=== ---- <tt>time.min =&gt; fixnum</tt> ---- Returns the minute of the hour (0..59) for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.min #=> 56</code> ===Time#mon=== ---- <tt>time.mon =&gt; fixnum time.month =&gt; fixnum</tt> ---- Returns the month of the year (1..12) for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.mon #=> 4 t.month #=> 4</code> ===Time#month=== ---- <tt>time.mon =&gt; fixnum time.month =&gt; fixnum</tt> ---- Returns the month of the year (1..12) for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.mon #=> 4 t.month #=> 4</code> ===Time#rfc2822=== ---- <tt>rfc2822()</tt> ---- Returns a string which represents the time as date-time defined by {{RFC|2822}}: <code>day-of-week, DD month-name CCYY hh:mm:ss zone</code> where zone is [+-]hhmm. If <tt>self</tt> is a UTC time, -0000 is used as zone. (еще известен как rfc822) ===Time#rfc822=== ---- <tt>rfc822()</tt> ---- Alias for #rfc2822 ===Time#sec=== ---- <tt>time.sec =&gt; fixnum</tt> ---- Returns the second of the minute (0..60)<i>[Yes, seconds really can </i><i>range from zero to 60. This allows the system to inject leap </i><i>seconds every now and then to correct for the fact that years are </i><i>not really a convenient number of hours long.]</i> for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t.sec #=> 4</code> ===Time#strftime=== ---- <tt>Time.strftime( string ) =&gt; string</tt> ---- Formats <i>time</i> according to the directives in the given format string. Any text not listed as a directive will be passed through to the output string. Format meaning: <code>%a - The abbreviated weekday name (``Sun'') %A - The full weekday name (``Sunday'') %b - The abbreviated month name (``Jan'') %B - The full month name (``January'') %c - The preferred local date and time representation %d - Day of the month (01..31) %H - Hour of the day, 24-hour clock (00..23) %I - Hour of the day, 12-hour clock (01..12) %j - Day of the year (001..366) %m - Month of the year (01..12) %M - Minute of the hour (00..59) %p - Meridian indicator (``AM'' or ``PM'') %S - Second of the minute (00..60) %U - Week number of the current year, starting with the first Sunday as the first day of the first week (00..53) %W - Week number of the current year, starting with the first Monday as the first day of the first week (00..53) %w - Day of the week (Sunday is 0, 0..6) %x - Preferred representation for the date alone, no time %X - Preferred representation for the time alone, no date %y - Year without a century (00..99) %Y - Year with century %Z - Time zone name %% - Literal ``%'' character t = Time.now t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003" t.strftime("at %I:%M%p") #=> "at 08:56AM"</code> ===Time#succ=== ---- <tt>time.succ =&gt; new_time</tt> ---- Return a new time object, one second later than <tt>time</tt>. ===Time#to_a=== ---- <tt>time.to_a =&gt; array</tt> ---- Returns a ten-element <i>array</i> of values for <i>time</i>: {<tt>[ sec, min, hour, </tt><tt>day, month, year, wday, yday, isdst, zone ]</tt>}. See the individual methods for an explanation of the valid ranges of each value. The ten elements can be passed directly to <tt>Time::utc</tt> or <tt>Time::local</tt> to create a new <tt>Time</tt>. <code>now = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t = now.to_a #=> [4, 56, 8, 9, 4, 2003, 3, 99, true, "CDT"]</code> ===Time#to_f=== ---- <tt>time.to_f =&gt; float</tt> ---- Returns the value of <i>time</i> as a floating point number of seconds since epoch. <code>t = Time.now "%10.5f" % t.to_f #=> "1049896564.13654" t.to_i #=> 1049896564</code> ===Time#to_i=== ---- <tt>time.to_i =&gt; int time.tv_sec =&gt; int</tt> ---- Returns the value of <i>time</i> as an integer number of seconds since epoch. <code>t = Time.now "%10.5f" % t.to_f #=> "1049896564.17839" t.to_i #=> 1049896564</code> ===Time#to_s=== ---- <tt>time.inspect =&gt; string time.to_s =&gt; string</tt> ---- Returns a string representing <i>time</i>. Equivalent to calling <tt>Time#strftime</tt> with a format string of ``<tt>%a</tt> <tt>%b</tt> <tt>%d</tt> <tt>%H:%M:%S</tt> <tt>%Z</tt> <tt>%Y</tt>''. <code>Time.now.to_s #=&gt; &quot;Wed Apr 09 08:56:04 CDT 2003&quot;</code> ===Time#to_yaml=== ---- <tt>to_yaml( opts = {} )</tt> ---- (нет описания...) ===Time#tv_sec=== ---- <tt>time.to_i =&gt; int time.tv_sec =&gt; int</tt> ---- Returns the value of <i>time</i> as an integer number of seconds since epoch. <code>t = Time.now "%10.5f" % t.to_f #=> "1049896564.17839" t.to_i #=> 1049896564</code> ===Time#tv_usec=== ---- <tt>time.usec =&gt; int time.tv_usec =&gt; int</tt> ---- Returns just the number of microseconds for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 "%10.6f" % t.to_f #=> "1049896564.259970" t.usec #=> 259970</code> ===Time#usec=== ---- <tt>time.usec =&gt; int time.tv_usec =&gt; int</tt> ---- Returns just the number of microseconds for <i>time</i>. <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 "%10.6f" % t.to_f #=> "1049896564.259970" t.usec #=> 259970</code> ===Time#utc=== ---- <tt>time.gmtime =&gt; time time.utc =&gt; time</tt> ---- Converts <i>time</i> to UTC (GMT), modifying the receiver. <code>t = Time.now #=&gt; Wed Apr 09 08:56:03 CDT 2003 t.gmt? #=> false t.gmtime #=> Wed Apr 09 13:56:03 UTC 2003 t.gmt? #=> true t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003 t.utc? #=> false t.utc #=> Wed Apr 09 13:56:04 UTC 2003 t.utc? #=> true</code> ===Time#utc?=== ---- <tt>time.utc? =&gt; true or false time.gmt? =&gt; true or false</tt> ---- Returns <tt>true</tt> if <i>time</i> represents a time in UTC (GMT). <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t.utc? #=> false t = Time.gm(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000 t.utc? #=> true t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003 t.gmt? #=> false t = Time.gm(2000,1,1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000 t.gmt? #=> true</code> ===Time#utc_offset=== ---- <tt>time.gmt_offset =&gt; fixnum time.gmtoff =&gt; fixnum </tt><tt>time.utc_offset =&gt; fixnum</tt> ---- Returns the offset in seconds between the timezone of <i>time</i> and UTC. <code>t = Time.gm(2000,1,1,20,15,1) #=&gt; Sat Jan 01 20:15:01 UTC 2000 t.gmt_offset #=> 0 l = t.getlocal #=> Sat Jan 01 14:15:01 CST 2000 l.gmt_offset #=> -21600</code> ===Time#wday=== ---- <tt>time.wday =&gt; fixnum</tt> ---- Returns an integer representing the day of the week, 0..6, with Sunday == 0. <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t.wday #=> 3</code> ===Time#xmlschema=== ---- <tt>xmlschema(fraction_digits=0)</tt> ---- Returns a string which represents the time as dateTime defined by XML Schema: <code>CCYY-MM-DDThh:mm:ssTZD CCYY-MM-DDThh:mm:ss.sssTZD</code> where TZD is Z or [+-]hh:mm. If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise. <tt>fractional_seconds</tt> specifies a number of digits of fractional seconds. Its default value is 0. (еще известен как iso8601) ===Time#yday=== ---- <tt>time.yday =&gt; fixnum</tt> ---- Returns an integer representing the day of the year, 1..366. <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t.yday #=> 99</code> ===Time#year=== ---- <tt>time.year =&gt; fixnum</tt> ---- Returns the year for <i>time</i> (including the century). <code>t = Time.now #=&gt; Wed Apr 09 08:56:04 CDT 2003 t.year #=> 2003</code> ===Time#zone=== ---- <tt>time.zone =&gt; string</tt> ---- Возвращает наименовние часового поиса. В Ruby 1.8 возвращает UTC , а не GMT для времени UTC. <code>t = Time.gm(2000, &quot;jan&quot;, 1, 20, 15, 1) t.zone #=> "UTC" t = Time.local(2000, "jan", 1, 20, 15, 1) t.zone #=> "CST"</code> Пример Ruby 2.0 <code>t=Time.new t.zone #=> OMST</code> [[Категория:Ruby|Справочник/Time]] a463mdv855alx8rpyy1ax1rb7ixts08 Python/Учебник Python 3.1 0 5101 270436 265141 2026-10-27T07:39:09Z Jcb 79968 270436 wikitext text/x-wiki {{Python/DocPart}} {|class="standard" |''Исходный текст'' |http://docs.python.org/3.1/tutorial/ |- |''Автор'' |Фред Л. Дрейк мл. (Fred L. Drake, Jr. ) [https://docs.python.org/3.1/about.html и другие] |- |''Релиз'' |3.1.5 |- |''Версия от'' |09 апреля 2012 |} __TOC__ === Описание === Python — мощный и простой для изучения язык программирования. В нём предоставлены проработанные высокоуровневые структуры данных и простой, но эффективный подход к объектно-ориентированному программированию. Сочетание изящного синтаксиса и динамической типизации, совмещённых с интерпретируемой сущностью, делает Python идеальным языком для написания сценариев и ускоренной разработки приложений в различных сферах и на большинстве платформ. Интерпретатор Python и разрастающаяся стандартная библиотека находятся в свободном доступе в виде исходников и бинарных файлов для всех основных платформ на официальном сайте Python http://www.python.org и могут распространяться без ограничений. Кроме этого на сайте содержатся дистрибутивы и ссылки на многочисленные модули третьих сторон для языка Python, различные программы и инструменты, а также дополнительная документация. Интерпретатор Python может быть легко расширен с помощью новых функций и типов данных, написанных на C/C++ (или других языках, к которым можно получить доступ из C). Также Python можно применять как язык расширений для настраиваемых приложений. Этот учебник неформально представляет читателю основные концепции и возможности языка и системы Python. Полезно держать интерпретатор Python под рукой для получения практического опыта, но при этом все примеры самодостаточны, так что учебник вполне возможно читать вне сети. Описание стандартных объектов и модулей вы можете найти в [[Справочник по библиотеке Python 3.1|справочнике по библиотеке Python]]. [[Справочник по языку Python 3.1|Руководство по языку]] даёт более формальное описание языка. Перед написанием расширений на C/C++ ознакомьтесь с [[Расширение и встраивание - Python 3.1|руководством по расширению и встраиванию в интерпретатор]] и [[Python 3.1 - C API|справочником по Python/C API]]. Существует также несколько книг, в которых подробно рассмотрен язык Python. Этот учебник не претендует на звание всеобъемлющего и не описывает каждую особенность Python: он даже не описывает ''все'' его часто используемые особенности. Вместо этого он знакомит читателя с наиболее заслуживающими внимания из них и даёт вам представление о стиле и ''привкусе'' языка. После прочтения учебника вы сможете писать и читать программы и модули, написанные на Python, и будете готовы узнать больше о различных модулях библиотеки Python, описанных в [[Справочник по библиотеке Python 3.1|справочнике по библиотеке Python]]. Кроме того, будет нелишним полистать [[Глоссарий Python 3.1|Глоссарий]]. == Разжигая ваш аппетит !== Если вы много работаете за компьютером — то периодически обнаруживаете задачи, которые хотели бы автоматизировать. Например, вы были бы не против ускорить операцию поиска и замены большого количества текстовых файлов, или как-то своеобразно переименовать и отсортировать набор фотографий. Возможно, вам хотелось бы написать небольшую базу данных на заказ, специализированное GUI-приложение или простую игру. Если вы профессиональный разработчик программных продуктов — вероятно, вы привыкли работать с несколькими библиотеками на C/C++/Java, но находите обычный цикл написания/компиляции/тестирования/перекомпиляции кода чересчур медленным. Возможно, вы пишете набор тестов для такой библиотеки и процесс написания тестирующего кода воспринимается утомительным. Или же вы написали программу, которая должна использовать специальный язык для расширений и не хотите проектировать и разрабатывать полностью новый язык для вашего приложения. Python — язык, который вам подойдёт. Вы можете написать шелл-сценарий для Unix или использовать пакетные файлы Windows для некоторых из этих задач, но шелл-сценарии хороши лишь для перемещения файлов и замены текстовых данных — они вряд ли подойдут для написания приложений, снабженных графическим интерфейсом, или для игр. Вы можете написать программу на C/C++/Java, но разработка может занять довольно много времени — даже на то, чтобы получить первый рабочий набросок, его требуется немало. Python — проще в использовании, доступен на операционных системах Windows, Mac OS X и Unix, и поможет сделать работу намного быстрее. Даже учитывая лёгкость использования, Python — полноценный язык программирования, предлагающий много больше возможностей для структурирования и поддержки крупных программ, чем могут позволить себе шелл-сценарии или пакетные файлы. С другой стороны, Python также предоставляет намного больше информации для отладки ошибок чем C и, будучи ''сверх-высокоуровневым-языком'', имеет встроенные высокоуровневые типы данных — такие, как гибкие массивы и словари. Благодаря наличию обобщённых типов данных Python применим для более широкого круга приложений, чем Awk или даже Perl, и при этом очень многие вещи остаются в языке Python как минимум настолько же простыми, насколько просты в упомянутых языках. Python позволяет вам разделить вашу программу на модули, которые могут быть заново использованы в других программах на Python. Он поставляется вместе с внушительной коллекцией стандартных модулей, которые вы можете использовать в качестве фундамента ваших программ; или в качестве примеров для того, чтобы начать изучение Python. Многие из этих модулей предоставляют различную полезную функциональность: например, ввод-вывод для файлов, системные вызовы, сокеты, и даже инструменты для создания графического пользовательского интерфейса&nbsp;— например, Tk. Python — интерпретируемый язык, и это может сохранить вам немало времени при разработке — в компиляции и связывании нет необходимости. Интерпретатор может использоваться в интерактивном режиме, что позволяет легко экспериментировать с возможностями языка, писать программы-однодневки или проверять функции во время разработки программ методом снизу-вверх. И, кроме всего прочего — это удобный настольный калькулятор. Python даёт возможность писать компактные и удобочитаемые программы. Программы, написанные на Python, отличаются большей краткостью, чем эквиваленты на C, C++ или Java по нескольким причинам: * высокоуровневые типы данных позволяют вам выражать сложные операции в одной инструкции; * группировка инструкций выполняется отступами, а не операторными скобками; * нет необходимости в описании переменных или аргументов. Python ''расширяем'': если вы знаете, как программировать на C, то вам легко будет добавить к интерпретатору новую встроенную функцию или модуль, либо для выполнения критических операции на максимальной скорости, либо для связывания программы на Python с библиотеками, которые могут быть доступны только в бинарной форме (например, зависящие от поставщика графические библиотеки). Как только вы приобретете соответствующий опыт, вы сможете привязать интерпретатор Python к приложению, написанному на C, чтобы использовать его как язык расширений или командный язык этого приложения. Кстати, язык назван в честь шоу «Летающий цирк Монти Пайтона» на BBC и не имеет ничего общего с рептилиями. Ссылки на скетчи Монти Пайтона в документации не только позволены, но и приветствуются! Теперь, когда ваш интерес к Python полностью пробужден, вам наверняка захочется изучить его более детально. В связи с тем, что лучший способ выучить язык — использовать его, автор приглашает вас использовать интерпретатор Python в процессе чтения. В следующей главе описана механика использования интерпретатора. Это довольно приземленная информация, но она необходима для работы с примерами, которые будут представлены позже. Остальная часть учебника описывает различные возможности языка и системы Python за счёт примеров — начиная с простых выражений, операторов и типов данных, рассматривая функции и модули, и заканчивая прикосновением к таким продвинутым концепциям как исключения и определённые пользователем<ref>''(Прим. перев.)'' Здесь и далее по учебнику понятия пользователя и программиста в некоторые моменты пересекаются, ввиду того что последний рассматривается как «пользователь языка». Обычно это понятно из контекста, но тем не менее, на всякий случай, поясняю.</ref> классы. == Использование интерпретатора Python == === Запуск интерпретатора === Интерпретатор Python после установки располагается, обычно, по пути <tt>/usr/local/bin/python3.1</tt> — на тех компьютерах, где этот путь доступен. Добавление каталога <tt>/usr/local/bin</tt> к пути поиска Unix-шелла (переменная <tt>PATH</tt>) позволит запустить интерпретатор набором команды <code>python3.1</code>salut прямо из шелла<ref>В случае операционных систем UNIX, интерпретатор версии 3.1 по умолчанию устанавливается с исполняемым файлом, имеющим имя, отличное от <tt>python</tt> — дабы не иметь конфликтов с (возможно) установленным исполняемым файлом версии 2.6</ref>. Поскольку выбор каталога, в котором будет обитать интерпретатор, осуществляется при его установке, то возможны и другие варианты — посоветуйтесь с вашим Python-гуру или системным администратором. (Например, путь <tt>/usr/local/python</tt> тоже популярен в качестве альтернативного расположения.) На машинах с ОС Windows, инсталляция Python обычно осуществляется в каталог <tt>C:\Python31</tt>, но и он может быть изменён во время установки. Чтобы добавить этот каталог к вашему пути поиска, вы можете набрать в окне DOS следующую команду, в ответ на приглашение: <code>set path=%path%;C:\python31</code> При наборе символа конца файла (<tt>Ctrl-D</tt> в Unix, <tt>Ctrl-Z</tt> в Windows) в ответ на основное приглашение интерпретатора, последний будет вынужден закончить работу с нулевым статусом выхода. Если это не сработает — вы можете выйти из интерпретатора путём ввода следующих команд: <syntaxhighlight lang="python">import sys; sys.exit()</syntaxhighlight> Особенности редактирования строк в интерпретаторе не оказываются обычно чересчур сложными. Те, кто установил интерпретатор на машину Unix, потенциально имеют поддержку библиотеки <tt>GNU readline</tt>, обеспечивающей усовершенствованное интерактивное редактирование и сохранение истории. Самый быстрый, наверное, способ проверить, поддерживается ли расширенное редактирование командной строки, заключается в нажатии <tt>Ctrl-P</tt> в ответ на первое полученное приглашение Python. Если вы услышите сигнал — значит вам доступно редактирование командной строки — тогда обратитесь к [[Учебник Python 3.1 — Приложения#Интерактивное редактирование входных данных и подстановка истории|Приложению об Интерактивном редактировании входных данных]] за описанием клавиш. Если на ваш взгляд ничего не произошло или отобразился символ <tt>^P</tt> — редактирование командной строки недоступно — удалять символы из текущей строки возможно будет лишь использованием клавиши <tt>Backspace</tt>. Интерпретатор ведёт себя сходно шеллу Unix: если он вызван, когда ''стандартный ввод'' привязан к устройству <tt>tty</tt> — он считывает и выполняет команды в режиме диалога; будучи вызванным с именем файла в качестве параметра или с файлом, назначенным на ''стандартный ввод'' — он читает и выполняет сценарий из этого файла. Другой способ запустить интерпретатор — директива <code>'''python -c''' ''команда'' <tt>[arg]</tt> ...</code> — при её использовании поочередно выполняются инструкции(-ция) из ''команды'' (как при использовании опции '''-c''' Unix-шелла). В связи с тем, что инструкции Python часто содержат пробелы или другие специальные для шелла символы, рекомендуется заключать ''команды'' полностью в одинарные кавычки. Некоторые модули Python оказываются полезными при использовании их в качестве сценариев. Они могут быть запущены в этом виде командой <code>'''python -m''' ''модуль'' <tt>[arg]</tt> ...</code> — таким образом исполняется исходный файл модуля (как произошло бы, если бы вы ввели его полное имя в командной строке). Обратите внимание на различие между командами <tt>python file</tt> и <tt>python <file</tt>. В последнем случае запросы на ввод из программы, такие как вызов <code>sys.stdin.read()</code>, удовлетворяются из самого файла. Поскольку файл уже был прочитан до конца ещё до начала выполнения программы — символ конца файла будет обнаружен программой незамедлительно. В большинстве случаев (это, чаще всего, и есть те ситуации, которых вы ожидали) вызовы удовлетворяются независимо от того, файл или устройство привязаны к стандартному вводу интерпретатора Python. При использовании файла сценария иногда полезно иметь возможность запустить сценарий и затем войти в интерактивный режим. Это может быть сделано через указание параметра '''-i''' перед именем сценария. (Этот способ не сработает, если сценарий считывается со стандартного ввода — по той самой причине, которая описана в предыдущем абзаце). ==== Передача параметров ==== В случае, если интерпретатору известны имя сценария и дополнительные параметры, с которыми он вызван, все они передаются сценарию в переменной <code>sys.argv</code>, представляющей собой список (<code>list</code>) строк. Длина (<code>length</code>) списка — минимум, единица; если не переданы ни имя сценария, ни аргументы — то <code>sys.argv[0]</code> содержит пустую строку. Когда в качестве имени сценария передан <code>'-'</code> (означает ''стандартный ввод''), <code>sys.argv[0]</code> устанавливается в <code>'-'</code>. Если используется директива '''-c''' ''команда'' — <code>sys.argv[0]</code> содержит <code>'-c'</code>. В случае, если используется директива '''-m''' ''модуль'' — то <code>sys.argv[0]</code> устанавливается равным полному имени модуля по расположению. Опции, обнаруженные после сочетаний '''-c''' ''команда'' или '''-m''' ''модуль'' не обрабатываются интерпретатором Python, но остаются в переменной <code>sys.argv</code>, дабы обеспечить возможность отслеживания в самой команде или в модуле. ==== Интерактивный режим ==== Если команды считываются с <tt>tty</tt> — говорят, что интерпретатор находится в ''интерактивном режиме'' (режиме диалога). В этом режиме он приглашает к вводу следующей команды, отобразив ''основное приглашение''<ref>''(Прим. перев.)'' <tt>primary prompt</tt> — ''зд.'', основное приглашение: приглашение к вводу команды или нескольких команд (сценария);</ref> (обычно это три знака «больше-чем» — <tt>&gt;&gt;&gt;</tt>); в то же время, для ''продолжающих строк''<ref>''(Прим. перев.)'' <tt>continuation lines</tt> — ''зд.'', продолжающие строки (строки продолжения): строки, продолжающие текст команды (оператора, выражения), или раскрывающие внутреннее устройство внешнего оператора (команды, выражения), в последнем случае определяются дополнительным отступом от края — углублением в структуру;</ref> выводится ''вспомогательное приглашение''<ref>''(Прим. перев.)'' <tt>secondary prompt</tt> — ''зд.'', вспомогательное приглашение: приглашение к продолжению ввода команды или набора команд (сценария) с использованием ''продолжающих строк'';</ref> (по умолчанию — три точки — <tt>...</tt>). Перед выводом первого приглашения интерпретатор отображает приветственное сообщение, содержащее номер его версии и пометку о правах копирования: <syntaxhighlight lang="python">$ python3.1 Python 3.1a1 (py3k, Sep 12 2007, 12:21:02) [GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>></syntaxhighlight> ''Продолжающие строки'' используются в случаях, когда необходимо ввести многострочную конструкцию. Взгляните, например, на следующий оператор <code>if</code><ref>''(Прим. перев.)'' Здесь и далее тексты некоторых исходных кодов также будут переведены в примечаниях (вместе с ключевыми словами, поэтому их нельзя будет запустить в интерпретаторе), чтобы показать их смысл или задумку, которые не всегда очевидны без перевода (если он вам нужен :)):<br /><br /> <code style="background-color: inherit !important;"><span style="color: #aaa">>>></span> мир_плоский = 1<br/> <span style="color: #aaa">>>></span> '''если''' мир_плоский:<br/> <span style="color: #aaa">...</span>&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("Будьте осторожны — не упадите!")<br/> <span style="color: #aaa">...</span> <br/> <span style="color: #030">Будьте осторожны — не упадите!</span></code><br /></ref>: <syntaxhighlight lang="python">>>> the_world_is_flat = 1 >>> if the_world_is_flat: ... print("Be careful not to fall off!") ... Be careful not to fall off!</syntaxhighlight> === Интерпретатор и его окружение === ==== Обработка ошибок ==== В случае появления ошибки интерпретатор выводит сообщение об ошибке, завершая его стеком вызовов. В интерактивном режиме он снова возвращается в состояние приглашения для ввода команд; если ввод происходит из файла — интерпретатор выходит с ненулевым статусом, сразу после распечатки стека вызовов. (Исключения, обрабатываемые в блоке <code>except</code> оператора <code>try</code> в этом контексте не считаются ошибками.) Некоторые ошибки исключительно фатальны и вызывают собой принудительное завершение работы с ненулевым статусом — это применимо к внутренним противоречиям языка и к некоторым случаям нехватки памяти. Все сообщения об ошибках выводятся в ''стандартный поток ошибок'' (<tt>error stream</tt>). Обычный вывод исполняемых команд направляется в ''стандартный вывод''. Нажатие клавиш прерывания процесса (обычно <tt>Ctrl-C</tt> или <tt>DEL</tt>), в ответ на приглашение в основном или вспомогательном режиме, отменяет ввод и возвращает вас к основному приглашению.<ref>Известная проблема в пакете <tt>GNU Readline</tt> может этому помешать.</ref> Символ прерывания, набранный во время выполнения какой-либо команды порождает исключение <code>KeyboardInterrupt</code>, которое, в свою очередь, может быть перехвачено оператором <code>try</code>. ==== Исполняемые сценарии на Python ==== На Unix-системах семейства BSD сценарии на Python могут быть сделаны исполняемыми, также как и шелл-сценарии, путём добавления следующей строки <code>#! /usr/bin/env python3.1</code> (предполагается, что интерпретатор может быть найден по одному из путей, указанных в пользовательской переменной <tt>PATH</tt>) в начало сценария и установки файла в исполняемый режим. Символы <tt>#!</tt> должны быть первыми символами в файле. На некоторых платформах строка должна оканчиваться символом конца строки в стиле Unix (<tt>'\n'</tt>), а не в стиле Windows (<tt>'\r\n'</tt>). Заметьте, что символ решётки <tt>'#'</tt> используется в Python для указания начала комментария. Исполняемый режим (или разрешение на исполнение) может быть установлен сценарию использованием команды '''chmod''': <code>$ chmod +x myscript.py</code> У систем с операционной системой Windows нет такого понятия, как исполняемый режим. Установщик Python автоматически связывает файлы <tt>.py</tt> с файлом <tt>python.exe</tt>, таким образом двойной клик на файле Python запустит его в виде сценария. Расширение может быть и <tt>.pyw</tt> в случае, если окно консоли (которое, обычно, отображается) при запуске сценария подавляется. ==== Кодировка исходных файлов ==== По умолчанию, исходники Python считаются созданными в кодировке <tt>UTF-8</tt>. В этой кодировке в строковых литералах, идентификаторах и комментариях могут быть использованы символы большинства языков мира — учитывая то, что стандартная библиотека Python использует символы <tt>ASCII</tt> для именования идентификаторов — и этому соглашению должен следовать любой переносимый код. Для корректного отображения всех этих символов, ваш редактор должен опознавать файл как закодированный в <tt>UTF-8</tt> и должен использовать шрифт, который содержит все символы, используемые в файле. Также, есть возможность указать другую кодировку для исходных файлов. Для этого нужно добавить специальный комментарий следом за строкой <tt>#!</tt>, дабы описать кодировку исходного файла: <code># -*- coding: encoding -*-</code> Если используется это описание — всё, что находится в этом файле будет опознаваться как имеющее соответствующую кодировку ''<tt>encoding</tt>'', а не <tt>UTF-8</tt>. Список возможных кодировок представлен в [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке]] — в разделе, описывающем модуль [[Справочник по библиотеке Python 3.1#codecs|codecs]]. Например, если выбранный вами редактор не поддерживает файлы, закодированные <tt>UTF-8</tt> и требует применения какой-либо другой кодировки, допустим <tt>Windows-1252</tt>, вы можете написать: <code># -*- coding: cp-1252 -*-</code> И, с этого момента, использовать в исходных файлах только символы из таблицы символов <tt>Windows-1252</tt>. Устанавливающий (отличную от установленной по умолчанию) кодировку специальный комментарий должен являться первой или второй строкой файла. ==== Интерактивный файл запуска ==== Если вы используете Python интерактивно — часто бывает удобным выполнить некоторые стандартные команды перед запуском интерпретатора. Вы можете сделать это, установив переменную окружения с именем <tt>PYTHONSTARTUP</tt> равной имени файла, содержащего ваши команды запуска. Способ схож с использованием файла <tt>.profile</tt> в Unix-шелле. Этот файл читается только в интерактивных сессиях, но не в случае считывания команд из сценария, и не в случае, если <tt>/dev/tty</tt> назначен как независимый источник команд (который в других случаях ведет себя сходно интерактивным сессиям). Файл исполняется в том же пространстве имён, что и исполняемые команды — поэтому объекты и импортированные модули, которые он определяет могут свободно использоваться в интерактивной сессии. Также в этом файле вы можете изменить приглашения: <code>sys.ps1</code> и <code>sys.ps2</code>. Если вы хотите прочитать дополнительный файл запуска из текущего каталога — вы можете использовать код вроде: <syntaxhighlight lang="python">if os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read())</syntaxhighlight> Если вы хотите использовать файл запуска в сценарии — вам нужно будет указать это явно: <syntaxhighlight lang="python">import os filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): exec(open(filename).read())</syntaxhighlight> == Неформальное введение в Python == В приведенных далее примерах, ввод и вывод различаются присутствием и отсутствием приглашений соответственно (приглашениями являются <tt>>>></tt> и <tt>...</tt>): чтобы воспроизвести пример — вам нужно ввести всё, что следует за приглашением, после его появления; строки, не начинающиеся с приглашений являются выводом интерпретатора. Обратите внимание, что строка, в которой содержится лишь вспомогательное приглашение («<tt>... </tt>») означает, что вам нужно ввести пустую строку — этот способ используется для завершения многострочных команд. Большинство примеров в этом руководстве — даже те, которые вводятся в интерактивном режиме — содержат комментарии. Комментарии в Python начинаются с символа решетки # (<tt>hash</tt>) — и продолжаются до физического конца строки. Комментарии могут находиться как в начале строки, так и следовать за пробельными символами или кодом — но не содержаться внутри строки. Символ решётки в строке остаётся лишь символом решётки. Поскольку комментарии предназначены для того, чтобы сделать код более понятным, и не интерпретируются Python — при вводе примеров они могут быть опущены. Несколько примеров: <syntaxhighlight lang="python"># это первый комментарий SPAM = 1 # а это второй комментарий # ... и наконец третий! STRING = "# Это не комментарий."</syntaxhighlight> === Использование Python в качестве калькулятора === Давайте опробуем несколько простых команд Python. Запустите интерпретатор и дождитесь появления основного приглашения — <tt>>>></tt>. (Это не должно занять много времени.) ==== Числа ==== Вот вам маленький пример: print("Привет, как дела?") Поведение интерпретатора сходно поведению калькулятора: вы вводите выражение, а в ответ он выводит значение. Синтаксис выражений привычен: операции <code>+</code>, <code>-</code>, <code>*</code> и <code>/</code> работают так же как и в большинстве других языков (например, Паскале или C); для группировки можно использовать скобки. Например: <syntaxhighlight lang="python">>>> 2+2 4 >>> # Это комментарий ... 2+2 4 >>> 2+2 # а вот комментарий на одной строке с кодом 4 >>> (50-5*6)/4 5.0 >>> 8/5 # При делении целых чисел дробные части не теряются 1.6000000000000001 </syntaxhighlight> ''Заметьте'': Вы можете получить результат, несколько отличный от представленного: результаты деления с плавающей запятой могут различаться на разных системах. Позже мы расскажем о том, как контролировать вывод чисел с плавающей запятой. Здесь использован наиболее информативный вариант вывода этого значения, а не более легко-читаемый, какой возможен: <syntaxhighlight lang="python">>>> print(8/5) 1.6 </syntaxhighlight> Чтобы учебник читался легче, мы будем показывать упрощённый вывод чисел с плавающей точкой и объясним позже, почему эти два способа отображения чисел с плавающей точкой стали различными. Обратитесь к приложению [[Учебник Python 3.1 — Приложения#Арифметика с плавающей точкой - Проблемы и ограничения|Арифметика с плавающей точкой: Проблемы и ограничения]], чтобы ознакомиться с подробным обсуждением. Для получения целого результата при делении целых чисел, отсекая дробные результаты, предназначена другая операция: <tt>//</tt>: <syntaxhighlight lang="python">>>> # Деление целых чисел возвращает округлённое к минимальному значение: ... 7//3 2 >>> 7//-3 -2</syntaxhighlight> Знак равенства (<code>'='</code>) используется для присваивания переменной какого-либо значения. После этого действия в интерактивном режиме ничего не выводится: <syntaxhighlight lang="python">>>> width = 20 >>> height = 5*9 >>> width * height 900</syntaxhighlight> Значение может быть присвоено нескольким переменным одновременно: <syntaxhighlight lang="python">>>> x = y = z = 0 # Нулевые x, y и z >>> x 0 >>> y 0 >>> z 0</syntaxhighlight> Переменные должны быть ''определены'' (<tt>defined</tt>) (должны иметь присвоенное значение) перед использованием, иначе будет сгенерирована ошибка: <syntaxhighlight lang="python">>>> # попытка получить доступ к неопределённой переменной ... n Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'n' is not defined</syntaxhighlight> Присутствует полная поддержка операций с плавающей точкой; операции над операндами смешанного типа конвертируют целочисленный операнд в число с плавающей запятой: <syntaxhighlight lang="python">>>> 3 * 3.75 / 1.5 7.5 >>> 7.0 / 2 3.5</syntaxhighlight> Поддерживаются и комплексные числа, добавлением к мнимым частям суффикса <code>j</code> или <code>J</code>. Комплексные числа с ненулевым вещественным компонентом записываются в виде <code>(''<вещественная_часть>''+''<мнимая_часть>''j)</code>, или могут быть созданы с помощью функции <code>complex(''<вещественная_часть>'', ''<мнимая_часть>'')</code>. <syntaxhighlight lang="python">>>> 1j * 1J (-1+0j) >>> 1j * complex(0, 1) (-1+0j) >>> 3+1j*3 (3+3j) >>> (3+1j)*3 (9+3j) >>> (1+2j)/(1+1j) (1.5+0.5j)</syntaxhighlight> Комплексные числа всегда представлены в виде двух чисел с плавающей запятой — вещественной и мнимой частями. Для получения этих частей из комплексного числа <code>z</code> используется <code>z.real</code> и <code>z.imag</code> соответственно. <syntaxhighlight lang="python">>>> a=1.5+0.5j >>> a.real 1.5 >>> a.imag 0.5</syntaxhighlight> Функции конвертации (приведения) к вещественным и целым числам (<code>float()</code>, <code>int()</code>) не работают с комплексными числами, так как нет единственно правильного способа сконвертировать комплексное число в вещественное. Используйте функцию <code>abs(z)</code> чтобы получить ''модуль'' числа (в виде числа с плавающей точкой) или <code>z.real</code> чтобы получить его вещественную часть: <syntaxhighlight lang="python">>>> a=3.0+4.0j >>> float(a) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: can`t convert complex to float; use abs(z) >>> a.real 3.0 >>> a.imag 4.0 >>> abs(a) # sqrt(a.real**2 + a.imag**2) 5.0 >>></syntaxhighlight> В интерактивном режиме последнее выведенное выражение сохраняется в переменной <code>_</code>. Это значит, что если вы используете Python в качестве настольного калькулятора — всегда есть способ продолжить вычисления с меньшими усилиями, например: <syntaxhighlight lang="python">>>> tax = 12.5 / 100 >>> price = 100.50 >>> price * tax 12.5625 >>> price + _ 113.0625 >>> round(_, 2) 113.06 >>></syntaxhighlight> Эта переменная для пользователя должна иметь статус ''только для чтения''. Не навязывайте ей значение собственноручно — вы создадите независимую переменную с таким же именем, скрывающую встроенную переменную вместе с её магическими свойствами. ==== Строки ==== Помимо чисел, Python может работать со строками, которые, в свою очередь, могут быть описаны различными способами. Строки могут быть заключены в одинарные или двойные кавычки: <syntaxhighlight lang="python">>>> 'spam eggs' 'spam eggs' >>> 'doesn\'t' "doesn't" >>> "doesn't" "doesn't" >>> '"Yes," he said.' '"Yes," he said.' >>> "\"Yes,\" he said." '"Yes," he said.' >>> '"Isn\'t," she said.' '"Isn\'t," she said.'</syntaxhighlight> Интерпретатор выводит результаты операций над строками тем же способом, каким они были введены: обрамляя в кавычки, и, кроме того, экранируя обратными слэшами внутренние кавычки и другие забавные символы — для того, чтобы отобразить точное значение. Строка заключается в двойные кавычки, если строка содержит одинарные кавычки и ни одной двойной, иначе она заключается в одинарные кавычки. Повторимся, функция <tt>print()</tt> предоставляет более читаемый вывод. Строковые литералы могут быть разнесены на несколько строк различными способами. Могут быть использованы ''продолжающие строки'', с обратным слэшем в качестве последнего символа строки, сообщающим о том, что следующая строка есть продолжение текущей<ref>''(Прим. перев.):''<syntaxhighlight lang="python">hello = "Это довольно длинная строка, содержащая\n\ несколько строк текста — такой вы бы представили её в C.\n\ Обратите внимание, что пробельное пространство в начале строки\ имеет значение." print(hello)</syntaxhighlight></ref>: <syntaxhighlight lang="python">hello = "This is a rather long string containing\n\ several lines of text just as you would do in C.\n\ Note that whitespace at the beginning of the line is\ significant." print(hello)</syntaxhighlight> Обратите внимание, что новые строки все ещё нужно подключать в строку через <code>\n</code>; символ новой строки, перед которым идёт обратный слэш — не обрабатывается. Запуск примера выведет следующее: <pre>This is a rather long string containing several lines of text just as you would do in C. Note that whitespace at the beginning of the line is significant.</pre> Если мы объявим строковой литерал ''сырым'' (<tt>raw</tt>)<ref>''(Прим. перев.)'' ''raw string'' — для описания ''сырой строки'' (не требующей последующей обработки) используется префикс '''<code>r</code>'''.</ref> — символы <code>\n</code> не будут конвертированы в новые строки, но и обратный слэш в конце строки, и символ новой строки в исходном коде — будут добавлены в строку в виде данных. Следовательно, код из примера: <syntaxhighlight lang="python">hello = r"This is a rather long string containing\n\ several lines of text much as you would do in C." print(hello)</syntaxhighlight> выведет: <pre>This is a rather long string containing\n\ several lines of text much as you would do in C.</pre> Или, строки могут быть обрамлены совпадающей парой тройных кавычек: <code>"""</code> или <code><nowiki>'''</nowiki></code>. Окончания строк не нужно завершать тройными кавычками — при этом будут включены в строку. <syntaxhighlight lang="python">print(""" Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to """)</syntaxhighlight> выводит в результате следующее: <syntaxhighlight lang="text">Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to</syntaxhighlight> Строки могут конкатенироваться (склеиваться вместе) операцией <code>+</code> и быть повторенными операцией <code>*</code>: <syntaxhighlight lang="python">>>> word = 'Help' + 'A' >>> word 'HelpA' >>> '<' + word*5 + '>' '<HelpAHelpAHelpAHelpAHelpA>'</syntaxhighlight> Два строковых литерала, расположенные друг за другом, автоматически конкатенируются; первая строка в предыдущем примере также могла быть записана как <code>word = 'Help' 'A'</code>; это работает только с двумя литералами — не с произвольными выражениями, содержащими строки. <syntaxhighlight lang="python">>>> 'str' 'ing' # <- Так — верно 'string' >>> 'str'.strip() + 'ing' # <- Так — верно 'string' >>> 'str'.strip() 'ing' # <- Так — не верно File "<stdin>", line 1, in ? 'str'.strip() 'ing' ^ SyntaxError: invalid syntax</syntaxhighlight> Строки могут быть проиндексированы; также как и в C, первый символ строки имеет индекс <tt>0</tt>. Отсутствует отдельный тип для символов; символ является строкой с единичной длиной. Как и в языке программирования Icon, подстроки могут определены через нотацию срезов (<tt>slice</tt>): два индекса, разделенных двоеточием. <syntaxhighlight lang="python">>>> word[4] 'A' >>> word[0:2] 'He' >>> word[2:4] 'lp'</syntaxhighlight> Индексы срезов имеют полезные значения по умолчанию; опущенный первый индекс заменяется нулём, опущенный второй индекс подменяется размером срезаемой строки. <syntaxhighlight lang="python">>>> word[:2] # Первые два символа 'He' >>> word[2:] # Всё, исключая первые два символа 'lpA'</syntaxhighlight> В отличие от строк в C, строки Python не могут быть изменены. Присваивание по позиции индекса строки вызывает ошибку: <syntaxhighlight lang="python">>>> word[0] = 'x' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'str' object doesn't support item assignment >>> word[:1] = 'Splat' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'str' object doesn't support slice assignment</syntaxhighlight> Тем не менее, создание новой строки со смешанным содержимым — процесс легкий и очевидный: <syntaxhighlight lang="python">>>> 'x' + word[1:] 'xelpA' >>> 'Splat' + word[4] 'SplatA'</syntaxhighlight> Полезный инвариант операции среза: <code>s[:i] + s[i:]</code> эквивалентно <code>s</code>. <syntaxhighlight lang="python">>>> word[:2] + word[2:] 'HelpA' >>> word[:3] + word[3:] 'HelpA'</syntaxhighlight> Вырождения индексов срезов обрабатываются элегантно: чересчур большой индекс заменяется на размер строки, а верхняя граница меньшая нижней возвращает пустую строку. <syntaxhighlight lang="python">>>> word[1:100] 'elpA' >>> word[10:] '' >>> word[2:1] ''</syntaxhighlight> Индексы могут быть отрицательными числами, обозначая при этом отсчет справа налево. Например: <syntaxhighlight lang="python">>>> word[-1] # Последний символ 'A' >>> word[-2] # Предпоследний символ 'p' >>> word[-2:] # Последние два символа 'pA' >>> word[:-2] # Всё, кроме последних двух символов 'Hel'</syntaxhighlight> Но обратите внимание, что <tt>-0</tt> действительно эквивалентен <tt>0</tt> — это не отсчет справа. <syntaxhighlight lang="python">>>> word[-0] # (поскольку -0 равен 0) 'H'</syntaxhighlight> Отрицательные индексы вне диапазона обрезаются, но не советуем делать это с одно-элементными индексами (''не-срезами''): <syntaxhighlight lang="python">>>> word[-100:] 'HelpA' >>> word[-10] # ошибка Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: string index out of range</syntaxhighlight> Один из способов запомнить, как работают срезы — думать о них, как об указателях на места между символами, где левый край первого символа установлен в ноль, а правый край последнего символа строки из <code>n</code> символов имеет индекс <code>n</code>, например: <pre> +---+---+---+---+---+ | H | e | l | p | A | +---+---+---+---+---+ 0 1 2 3 4 5 -5 -4 -3 -2 -1</pre> Первый ряд чисел дает позицию индексов строки от 0 до 5; второй ряд описывает соответствующие отрицательные индексы. Срез от i до j состоит из всех символов между правым и левым краями, отмеченными, соответственно, через <code>i</code> и <code>j</code>. Для всех индексов, больших или равных нулю, длина среза — разность между индексами, при условии что оба индекса находятся в диапазоне. Например, длина <code>word[1:3]</code> — 2. Встроенная функция <code>len()</code> возвращает длину строки<ref>''(Прим. перев.)'': [[w:en:Supercalifragilisticexpialidocious|Supercalifragilisticexpialidocious]] — английское слово из одноименной песни, прозвучавшей в фильме [[w:en:Mary Poppins (film)|Мэри Поппинс]]</ref>: <syntaxhighlight lang="python">>>> s = 'supercalifragilisticexpialidocious' >>> len(s) 34</syntaxhighlight> {{Смотрите также| ;[[Справочник по библиотеке Python 3.1#Перечисляемые типы|Перечисляемые типы]]: Строки — вид перечисляемых типов и они поддерживают привычные для этих типов операции. ;[[Справочник по библиотеке Python 3.1#Строковые методы|Строковые методы]]: Строки поддерживают большое количество методов для поиска и простых трансформаций. ;[[Справочник по библиотеке Python 3.1#Форматирование строк|Форматирование строк]]: Здесь описано форматирование строк с применением функции <code>str.format()</code> ;[[Справочник по библиотеке Python 3.1#Форматирование строк в старом стиле|Операции форматирования строк в старом стиле]]:Операции форматирования, вызывающиеся тогда, когда обычные строки или строки в Unicode оказываются левым операндом относительно операции <code>%</code>, более детально рассмотрены здесь.<ref>''(Прим. перев.) Эти операции будут отключены в финальном релизе 3.1''</ref> }} ==== О Unicode ==== Начиная с Unicode версии 3.0, строковый тип поддерживает только Unicode (см. http://www.unicode.org/). Преимущество набора Unicode состоит в том, что он предоставляет порядковый номер для любого символа из любой письменности, использовавшейся в современных или древнейших текстах. До этих пор для символов в сценарии было доступно лишь 256 номеров. Тексты обычно привязывались к кодовой странице, которая устанавливала в соответствие порядковые номера и символы сценария. Это приводило к серьезной путанице, особенно в том, что касалось интернационализации<ref>Часто записывается как <tt>'''i18n'''</tt> — <tt>''internationalization'' = '''i''' + '''18''' символов + '''n'''</tt></ref> программного продукта. Unicode решает эти проблемы, определяя единую кодовую страницу для всех письменностей. Для вставки в строку специального символа можно использовать Unicode-экранирование (<tt>Python Unicode-Escape encoding</tt>). Следующий пример всё пояснит: <syntaxhighlight lang="python">>>> 'Hello\u0020World !' 'Hello World !'</syntaxhighlight> Экранированная последовательность <code>\u0020</code> задаёт символ Unicode с порядковым номером <tt>0x0020</tt> (символ пробела). Другие символы интерпретируются с использованием соответствующих им порядковых значений тем же способом, что и порядковые номера Unicode. Первые 128 символов кодировки Unicode полностью совпадают с 128 символами кодировки <tt>Latin-1</tt>, использующейся во многих западных странах. Помимо стандартных способов кодирования, Python предоставляет целый набор различных способов создания Unicode-строк, основываясь на известной кодировке. Для конвертирования Unicode-строки в последовательность байтов с использованием желаемой кодировки, строковые объекты предоставляют метод <code>encode()</code>, принимающий единственный параметр — название кодировки. Предпочитаются названия кодировок, записанные в нижнем регистре. ==== Списки ==== В языке Python доступно некоторое количество ''составных'' типов данных, использующихся для группировки прочих значений вместе. Наиболее гибкий из них — список (<tt>list</tt>). Его можно выразить в тексте программы через разделённые запятыми значения (''элементы''), заключённые в квадратные скобки. Элементы списка могут быть разных типов. <syntaxhighlight lang="python">>>> a = ['spam', 'eggs', 100, 1234] >>> a ['spam', 'eggs', 100, 1234]</syntaxhighlight> Подобно индексам в строках, индексы списков начинаются с нуля, списки могут быть срезаны, объединены (''конкатенированы'') и так далее: <syntaxhighlight lang="python">>>> a[0] 'spam' >>> a[3] 1234 >>> a[-2] 100 >>> a[1:-1] ['eggs', 100] >>> a[:2] + ['bacon', 2*2] ['spam', 'eggs', 'bacon', 4] >>> 3*a[:3] + ['Boo!'] ['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boo!']</syntaxhighlight> В отличие от строк, являющихся неизменяемыми, изменить индивидуальные элементы списка вполне возможно: <syntaxhighlight lang="python">>>> a ['spam', 'eggs', 100, 1234] >>> a[2] = a[2] + 23 >>> a ['spam', 'eggs', 123, 1234]</syntaxhighlight> Присваивание срезу также возможно, и это действие может даже изменить размер списка или полностью его очистить: <syntaxhighlight lang="python">>>> # Заменим некоторые элементы: ... a[0:2] = [1, 12] >>> a [1, 12, 123, 1234] >>> # Удалим немного: ... a[0:2] = [] >>> a [123, 1234] >>> # Вставим пару: ... a[1:1] = ['bletch', 'xyzzy'] >>> a [123, 'bletch', 'xyzzy', 1234] >>> # Вставим (копию) самого себя в начало >>> a[:0] = a >>> a [123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234] >>> # Очистка списка: замена всех значений пустым списком >>> a[:] = [] >>> a []</syntaxhighlight> Встроенная функция <code>len()</code> также применима к спискам: <syntaxhighlight lang="python">>>> a = ['a', 'b', 'c', 'd'] >>> len(a) 4</syntaxhighlight> Вы можете встраивать списки (создавать списки, содержащие другие списки), например так: <syntaxhighlight lang="python">>>> q = [2, 3] >>> p = [1, q, 4] >>> len(p) 3 >>> p[1] [2, 3] >>> p[1][0] 2</syntaxhighlight> Вы можете добавить что-нибудь в конец списка. <syntaxhighlight lang="python">>>> p[1].append('xtra') >>> p [1, [2, 3, 'xtra'], 4]</syntaxhighlight> Обратите внимание, что в последнем примере <code>p[1]</code> и <code>q</code> на самом деле ссылаются на один и тот же объект! <syntaxhighlight lang="python">>>> q [2, 3, 'xtra']</syntaxhighlight> Мы вернёмся к ''семантике объектов'' позже. === Первые шаги к программированию === Безусловно, Python можно использовать для более сложных задач, чем сложение двух чисел. Например, мы можем вывести начало последовательности чисел Фибоначчи таким образом: <syntaxhighlight lang="python">>>> # Ряд Фибоначчи: ... # сумма двух элементов определяет следущий элемент ... a, b = 0, 1 >>> while b < 10: ... print(b) ... a, b = b, a+b ... 1 1 2 3 5 8</syntaxhighlight> Этот пример показывает нам некоторые новые возможности. * Первая строка содержит ''множественное присваивание'' (<tt>multiple assignment</tt>): переменные <code>a</code> и <code>b</code> параллельно получают новые значения — <code>0</code> и <code>1</code>. В последней строке этот метод используется снова, демонстрируя тот факт, что выражения по правую сторону [от оператора присваивания] всегда вычисляются раньше каких бы то ни было присваиваний. Сами же разделённые запятыми выражения вычисляются слева направо. * Цикл <code>while</code> (пока) исполняется до тех пор, пока условие (здесь: <code>b < 10</code>) остается истиной. В Python, также как и в C, любое ненулевое значение является истиной (<code>True</code>); ноль является ложью (<code>False</code>). Условием может быть строка, список или вообще любая последовательность; все, что имеет ненулевую длину, играет роль истины, пустые последовательности — лжи. Использованная в примере проверка — простое условие. Стандартные операции сравнения записываются так же, как и в C: <code><</code> (меньше чем), <code>></code> (больше чем), <code>==</code> (равно), <code><=</code> (меньше или равно), <code>>=</code> (больше или равно) и <code>!=</code> (не равно). * ''Тело'' цикла выделено ''отступом'' (<tt>indented</tt>). Отступы — это средство группировки операторов в Python. Интерактивный режим Python (пока!) не имеет какого-либо разумного и удобного средства для редактирования строк ввода, поэтому необходимо использовать табуляции или пробелы для отступа в каждой строке. На практике более сложный текст на Python готовится в текстовом редакторе, большинство из которых имеют функцию авто-отступа. По окончании ввода составного выражения в интерактивном режиме его необходимо закончить пустой строкой — признаком завершения (поскольку интерпретатор не может угадать, когда вами была введена последняя строка). Обратите внимание, что размер отступа в каждой строке основного блока должен быть одним и тем же<ref>''(Прим. перев.)'' Размер отступа для блока не унифицирован — табуляция может чередоваться с пробелами, это может быть один пробел или же пять — главное, чтобы у всего блока он был одинаковым и был больше по величине чем у внешнего (обрамляющего) блока. Тем не менее, чаще всего программисты на Python устанавливают в редакторах режим замены табуляции четырьмя пробелами и при наборе кода вложенность блока обозначают отступом с соответствующим количеством нажатий клавиш табуляции. Благодаря этому код остается читабельным во всех текстовых редакторах и в большинстве браузеров (или, в редких случаях, требует минимального форматирования для корректного отображения)).''</ref>. * Функция <code>print()</code> выводит значения переданных ей выражений. Поведение этой функции отличается от обычного вывода выражения (как происходило выше в примерах с калькулятором) тем, каким способом обрабатываются ряды выражений, величины с плавающей точкой и строки. Строки выводятся без кавычек, и между элементами вставляются пробелы, благодаря чему форматирование вывода улучшается — как, например, здесь: <syntaxhighlight lang="python">>>> i = 256*256 >>> print('Значением i является', i) Значением i является 65536</syntaxhighlight> : Для отключения перевода строки после вывода или завершения вывода другой строкой используется именованный параметр <code>end</code>: <syntaxhighlight lang="python">>>> a, b = 0, 1 >>> while b < 1000: ... print(b, end=' ') ... a, b = b, a+b ... 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987</syntaxhighlight> == Больше средств для управления потоком команд<ref>''(Прим. перев.)'' More Control Flow Tools; [[w:en:Control Flow|Control Flow]] — поток команд, процесс управления, алгоритм; подразделы в оригинале используют множественное число: "Операторы (выражения, инструкции) <code>if</code>, «Операторы (выражения, инструкции) <code>for</code>», и. т. п.</ref> == Помимо описанного выше оператора <code>while</code>, в Python доступны привычные операторы управления потоком из других языков, но с некоторыми особенностями. === Оператор <code>if</code> === Возможно, наиболее широко известный тип оператора — оператор <code>if</code> (если). Пример: <syntaxhighlight lang="python">>>> x = int(input("Введите, пожалуйста, целое число: ")) Введите, пожалуйста, целое число: 42 >>> if x < 0: ... x = 0 ... print('Отрицательное значение, изменено на ноль') ... elif x == 0: ... print('Ноль') ... elif x == 1: ... print('Один') ... else: ... print('Больше') ...</syntaxhighlight> Блока <code>elif</code> может не быть вообще, он может быть один или их может быть несколько, а блок <code>else</code> (иначе) необязателен. Ключевое слово <tt>elif</tt> — краткая запись <tt>else if</tt> (иначе если) — позволяет избавиться от чрезмерного количества отступов. Оператор <code>if</code> <tt>...</tt> <code>elif</code> <tt>...</tt> <code>elif</code> <tt>...</tt> — аналог оператора выбора <code>switch</code> или <code>case</code>, которые можно встретить в других языках программирования. === Оператор <code>for</code> === Оператор <code>for</code> в Python немного отличается от того, какой вы, возможно, использовали в C или Pascal. Вместо неизменного прохождения по арифметической прогрессии из чисел (как в Pascal) или предоставления пользователю возможности указать шаг итерации и условие остановки (как в С), оператор <code>for</code> в Python проходит по всем элементам любой последовательности (списка или строки) в том порядке, в котором они в ней располагаются. Например (игра слов не подразумевалась):<ref>''(Прим. перев.)'' Defenestrate{{ref-en}} — выкидывать кого-либо из окна с целью покалечить. Другие слова — «кошка» и «окно».</ref> <syntaxhighlight lang="python">>>> # Измерим несколько строк: ... a = ['cat', 'window', 'defenestrate'] >>> for x in a: ... print(x, len(x)) ... cat 3 window 6 defenestrate 12</syntaxhighlight> Изменять содержимое последовательности, по которой проходит цикл, небезопасно (это в принципе-то возможно только для изменяемых типов, таких как списки). Если необходимо модифицировать список, использующийся для организации цикла, (например, для того чтобы продублировать отдельные элементы) нужно передать циклу его копию. Нотация срезов делает это практически безболезненным: <syntaxhighlight lang="python">>>> for x in a[:]: # создать срез-копию всего списка ... if len(x) > 6: a.insert(0, x) ... >>> a ['defenestrate', 'cat', 'window', 'defenestrate']</syntaxhighlight> === Функция <code>range()</code> === <ad/lang=ru/id=5938)'''''Если вам нужно перебрать последовательность чисел, встроенная функция <code>range()</code> придёт на помощь. Она генерирует арифметические прогрессии: <syntaxhighlight lang="python">>>> for i in range(5): ... print(i) ... 0 1 2 3 4</syntaxhighlight> <syntaxhighlight lang="python">range(5, 10) от 5 до 9 range(0, 10, 3) 0, 3, 6, 9 range(-10, -100, -30) -10, -40, -70</syntaxhighlight> Чтобы пройти по всем индексам какой-либо последовательности, скомбинируйте вызовы <code>range()</code> и <code>len()</code> следующим образом: <syntaxhighlight lang="python">>>> a = ['Mary', 'had', 'a', 'little', 'lamb'] >>> for i in range(len(a)): ... print(i, a[i]) ... 0 Mary 1 had 2 a 3 little 4 lamb</syntaxhighlight> В большинстве таких случаев удобно использовать функцию <code>enumerate()</code>, обратитесь к [[Учебник Python 3.1#Организация циклов|Организация циклов]]. Странные вещи начинают происходить при попытке вывода последовательности: <ad/lang=ru/id=5938)''''' <syntaxhighlight lang="python">>>> print(range(10)) range(0, 10)</syntaxhighlight> Во многих случаях объект, возвращаемый функцией <code>range()</code>, ведёт себя как список, но фактически им не является. Этот объект возвращает по очереди элементы желаемой последовательности, когда вы проходите по нему в цикле, но на самом деле не создаёт списка, сохраняя таким образом пространство в памяти. Мы называем такие объекты ''итерируемыми'' (<tt>iterable</tt>), и это все объекты, которые предназначаются для функций и конструкций, ожидающих от них поочерёдного предоставления элементов до тех пор, пока источник не иссякнет. Мы видели, что оператор <code>for</code> является таким ''итератором'' <tt>iterator</tt>. Функция <code>list()</code> тоже из их числа — она создаёт списки из ''итерируемых'' объектов: <syntaxhighlight lang="python">>>> list(range(5)) [0, 1, 2, 3, 4]</syntaxhighlight> Позже мы познакомимся и с другими функциями, которые возвращают и принимают ''итерируемые'' объекты в качестве параметров. === Операторы <code>break</code> и <code>continue</code>, а также условие <code>else</code> в циклах === Оператор <code>break</code> прерывает выполнение самого ближайшего вложенного цикла <code>for</code> или <code>while</code> (по аналогии с языком C). Оператор <code>continue</code>, также заимствованный из C, продолжает выполнение цикла со следующей итерации. Операторы циклов могут иметь ветвь <code>else</code>. Она исполняется, когда цикл выполнил перебор до конца (в случае <code>for</code>) или когда условие становится ложным (в случае <code>while</code>), но не в тех случаях, когда цикл прерывается по <code>break</code>. Это поведение иллюстрируется следующим примером, в котором производится поиск простых чисел: <syntaxhighlight lang="python">>>> for n in range(2, 10): ... for x in range(2, int(n ** 0.5) + 1): ... if n % x == 0: ... print(n, 'равно', x, '*', n//x) ... break ... else: ... print(n, '- простое число') ... 2 - простое число 3 - простое число 4 равно 2 * 2 5 - простое число 6 равно 2 * 3 7 - простое число 8 равно 2 * 4 9 равно 3 * 3</syntaxhighlight> === Оператор <code>pass</code> === Оператор <code>pass</code> не делает ничего. Он может использоваться когда синтаксически требуется присутствие оператора, но от программы не требуется действий. Например: <syntaxhighlight lang="python">>>> while True: ... pass # Ожидание прерывания c клавиатуры (Ctrl+C) в режиме занятости ...</syntaxhighlight> Этот оператор часто используется для создания минималистичных классов, к примеру ''исключений'' (<tt>exceptions</tt>), или для игнорирования нежелательных исключений: <syntaxhighlight lang="python">>>> class ParserError(Exception): ... pass ... >>> try: ... import audioop ... except ImportError: ... pass ...</syntaxhighlight> Другой вариант: <code>pass</code> может применяться в качестве заглушки для тела функции или условия при создании нового кода, позволяя вам сохранить абстрактный взгляд на вещи. С другой стороны, оператор <code>pass</code> игнорируется без каких-либо сигналов и лучшим выбором было бы породить исключение <code>NotImplementedError</code>: <syntaxhighlight lang="python">>>> def initlog(*args): ... raise NotImplementedError # Открыть файл для логгинга, если он ещё не открыт ... if not logfp: ... raise NotImplementedError # Настроить заглушку для логгинга ... raise NotImplementedError('Обработчик инициализации лога вызовов') ...</syntaxhighlight> Если бы здесь использовались операторы <code>pass</code>, а позже вы бы запускали тесты, они могли бы упасть без указания причины. Использование <code>NotImplementedError</code> принуждает этот код породить исключение, сообщая вам конкретное место, где присутствует незавершённый код. Обратите внимание на два способа порождения исключений. Первый способ, без сообщения, но сопровождаемый комментарием, позволяет вам оставить комментарий когда вы будете подменять выброс исключения рабочим кодом, который, в свою очередь, в идеале, будет хорошим описанием блока кода, для которого исключение предназначалось заглушкой. Однако, передача сообщения вместе с исключением, как в третьем примере, обуславливает более насыщенный информацией вывод при отслеживании ошибки. === Определение функций === Мы можем создать функцию, которая выводит последовательность Фибоначчи до некоторого предела: <syntaxhighlight lang="python">>>> def fib(n): # вывести числа Фибоначчи меньшие (вплоть до) n ... """Выводит ряд Фибоначчи, ограниченный числом n.""" ... a, b = 0, 1 ... while b < n: ... print(b, end=' ') ... a, b = b, a+b ... >>> # Теперь вызовем определенную нами функцию: ... fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597</syntaxhighlight> Зарезервированное слово <code>def</code> предваряет ''определение'' функции. За ним должны следовать имя функции и заключённый в скобки список формальных параметров. Выражения, формирующие тело функции, начинаются со следующей строки и должны иметь отступ. Первым выражением в теле функции может быть строковой литерал — этот литерал является строкой документации функции, или ''док-строкой'' (<tt>docstring</tt>). (Больше информации о ''док-строках'' вы найдёте в разделе [[Учебник Python 3.1#Строки документации|Строки документации]]) Существуют инструменты, которые используют ''док-строки'' для того, чтобы сгенерировать печатную или онлайн-документацию или чтобы позволить пользователю перемещаться по коду интерактивно; добавление строк документации в ваш код — это хорошая практика, постарайтесь к ней привыкнуть. ''Исполнение'' функции приводит к созданию новой таблицы символов<ref>''(Прим. перев.)'' Здесь слово «символ» используется не в привычном значении — под ''символом'' подразумевается нечто лингвистическое, описывающее какую-либо сущность (близко к значению ''символизировать''), в данном случае: имя переменной — саму переменную.</ref>, использующейся для хранения локальных переменных функции. Если быть более точными, все присваивания переменных в функции сохраняют значение в локальной таблице символов; при обнаружении ссылки на переменную, в первую очередь просматривается локальная таблица символов, затем локальная таблица символов для окружающих функций, затем глобальная таблица символов и, наконец, таблица встроенных имён. Таким образом, глобальным переменным невозможно прямо присвоить значения внутри функций (если они конечно не упомянуты в операторе <code>global</code>) несмотря на то, что ссылки на них могут использоваться. Фактические параметры при вызове функции помещаются в локальную таблицу символов вызванной функции; в результате аргументы передаются через ''вызов по значению'' (<tt>call by value</tt>) (где значение — это всегда ''ссылка'' (<tt>reference</tt>) на объект, а не значение его самого)<ref>На самом деле, лучшим определением был бы ''вызов по ссылке на объект'' (<tt>call by object reference</tt>), так как при передаче изменяемого объекта, вызывающему будут видны все изменения, которые производит над объектом вызываемый (вставка элементов в список)</ref>. Если одна функция вызывает другую — то для этого вызова создается новая локальная таблица символов. При определении функции её имя также помещается в текущую таблицу символов. Тип значения, связанного с именем функции, распознается интерпретатором как функция, определённая пользователем (<tt>user-defined function</tt>). Само значение может быть присвоено другому имени, которое затем может также использоваться в качестве функции. Эта система работает в виде основного механизма переименования: <syntaxhighlight lang="python">>>> fib <function fib at 10042ed0> >>> f = fib >>> f(100) 1 1 2 3 5 8 13 21 34 55 89</syntaxhighlight> Если вы использовали в работе другие языки программирования, вы можете возразить, что <code>fib</code> — это не функция, а процедура, поскольку не возвращает никакого значения. На самом деле, даже функции без ключевого слова <code>return</code> возвращают значение, хотя и более скучное. Такое значение именуется <code>None</code> (это встроенное имя). Вывод значения <code>None</code> обычно подавляется в интерактивном режиме интерпретатора, если оно оказывается единственным значением, которое нужно вывести. Вы можете проследить за этим процессом, если действительно хотите, используя функцию <code>print()</code>: <syntaxhighlight lang="python">>>> fib(0) >>> print(fib(0)) None</syntaxhighlight> Довольно легко написать функцию, которая возвращает список чисел из ряда Фибоначчи, вместо того, чтобы выводить их: <syntaxhighlight lang="python">>>> def fib2(n): # вернуть числа Фибоначчи меньшие (вплоть до) n ... """Возвращает список чисел ряда Фибоначчи, ограниченный n.""" ... result = [] ... a, b = 0, 1 ... while b < n: ... result.append(b) # см. ниже ... a, b = b, a+b ... return result ... >>> f100 = fib2(100) # вызываем >>> f100 # выводим результат [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]</syntaxhighlight> И на этот раз пример демонстрирует некоторые новые возможности Python: * Оператор <code>return</code> завершает выполнение функции, возвращая некоторое значение. Оператор <code>return</code> без аргумента возвращает <code>None</code>. Достижение конца функции также возвращает <code>None</code>. * Выражение <code>result.append(b)</code> вызывает метод <code>append</code> объекта-списка <code>result</code>. Метод — это функция, которая «принадлежит» объекту и указывается через выражение вида <code>obj.methodname</code>, где <code>obj</code> — некоторый объект (может быть выражением), а <code>methodname</code> — имя метода, присущий объекту данного типа. Различные типы определяют различные методы. Методы разных типов могут иметь одинаковые имена, не вызывая неопределённостей. (Позже в этом учебнике будет рассмотрено как определять собственные типы объектов и методы, используя классы.) Метод <code>append()</code>, показанный в примере, определён для объектов типа список. Он добавляет в конец списка новый элемент. В данном примере это действие эквивалентно выражению <code>result = result + [b]</code>, но более эффективно. === Подробнее об определении функций === Также есть возможность определять функции с переменным количеством параметров. Для этого существует три формы, которые также можно использовать совместно. ==== Значения аргументов по умолчанию ==== Наиболее полезной формой является задание значений по умолчанию для одного или более параметров. Таким образом создаётся функция, которая может быть вызвана с меньшим количеством параметров, чем в её определении: при этом неуказанные при вызове параметры примут данные в определении функции значения. Например<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' спросить_подтверждения(вопрос, попытки=4, протест='Да или нет, пожалуйста!'):<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''пока''' ''Истина'':<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ответ = ''ввод''(вопрос)<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''если''' ответ '''среди''' ('д', 'да', 'ага'): '''вернуть''' ''Истина''<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''если''' ответ '''среди''' ('н', 'не', 'нет', 'не-а'): '''вернуть''' ''Ложь''<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;попытки = попытки - 1<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''если''' попытки < 0: '''породить''' ОшибкаВВ('пользователь-отказник')<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''(протест)</code><br /><br /> (''Refusenik''{{ref-en}} — [[w:ru:Отказник|Отказник]]). Ниже: «…<code>спросить_подтверждения('Вы действительно хотите выйти?')</code> или так: <code>спросить_подтверждения('Согласны ли вы перезаписать файл?', 2)</code>…»</ref>: <syntaxhighlight lang="python">def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while True: ok = input(prompt) if ok in ('y', 'yeah', 'yes', 'yep'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise IOError('refusenik user') print(complaint)</syntaxhighlight> Эта функция может быть вызвана, например, так: <code>ask_ok('Do you really want to quit?')</code> или так: <code>ask_ok('OK to overwrite the file?', 2)</code>. Этот пример также знакомит вас с зарезервированным словом <code>in</code>. Посредством его можно проверить, содержит ли последовательность определённое значение или нет. Значения по умолчанию вычисляются в месте определения функции, в ''определяющей'' области, поэтому код <syntaxhighlight lang="python">i = 5 def f(arg=i): print(arg) i = 6 f()</syntaxhighlight> выведет 5. '''Важное предупреждение:''' Значение по умолчанию вычисляется лишь единожды. Это особенно важно помнить, когда значением по умолчанию является изменяемый объект, такой как список, словарь (<tt>dictionary</tt>) или экземпляры большинства классов. Например, следующая функция накапливает переданные ей параметры: <syntaxhighlight lang="python">def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3))</syntaxhighlight> Она выведет <syntaxhighlight lang="python">[1] [1, 2] [1, 2, 3]</syntaxhighlight> Если вы не хотите, чтобы значение по умолчанию распределялось между последовательными вызовами, вместо предыдущего варианта вы можете использовать такую идиому: <syntaxhighlight lang="python">def f(a, L=None): if L is None: L = [] L.append(a) return L</syntaxhighlight> ==== Именованные параметры<ref>''(Прим. перев.)'' В оригинале — Keyword Arguments — параметры по ключевым словам, ключевые параметры (далее используется слово ''keywords'' для набора имён параметров непостоянного количества. ''Ключевые'' — возможно, корректнее, но как мне показалось — менее понятно ([http://www.infocity.kiev.ua/prog/python/content/sempit_14.phtml альтернативный перевод]))</ref> ==== Функции также могут быть вызваны с использованием именованных параметров (<tt>keyword arguments</tt>) в форме «''имя = значение''». Например, нижеприведённая функция<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' попугай(вольтаж, состояние='труп', действие='ввум', тип='Норвежский Голубой'):<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Этот попугай не сделает ", действие, завершить=' ')<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("если вы пропустите через него ", вольтаж, " вольт.")<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Великолепное оперенье, ", тип)<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Он", состояние, "!")</code><br /><br /> (''Из [http://www.ibras.dk/montypython/episode08.htm#6 скетча Монти Пайтона]'')</ref>: <syntaxhighlight lang="python">def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It's", state, "!")</syntaxhighlight> могла бы быть вызвана любым из следующих способов<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">попугай(действие='ВВУУУУМ', вольтаж=1000000)<br/> попугай('тысячу', состояние='слёг в могилу')<br/> попугай('миллион', 'лишённый жизни', 'прыжок')</code><br /><br /></ref>: <syntaxhighlight lang="python">parrot(1000) parrot(action='VOOOOOM', voltage=1000000) parrot('a thousand', state='pushing up the daisies') parrot('a million', 'bereft of life', 'jump')</syntaxhighlight> а эти случаи оказались бы неверными<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">попугай()<br/> попугай(вольтаж=5.0, 'мёртв')<br/> попугай(исполнитель='Джон Клиз')</code><br /><br /></ref>: <syntaxhighlight lang="python">parrot() # пропущен требуемый аргумент parrot(voltage=5.0, 'dead') # позиционный параметр вслед за именованным parrot(110, voltage=220) # повторное значение параметра parrot(actor='John Cleese') # неизвестное имя параметра</syntaxhighlight> В общем случае, список параметров должен содержать любое количество позиционных (<tt>positional</tt>) параметров, за которыми может следовать любое количество именованных, и при этом имена аргументов выбираются из формальных параметров. Неважно, имеет формальный параметр значение по умолчанию или нет. Ни один из аргументов не может получать значение более чем один раз — имена формальных параметров, совпадающие с именами позиционных параметров, не могут использоваться в качестве именующих в одном и том же вызове<ref>''(Прим. перев.)'' В главе о функциях автор отталкивается не от привычного по другим учебникам первоначального полного описания определения функций, а уже потом — описания их вызова, а объединяет обе темы вместе (как минимум в случае с непостоянным списком аргументов это возможно непривычно, но оправдано), отдавая приоритет описанию вызова. Учебник рассчитан на тех, кто уже программирует на каком-либо языке программирования и потенциально не должен смутить читателя.</ref>. Вот пример, завершающийся неудачей по причине описанного ограничения: <syntaxhighlight lang="python">>>> def function(a): ... pass ... >>> function(0, a=0) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: function() got multiple values for keyword argument 'a'</syntaxhighlight> Если в определении функции присутствует завершающий параметр в виде ''**имя'', он получит в качестве значения словарь (подробнее в разделе [[Справочник по библиотеке Python 3.1#Типы-отображения|Справочника — Типы-отображения — словари]]), содержащий все именованные параметры и их значения, исключая те, которые соответствуют формальным параметрам. Можно совместить эту особенность с поддержкой формального параметра в формате ''*имя'' (описывается в следующем подразделе), который получает кортеж (<tt>tuple</tt>), содержащий все позиционные параметры, следующие за списком формальных параметров. (параметр в формате ''*имя'' должен описываться перед параметром в формате ''**имя''.) Например, если мы определим такую функцию<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' лавка_сыров(сорт, *аргументы, **именованные):<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Есть ли у вас ", сорт, '?')<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Простите, весь ", сорт, " у нас закончился.")<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''для''' аргумент '''из''' аргументы: '''вывести'''(аргумент)<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''('-' * 40)<br/> &nbsp;&nbsp;&nbsp;&nbsp;имена = '''сортированные'''(именованные.''ключи''())<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''для''' имя '''из''' имена: '''вывести'''(имя , ":", именованные[имя])</code><br /><br /> (''Из [http://www.ibras.dk/montypython/episode33.htm#7 скетча Монти Пайтона]'')</ref>: <syntaxhighlight lang="python">def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any", kind, "?") print("-- I'm sorry, we're all out of", kind) for arg in arguments: print(arg) print("-" * 40) keys = sorted(keywords.keys()) for kw in keys: print(kw, ":", keywords[kw])</syntaxhighlight> то её можно будет вызвать так<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">лавка_сыров("Лимбургер", "Это очень расстраивает, сэр.",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Это действительно очень, ОЧЕНЬ расстраивает, сэр.",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;торговец="Майкл Палин",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;клиент="Джон Клиз",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;скетч="Скетч о сырной лавке")</code></ref>: <syntaxhighlight lang="python">cheeseshop('Limburger', "It's very runny, sir.", "It's really very, VERY runny, sir.", client="John Cleese", shopkeeper="Michael Palin", sketch="Cheese Shop Sketch")</syntaxhighlight> и она, конечно же, выведет<ref>''(Прим. перев.):'' <br/><br/> <code style="background-color: inherit !important;">-- Есть ли у вас Лимбургер ?<br/> -- Простите, весь Лимбургер у нас закончился.<br/> Это очень расстраивает, сэр.<br/> Это действительно очень, ОЧЕНЬ расстраивает, сэр.<br/> <nowiki>----------------------------------------</nowiki><br/> клиент: Джон Клиз<br/> торговец : Майкл Палин<br/> скетч : Скетч о сырной лавке</code><br /><br /></ref>: <code>-- Do you have any Limburger ?<br/> -- I'm sorry, we're all out of Limburger<br/> It's very runny, sir.<br/> It's really very, VERY runny, sir.<br/> <nowiki>----------------------------------------</nowiki><br/> client : John Cleese<br/> shopkeeper : Michael Palin<br/> sketch : Cheese Shop Sketch</code> Обратите внимание, что список имён (ключей) именованных параметров (<code>keys</code>) создается посредством сортировки содержимого списка ключей <code>keys()</code> словаря <code>keywords</code>; если бы этого не было сделано, порядок вывода параметров был бы произволен. ==== Списки параметров произвольной длины ==== Наконец, наиболее редко используется возможность указания того, что функция может быть вызвана с произвольным числом аргументов. При этом сами параметры будут обёрнуты в кортеж (см. раздел [[Учебник Python 3.1#Кортежи|Кортежи]]). Переменное количество параметров могут предварять ноль или более обычных. <syntaxhighlight lang="python">def write_multiple_items(file, separator, *args): file.write(separator.join(args))</syntaxhighlight> Обычно параметры неизвестного заранее количества (<tt>variadic</tt>) указываются последними в списке формальных параметров, поскольку включают в себя все остальные переданные в функцию параметры. Все формальные параметры, которые следуют за параметром <code>*args</code>, должны быть только именованными, то есть, они могут быть заданы только по имени (в отличие от позиционных параметров). <syntaxhighlight lang="python">>>> def concat(*args, sep="/"): ... return sep.join(args) ... >>> concat("earth", "mars", "venus") 'earth/mars/venus' >>> concat("earth", "mars", "venus", sep=".") 'earth.mars.venus'</syntaxhighlight> ==== Распаковка списков параметров ==== Обратная ситуация возникает когда параметры уже содержатся в списке или в кортеже, но должны быть распакованы для вызова функции, требующей отдельных позиционных параметров. Например, встроенная функция <code>range()</code> ожидает отдельные параметры ''start'' и ''stop'' соответственно. Если они не доступны раздельно, для распаковки аргументов из списка или кортежа в вызове функции используйте *-синтаксис: <syntaxhighlight lang="python">>>> list(range(3, 6)) # обычный вызов с отдельными параметрами [3, 4, 5] >>> args = [3, 6] >>> list(range(*args)) # вызов с распакованными из списка параметрами [3, 4, 5]</syntaxhighlight> Схожим способом, словари могут получать именованные параметры через **-синтаксис<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' попугай(вольтаж, состояние='труп', действие='ввум', тип='Норвежский Голубой'):<br/> ...&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Этот попугай не сделает ", действие, конец=' ')<br/> ...&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("если вы пропустите через него ", вольтаж, " вольт.", конец=' ')<br/> ...&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Это", состояние, "!")<br/> ...<br/> >>> d = {"вольтаж": "четыре миллиона", "состояние": "кровавая кончина", "действие": "ВВУМ"}<br/> >>> попугай(**d)<br/> -- Этот попугай не сделает ВВУМ если вы пропустите через него четыре миллиона вольт. Это кровавая смерть !</code><br /><br /> (''Из [http://www.ibras.dk/montypython/episode08.htm#6 скетча Монти Пайтона]'')</ref>: <syntaxhighlight lang="python">>>> def parrot(voltage, state='a stiff', action='voom'): ... print("-- This parrot wouldn't", action, end=' ') ... print("if you put", voltage, "volts through it.", end=' ') ... print("It's", state, "!") ... >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"} >>> parrot(**d) -- This parrot wouldn't VOOM if you put four million volts through it. It's bleedin' demised !</syntaxhighlight> ==== Модель <tt>lambda</tt> ==== В связи с неустанными просьбами, в Python были добавлены несколько возможностей, которые были привычны для функциональных языков программирования, таких как Lisp. Используя зарезервированное слово <code>lambda</code>, вы можете создать небольшую безымянную функцию. Например, функцию, которая возвращает сумму двух своих аргументов, можно записать так: <code>lambda a, b: a+b</code>. Формы <code>lambda</code> могут быть использованы в любом месте где требуется объект функции. При этом они синтаксически ограничены одним выражением. Семантически, они лишь «синтаксический сахар» для обычного определения функции. Как и определения вложенных функций, <code>lambda</code>-формы могут ссылаться на переменные из содержащей их области видимости: <syntaxhighlight lang="python">>>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43</syntaxhighlight> ==== Строки документации ==== Перечислим некоторые существующие соглашения по содержимому строк документации и их форматированию. По поводу форматирования строк документации и их содержимого постоянно появляются всё новые соглашения. Первая строка всегда должна быть сжатой, лаконичной сводкой о назначении объекта. Для краткости, в ней не обязательно присутствие имени типа или объекта, поскольку они доступны другими способами (исключая случай, когда имя функции оказывается глаголом, описывающим суть операции). Эта строка должна начинаться с прописной буквы и оканчиваться точкой. Если строке документации (литералу, объекту строки) требуется больше строк (физических), вторая строка должна быть пустой, визуально отделяя сводку от остального описания. Следующие строки могут быть одним или более абзацем, описывающим соглашения по вызову объекта, сторонние эффекты, и т. д. Парсер Python не обрабатывает отступы в много-строковых литералах, поэтому инструментам, которые работают над документацией, предлагается, по желанию, делать это самим. Производится это по следующему соглашению. Первая непустая строка после первой строки литерала определяет величину отступа всего литерала документации. (Мы не можем использовать первую строку, поскольку она обычно выравнивается по открывающим кавычкам и её отступ в литерале не явен). Пробельный «эквивалент» этого отступа затем отрезается от начала всех строк литерала. Строк с меньшим отступом не должно обнаруживаться, но если они встретились, весь их начальный отступ должен быть обрезан. Эквивалентность пробельных замен может быть протестирована развертыванием табуляции (обычно, к 8 пробелам). Вот пример многострочной документации (''док-строки''): <syntaxhighlight lang="python">>>> def my_function(): ... """Не делаем ничего, но документируем. ... ... Нет, правда, эта функция ничего не делает. ... """ ... pass ... >>> print(my_function.__doc__) Не делаем ничего, но документируем. Нет, правда, эта функция ничего не делает.</syntaxhighlight> === Интермеццо: Стиль написания кода === Теперь, когда вам предстоит писать более объёмные и сложные блоки кода на Python, настало время поговорить о ''стиле написания кода'' (<tt>coding style</tt>). Код на большинстве языков программирования может быть записан (или, точнее говоря, ''отформатирован'' (<tt>formatted</tt>)) различными способами; некоторые из них более читабельны, некоторые — нет. Стремление к написанию лёгкого для прочтения другими кода всегда считалось хорошим тоном, и выбор правильного стиля для кода крайне ему способствует. В случае языка Python, в качестве руководства по стилю было создано предложение [http://www.python.org/dev/peps/pep-0008 PEP8]<ref>''(Прим. перев.)'' — <tt>[[w:Python_Enhancement_Proposal|PEP]]</tt> (</tt>''Python Enchancement Proprosal</tt>'', Предложение по улучшению Python) — документ, имеющий стандартизированный формат и описывающий какую-либо из возможностей или какое-либо из свойств языка Python, планируемые для разработки в будущем (или уже разработанную). В завершённом варианте используется как основное соглашение по данной функциональности. (см. также [[w:Python#Дальнейшая разработка|пояснение на странице языка Python]])</ref>, которого придерживаются создатели большинства проектов. В нём учреждается чрезвычайно читабельный и приятный для глаза стиль написания кода. В некоторый момент с ним должен ознакомиться каждый разработчик на Python. Приведём здесь избранные, наиболее важные, пункты: * Используйте отступ в 4 пробела, не используйте табуляцию : 4 пробела легко опознаются и в случае небольших отступов (хватает места для глубоких вложений) и в случае больших отступов (приятнее читается). Табуляция вносит путаницу и лучше от неё воздержаться. * Разделяйте строки так, чтобы их длина не превышала 79-и символов : Это поможет пользователям с небольшими экранами, а пользователям с большими экранами позволит уложить несколько файлов с исходным кодом рядом. * Используйте пустые строки для отделения функций, классов, и крупных блоков внутри функций. * При возможности располагайте комментарий на отдельной строке. * Используйте строки документации (''док-строки'') * Применяйте пробелы вокруг символов операций и после запятых, но не добавляйте их в конструкции со скобками: <code>a = f(1, 2) + g(3, 4)</code> * Называйте ваши классы и функции единообразно; соглашение следующее: используйте <code>CamelCase</code><ref>''(Прим. перев.)'' <tt>CamelCase</tt> (''ВерблюжийСтиль'') — стиль именования идентификаторов, при котором все слова, записанные строчными буквами, объединяются в одно и первая буква каждого слова выделяется заглавной буквой — такая запись напоминает верблюжьи горбы, в связи с чем и названа.</ref> для именования классов и <code>нижний_регистр_с_подчёркиваниями</code></tt><ref>''(Прим. перев.)'' Пусть данный пример по вине переводчика и использует русские буквы, соглашение корректно настаивает на использовании латиницы для именования идентификаторов, см. следующий пункт соглашения</ref> для функций и методов. (обращайтесь к разделу [[Учебник Python 3.1#Первый взгляд на классы|Первый взгляд на классы]] за дополнительной информацией о классах и методах) * Не используйте в вашем коде изощрённых кодировок<ref>''(Прим. перев.)'' В строковых литералах (не комментариях) это, конечно же, позволено</ref>, если он рассчитан на использование в интернациональной среде. Стандартный набор ASCII всегда работает на ура<ref>''(Прим. перев.)'' Не кодировка, а именно набор символов — латиница, пунктуация и несколько служебных символов. Кодировка по умолчанию для файлов с исходными кодами, начиная с Python 3.0, всегда UTF-8 — дабы существовала возможность использовать национальные символы в строковых литералах и, в редких случаях — комментариях.</ref>. == Структуры данных == Эта глава описывает подробнее некоторые вещи, которые вы уже изучили, а также раскрывает некоторые новые темы. === Подробнее о списках === У типа данных список также имеются не описанные ранее методы. Ниже приведены все методы объекта типа список: ;<code>list.append(''x'')</code>:Добавить элемент к концу списка; эквивалент <code>list[len(list):] = [x]</code> ;<code>list.extend(''L'')</code>:Расширить список за счёт добавления всех элементов переданного списка; эквивалентно <code>list[len(list):] = L</code>. ;<code>list.insert(''i'', ''x'')</code>:Вставить элемент в указанную позицию. Первый аргумент — это индекс того элемента, перед которым требуется выполнить операцию вставки, поэтому вызов <code>list.insert(0, x)</code> вставляет элемент в начало списка, а <code>list.insert(len(list), x)</code> эквивалентно <code>list.append(x)</code>. ;<code>list.remove(''x'')</code>:Удалить первый найденный элемент из списка, значение которого — <code>x</code>. Если элемент не найден, генерируется ошибка. ;<code>list.pop([''i''])</code>:Удалить элемент, находящийся на указанной позиции в списке, и вернуть его. Если индекс не указан, <code>list.pop()</code> удаляет и возвращает последний элемент списка. (Квадратные скобки вокруг <code>i</code> в сигнатуре метода означают, что параметр необязателен, а не необходимость набора квадратных скобок в этой позиции. Вы часто будете встречать такую нотацию в [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке]].) ;<code>list.index(''x'')</code>:Вернуть индекс первого найденного в списке элемента, значение которого равно <code>x</code>. Если элемент не найден, генерируется ошибка. ;<code>list.count(''x'')</code>:Вернуть значение сколько раз, <code>x</code> встречается в списке. ;<code>list.sort()</code>:Сортировать элементы списка, на месте. ;<code>list.reverse()</code>:Обратить порядок элементов списка, на месте. Пример, использующий большинство методов списка: <syntaxhighlight lang="python">>>> a = [66.25, 333, 333, 1, 1234.5] >>> print(a.count(333), a.count(66.25), a.count('x')) 2 1 0 >>> a.insert(2, -1) >>> a.append(333) >>> a [66.25, 333, -1, 333, 1, 1234.5, 333] >>> a.index(333) 1 >>> a.remove(333) >>> a [66.25, -1, 333, 1, 1234.5, 333] >>> a.reverse() >>> a [333, 1234.5, 1, 333, -1, 66.25] >>> a.sort() >>> a [-1, 1, 66.25, 333, 333, 1234.5]</syntaxhighlight> ==== Использование списка в качестве стека ==== Методы списков позволяют легко использовать список в качестве стека, где последний добавленный элемент становится первым полученным («первый вошёл — последний вышел»). Чтобы положить элемент на вершину стека, используйте метод <code>append()</code>. Для получения элемента с вершины стека — метод <code>pop()</code> без указания явного индекса. Например: <syntaxhighlight lang="python">>>> stack = [3, 4, 5] >>> stack.append(6) >>> stack.append(7) >>> stack [3, 4, 5, 6, 7] >>> stack.pop() 7 >>> stack [3, 4, 5, 6] >>> stack.pop() 6 >>> stack.pop() 5 >>> stack [3, 4]</syntaxhighlight> ==== Использование списка в качестве очереди ==== Вы можете без труда использовать список также и в качестве очереди, где первый добавленный элемент оказывается первым полученным («первый вошёл — первый вышел»). Чтобы добавить элемент в конец очереди, используйте метод <code>append()</code>, а чтобы получить элемент из начала очереди — метод <code>pop()</code> с нулём в качестве индекса. Например: <syntaxhighlight lang="python">>>> queue = ["Eric", "John", "Michael"] >>> queue.append("Terry") # Прибыл Terry >>> queue.append("Graham") # Прибыл Graham >>> queue.pop(0) 'Eric' >>> queue.pop(0) 'John' >>> queue ['Michael', 'Terry', 'Graham']</syntaxhighlight> ==== Генераторы списков<ref>''(Прим. перев.)'' ''Lists Comprehensions'', comprehension — включение, вложение, добавление (понимание, охват, интенция).</ref> ==== Использование метода списковой сборки — легкий способ создать список на основе последовательности. В большинстве случаев он применяется для создания списков, в которых каждый элемент является результатом некой операции, произведённой над каждым членом последовательности, или для создания выборок из тех элементов, которые удовлетворяют определённому условию. Любая списковая сборка состоит из выражения, за которым следует оператор <code>for</code>, а затем ноль или более операторов <code>for</code> или <code>if</code>. Результатом станет список, получившийся через вычисление выражения в контексте следующих за ним операторов <code>for</code> и/или <code>if</code>. Если в результате вычисления выражения строится кортеж, его нужно явно обернуть в скобки. В следующем примере на основе списка чисел создаётся список, где каждое число утроено: <syntaxhighlight lang="python">>>> vec = [2, 4, 6] >>> [3*x for x in vec] [6, 12, 18]</syntaxhighlight> Применим фантазию: <syntaxhighlight lang="python">>>> [[x, x**2] for x in vec] [[2, 4], [4, 16], [6, 36]]</syntaxhighlight> Здесь мы вызываем метод по очереди с каждым элементом последовательности: <syntaxhighlight lang="python">>>> freshfruit = [' banana', ' loganberry ', 'passion fruit '] >>> [weapon.strip() for weapon in freshfruit] ['banana', 'loganberry', 'passion fruit']</syntaxhighlight> Используя оператор <code>if</code>, мы можем отфильтровать поток: <syntaxhighlight lang="python">>>> [3*x for x in vec if x > 3] [12, 18] >>> [3*x for x in vec if x < 2] []</syntaxhighlight> Кортежи могут быть созданы без использования скобок, но не в этом случае: <syntaxhighlight lang="python">>>> [x, x**2 for x in vec] # ошибка - для кортежей необходимы скобки File "<stdin>", line 1, in ? [x, x**2 for x in vec] ^ SyntaxError: invalid syntax >>> [(x, x**2) for x in vec] [(2, 4), (4, 16), (6, 36)]</syntaxhighlight> Вот несколько вложенных циклов <code>for</code> и ещё кое-какое забавное поведение: <syntaxhighlight lang="python">>>> vec1 = [2, 4, 6] >>> vec2 = [4, 3, -9] >>> [x*y for x in vec1 for y in vec2] [8, 6, -18, 16, 12, -36, 24, 18, -54] >>> [x+y for x in vec1 for y in vec2] [6, 5, -7, 8, 7, -5, 10, 9, -3] >>> [vec1[i]*vec2[i] for i in range(len(vec1))] [8, 12, -54]</syntaxhighlight> Списковые сборки могут применяться в сложных выражениях и вложенных функциях<ref>''(Прим. перев.)'' в Python, как и в большинстве других языков программирования, используется европейский стандарт разделения целой и дробной части десятичных дробей точкой.</ref>: <syntaxhighlight lang="python">>>> [str(round(355/113, i)) for i in range(1, 6)] ['3.1', '3.14', '3.142', '3.1416', '3.14159']</syntaxhighlight> ==== Вложенные списковые сборки ==== Если вы в состоянии это переварить: списковые сборки могут быть вложенными. Но как любой мощный инструмент, их следует использовать с осторожностью. Представьте нижеследующий пример матрицы 3x3 в виде списка, содержащего три других списка, по одному в ряд: <syntaxhighlight lang="python">>>> mat = [ ... [1, 2, 3], ... [4, 5, 6], ... [7, 8, 9], ... ]</syntaxhighlight> Чтобы поменять строки и столбцы местами, можно использовать такую списковую сборку: <syntaxhighlight lang="python">>>> print([[row[i] for row in mat] for i in [0, 1, 2]]) [[1, 4, 7], [2, 5, 8], [3, 6, 9]]</syntaxhighlight> Применяя вложенные списковые сборки, необходимо помнить о важной вещи: : Во избежание недоразумений при конструировании вложенных списковых сборок, читайте их справа налево. Более многословная, с использованием операторов, версия примера может служить иллюстрацией: <syntaxhighlight lang="python">for i in [0, 1, 2]: for row in mat: print(row[i], end="") print()</syntaxhighlight> В реальных случаях лучше использовать встроенные функции вместо сложных выражений. В нашем случае поможет функция <code>zip()</code>: <syntaxhighlight lang="python">>>> list(zip(*mat)) [(1, 4, 7), (2, 5, 8), (3, 6, 9)]</syntaxhighlight> В разделе [[Учебник Python 3.1#Распаковка списков параметров|Распаковка списков параметров]] описано предназначение звёздочки в этих строках. Другой пример использования вложенных списковых сборок — произведение матрицы a на матрицу b: <syntaxhighlight lang="python">c=[[sum(x*y for x,y in zip(i,j)) for j in zip(*b)] for i in a]</syntaxhighlight> Это можно сделать эффективнее и прозрачнее, но на данном примере видна мощь инструмента. Получение единичной матрицы порядка n: <syntaxhighlight lang="python">a=[[0]*i+[1]+[0]*(n-i-1) for i in range(n)]</syntaxhighlight> === Оператор <code>del</code> === Существует способ удалить элемент, указывая его индекс, а не его значение: оператор <code>del</code>. В отличие от метода <code>pop()</code>, он не возвращает значения. Оператор <code>del</code> может также использоваться для удаления срезов из списка или полной очистки списка (что мы делали ранее через присваивание пустого списка срезу). Например: <syntaxhighlight lang="python">>>> a = [-1, 1, 66.25, 333, 333, 1234.5] >>> del a[0] >>> a [1, 66.25, 333, 333, 1234.5] >>> del a[2:4] >>> a [1, 66.25, 1234.5] >>> del a[:] >>> a []</syntaxhighlight> <code>del</code> может быть также использован для удаления переменных полностью: <syntaxhighlight lang="python">>>> del a</syntaxhighlight> Ссылка на имя <code>a</code> в дальнейшем вызовет ошибку (по крайней мере до тех пор, пока с ним не будет связано другое значение). Позже мы с вами узнаем другие способы использования <code>del</code>. === Кортежи и последовательности === Мы видели, что списки и строки поддерживают много привычных свойств, таких как индексирование и операция получения срезов. Существует два подвида типов данных ''последовательность'' (<tt>sequence</tt>) (см. [[Справочник по библиотеке Python 3.1#Последовательности|Справочник по библиотеке — Последовательности]]), и поскольку Python — развивающийся язык, со временем могут быть добавлены другие последовательные типы данных. Итак, существует также и другой, достойный рассмотрения, стандартный последовательный тип данных: ''кортеж'' (<tt>tuple</tt>). Кортеж состоит из некоторого числа значений разделённых запятыми, например: <syntaxhighlight lang="python">>>> t = 12345, 54321, 'hello!' >>> t[0] 12345 >>> t (12345, 54321, 'hello!') >>> # Кортежи могут быть вложенными: ... u = t, (1, 2, 3, 4, 5) >>> u ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))</syntaxhighlight> Как видите, кортежи на выводе всегда заключены в скобки, таким образом вложенные кортежи интерпретируются корректно; они могут быть введены и с обрамляющими скобками и без, тем не менее в любом случае скобки чаще всего необходимы (если кортеж — часть более крупного выражения). Кортежи можно использовать в различных целях. Например: <code>(x, y)</code> пары координат, записи о рабочих из базы данных, и так далее. Кортежи, как и строки, неизменяемы: невозможно присвоить что-либо индивидуальным элементам кортежа (однако, вы можете симулировать большинство схожих эффектов за счёт операций срезов и конкатенации). Также можно создать кортежи, содержащие изменяемые объекты, такие как списки. Определённая проблема состоит в конструировании кортежей, состоящих из нуля или одного элемента: в синтаксисе языка есть дополнительные хитрости, позволяющие достигнуть этого. Пустые кортежи формируются за счёт пустой пары скобок; кортеж с одним элементом конструируется за счёт запятой, следующей за первым и единственным значением (его не обязательно заключать в скобки). Необычно, но эффективно. Например: <syntaxhighlight lang="python">>>> empty = () >>> singleton = 'hello', # <-- обратите внимание на замыкающую запятую >>> len(empty) 0 >>> len(singleton) 1 >>> singleton ('hello',)</syntaxhighlight> Выражение <code>t = 12345, 54321, 'hello!'</code> является примером ''упаковки кортежей'' (<tt>tuple packing</tt>): значения <code>12345</code>, <code>54321</code> и <code>'hello!'</code> упаковываются в кортеж вместе. Обратная операция также возможна: <syntaxhighlight lang="python">>>> x, y, z = t</syntaxhighlight> Такое действие называется, довольно удачно, ''распаковкой последовательности'' (<tt>sequence unpacking</tt>). Для распаковки на левой стороне требуется список переменных с количеством элементов равным длине последовательности. Обратите внимание, что множественное присваивание на самом деле является лишь комбинацией упаковки кортежа и распаковки последовательности. Здесь есть некоторая асимметрия: упаковка нескольких значений всегда создаёт кортеж, а распаковка работает для любой последовательности. === Множества === Python имеет также тип данных ''множество'' (<tt>set</tt>). Множество — это неупорядоченная коллекция без дублирующихся элементов. Основные способы использования — проверка на вхождение и устранение дублирующихся элементов. Объекты этого типа поддерживают обычные математические операции над множествами, такие как объединение, пересечение, разность и симметрическая разность. Для создания множеств могут быть использованы фигурные скобки или функция <tt>set()</tt>. ''Заметьте:'' Для создания пустого множества нужно использовать <code>set()</code>, а не <code>{}</code>: в последнем случае создаётся пустой ''словарь'' (<tt>dictionary</tt>) — тип данных, который мы обсудим в следующем разделе. Продемонстрируем работу с множествами на небольшом примере<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">>>> корзина = {'яблоко', 'апельсин', 'яблоко', 'груша', 'апельсин', 'банан'}<br/> >>> ''вывести''(корзина)<br/> {'апельсин', 'банан', 'яблоко', 'груша'}<br/> >>> список_фруктов = ['яблоко', 'апельсин', 'яблоко', 'груша', 'апельсин', 'банан']<br/> >>> фрукты = ''множество''(список_фруктов)&nbsp;&nbsp;&nbsp;&nbsp;# создать множество на основе данных из списка (заметьте исчезновение дубликатов -перев.)<br/> >>> фрукты<br/> {'апельсин', 'груша', 'яблоко', 'банан'}<br/> >>> фрукты = {'апельсин', 'яблоко'}&nbsp;&nbsp;&nbsp;&nbsp;# синтаксис {} эквивалентен [] у списков<br/> >>> фрукты<br/> {'апельсин', 'яблоко'}<br/> >>> 'апельсин' '''среди''' фрукты&nbsp;&nbsp;&nbsp;&nbsp;# быстрая проверка вхождения<br/> Истина<br/> >>> 'росичка' '''среди''' фрукты<br/> Ложь</code><br /><br /></ref>: <syntaxhighlight lang="python">>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'} >>> print(basket) {'orange', 'banana', 'pear', 'apple'} >>> fruit_list = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> fruit = set(fruit_list) # создать множество на основе данных из списка (заметьте исчезновение дубликатов -перев.) >>> fruit {'orange', 'pear', 'apple', 'banana'} >>> fruit = {'orange', 'apple'} # синтаксис {} эквивалентен [] у списков >>> fruit {'orange', 'apple'} >>> 'orange' in fruit # быстрая проверка на вхождение True >>> 'crabgrass' in fruit False</syntaxhighlight> <syntaxhighlight lang="python">>>> # Демонстрация операций со множествами на примере букв из двух слов ... >>> a = set('abracadabra') >>> b = set('alacazam') >>> a # уникальные буквы в a {'a', 'r', 'b', 'c', 'd'} >>> a - b # буквы в a но не в b {'r', 'd', 'b'} >>> a | b # все буквы, которые встречаются в a или в b {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'} >>> a & b # буквы, которые есть и в a и в b {'a', 'c'} >>> a ^ b # буквы в a или в b, но не в обоих {'r', 'd', 'b', 'm', 'z', 'l'}</syntaxhighlight> Как и у списков, у множеств существует синтаксис сборок: <syntaxhighlight lang="python">>>> a = {x for x in 'abracadabra' if x not in 'abc'} >>> a {'r', 'd'}</syntaxhighlight> === Словари === Другой полезный встроенный в Python тип данных — это ''словарь'' (<tt>dictionary</tt>) (см. [[Справочник по библиотеке Python 3.1#Связывающие типы|Справочник по библиотеке — Связывающие типы]]). Словари иногда встречаются в других языках в виде «ассоциативных записей» или «ассоциативных массивов». В отличие от последовательностей, которые индексируются по диапазону чисел, словари индексируются по ''ключам'' (<tt>keys</tt>), которые, в свою очередь, могут быть любого неизменяемого типа; строки и числа всегда могут быть ключами. Кортежи могут быть ключами только если они составлены из строк, чисел или кортежей; если кортеж содержит какой-либо изменяемый объект, явно или неявно, то он не может быть использован в качестве ключа. Вы не можете использовать списки в роли ключей, поскольку списки могут быть изменены на месте присваиванием по индексу, присваиванием по срезу или такими методами как <code>append()</code> и <code>extend()</code>. Лучше всего воспринимать словарь как неупорядоченный набор пар ''ключ: значение'' с требованием, чтобы ключи были уникальны (в пределах одного словаря). Пара скобок создает пустой словарь: <code>{}</code>. Указывая разделённый запятыми список пар ''ключ: значение'' внутри скобок, вы задаёте содержимое словаря; в таком же формате словарь можно вывести. Главные операции над словарём — это сохранение значения с каким-либо ключом и извлечение значения по указанному ключу. Также возможно удалить пару ''ключ: значение'' используя оператор <code>del</code>. Если вы сохраняете значение используя ключ, который уже встречается в словаре — старое значение, ассоциированное с этим ключом, стирается. Извлечение значения по несуществующему ключу вызывает ошибку. Выполнение конструкции <code>list(d.keys())</code> с объектом словаря возвращает список всех ключей, использующихся в словаре, в случайном порядке (если вы хотите отсортировать его, к списку ключей можно применить функцию <code>sorted()</code>). Чтобы проверить, содержит ли словарь определённый ключ, используйте ключевое слово <code>in</code>. Вот небольшой пример использования словарей: <syntaxhighlight lang="python">>>> tel = {'jack': 4098, 'sape': 4139} >>> tel['guido'] = 4127 >>> tel {'sape': 4139, 'guido': 4127, 'jack': 4098} >>> tel['jack'] 4098 >>> del tel['sape'] >>> tel['irv'] = 4127 >>> tel {'guido': 4127, 'irv': 4127, 'jack': 4098} >>> list(tel.keys()) ['irv', 'guido', 'jack'] >>> sorted(tel.keys()) ['guido', 'irv', 'jack'] >>> 'guido' in tel True >>> 'jack' not in tel False</syntaxhighlight> Конструктор <code>dict()</code> строит словарь непосредственно на основе пар ключей и значений, где каждая пара представлена в виде кортежа. Когда пары могут быть сформированы шаблоном, ''списковые сборки'' помогут описать список пар более компактно. <syntaxhighlight lang="python">>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}</syntaxhighlight> В дополнение ко всему этому, для создания словарей из произвольных выражений для ключей и значений, могут быть использованы словарные сборки: <syntaxhighlight lang="python">>>> {x: x**2 for x in (2, 4, 6)} {2: 4, 4: 16, 6: 36}</syntaxhighlight> Позже в учебнике мы изучим выражения-генераторы (<tt>Generator Expressions</tt>), которые даже лучше подходят для снабжения конструктора <code>dict()</code> парами ключ-значение. Если ключи являются простыми строками, иногда легче описать пары используя именованные параметры: <syntaxhighlight lang="python">>>> dict(sape=4139, guido=4127, jack=4098) {'sape': 4139, 'jack': 4098, 'guido': 4127}</syntaxhighlight> === Организация циклов === При организации перебора элементов из словаря ключ и соответствующее ему значение могут быть получены одновременно посредством метода <code>items()</code>. <syntaxhighlight lang="python">>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items(): ... print(k, v) ... gallahad the pure robin the brave</syntaxhighlight> Функция <code>enumerate()</code> поможет пронумеровать элементы перебираемой в цикле последовательности: <syntaxhighlight lang="python">>>> for i, v in enumerate(['tic', 'tac', 'toe']): ... print(i, v) ... 0 tic 1 tac 2 toe</syntaxhighlight> Для того, чтобы организовать цикл параллельно для двух или более последовательностей, элементы можно предварительно сгруппировать функцией <code>zip()</code><ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">>>> вопросы = ['имя', 'задание', 'любимый цвет']<br/> >>> ответы = ['ланцелот', 'святой грааль', 'синий']<br/> >>> '''для''' вопрос, ответ '''из''' ''застегнуть''(вопросы, ответы):<br/> ... &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''('Каков(о) ваш(е) {0}? {1}.'.форматировать(вопрос, ответ))<br/> ...<br/> Каков(о) ваш(е) имя? ланцелот.<br/> Каков(о) ваш(е) задание? святой грааль.<br/> Каков(о) ваш(е) любимый цвет? синий.</code></ref>. <syntaxhighlight lang="python">>>> questions = ['name', 'quest', 'favorite color'] >>> answers = ['lancelot', 'the holy grail', 'blue'] >>> for q, a in zip(questions, answers): ... print('What is your {0}? It is {1}.'.format(q, a)) ... What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue.</syntaxhighlight> Изменить порядок следования последовательности на обратный поможет функция <code>reversed()</code>. <syntaxhighlight lang="python">>>> for i in reversed(range(1, 10, 2)): ... print(i) ... 9 7 5 3 1</syntaxhighlight> Для организации цикла по отсортированной последовательности можно применить функцию <code>sorted()</code>, которая возвращает отсортированный список, оставляя исходный без изменений. <syntaxhighlight lang="python">>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> for f in sorted(set(basket)): ... print(f) ... apple banana orange pear</syntaxhighlight> === Подробнее об условиях === Условия в операторах <code>if</code> и <code>while</code> могут содержать любые операции, а не только операции сравнения. Операции сравнения <code>in</code> и <code>not in</code> проверяют, встречается значение в последовательности или нет. Операции <code>is</code> и <code>is not</code> проверяют, не являются ли два объекта на самом деле одним и тем же (это имеет смысл лишь для изменяемых объектов, таких как списки). Все операции сравнения имеют один и тот же приоритет, меньший чем у любых операций над числами. Сравнения можно объединять в цепочки. Например, <code>a < b == c</code> проверяет, меньше ли <code>a</code> чем <code>b</code> и, сверх того, равны ли <code>b</code> и <code>c</code>. Сравнения могут быть скомбинированы с использованием булевых операций <code>and</code> и <code>or</code>, а результат сравнения (или любого другого булева выражения) можно отрицать используя <code>not</code>. Эти операции имеют меньший приоритет, чем у операций сравнения; среди них у <code>not</code> высший приоритет, а у <code>or</code> — низший, поэтому <code>A and not B or C</code> эквивалентно <code>(A and (not B)) or C</code>. Как всегда, явно заданные скобки помогут выразить желаемый порядок выполнения операций. Булевы операции <code>and</code> и <code>or</code> — это так называемые ''коротящие операции''<ref>''(Прим. перев.)'' ''short-circuit''{{ref-en}} — закоротить, обходить, идти обходными путями (для достижения цели), препятствовать</ref> (<tt>short-circuit operators</tt>): их операнды вычисляются слева направо и вычисление заканчивается как только результат становится определён (очевиден). Например, если <code>A</code> и <code>C</code> истинны, а <code>B</code> — ложно, в условии <code>A and B and C</code> выражение <code>C</code> не вычисляется. Когда ''коротящая операция'' используется не в контексте логической операции, она возвращает последний элемент, который был вычислен. Можно присвоить результат сравнения, или другого булева выражения, переменной. Например, <syntaxhighlight lang="python">>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance' >>> non_null = string1 or string2 or string3 >>> non_null 'Trondheim'</syntaxhighlight> Заметьте, что в Python (в отличие от C) присваивание не может использоваться внутри выражений. Программисты на C могут возмутиться по этому поводу, но на самом деле это позволяет избежать ряда проблем, обычного для программ на C: указания оператора присваивания (<code>=</code>) в выражении, вместо предполагавшегося сравнения (<code>==</code>). === Сравнение последовательностей и других типов === Объекты последовательностей можно сравнивать с другими объектами с тем же типом последовательности. Сравнение использует лексикографический порядок: сравниваются первые два элемента, и если они различны — результат сравнения определён; если они равны, сравниваются следующие два элемента и так далее до тех пор, пока одна из последовательностей не будет исчерпана. Если сравниваемые два элемента сами являются последовательностями одного типа, лексикографическое сравнение происходит в них рекурсивно. Если все элементы обеих последовательностей оказались равны, последовательности считаются равными. Если одна последовательность оказывается стартовой последовательностью другой, более короткая последовательность считается меньшей. Лексикографическое упорядочивание строк использует порядок в таблице Unicode для индивидуальных символов. Несколько примеров сравнений между однотипными последовательностями: <syntaxhighlight lang="python">(1, 2, 3) < (1, 2, 4) [1, 2, 3] < [1, 2, 4] "Пайтон" < "Паскаль" < "Си" < "Си++" (1, 2, 3, 4) < (1, 2, 4) (1, 2) < (1, 2, -1) (1, 2, 3) == (1.0, 2.0, 3.0) (1, 2, ('aa', 'ab'), 4) < (1, 2, ('abc', 'a'))</syntaxhighlight> Обратите внимание, что сравнение объектов различных типов операциями <code><</code> или <code>></code> позволено, если объекты имеют соответствующие методы сравнения. Например, смешанные числовые типы сравниваются в соответствии с их численными значениями, так что <code>0</code> равен <code>0.0</code> и т. д. В противном случае интерпретатор, прервав процесс сортировки, возбудит исключение <code>TypeError</code>. == Модули == Если вы выйдете из интерпретатора и зайдёте в него снова, то все определённые вами имена (функции и переменные) будут потеряны. По этой причине, если вы захотите написать несколько более длинную программу, вам лучше использовать текстовый редактор для подготовки ввода для интерпретатора и запускать последний в режиме файлового ввода. Это называется созданием сценария. Если ваша программа становится обширнее, вы можете предпочесть разделить её на несколько файлов для удобства эксплуатации. Также вы можете захотеть использовать сразу в нескольких программах некоторую полезную функцию, написанную вами, не копируя её определение каждый раз. В языке Python можно поместить требуемые определения в файл и использовать их в сценариях или в интерактивном режиме интерпретатора. Такой файл называется ''модулем'' (<tt>module</tt>). Определения из модуля могут быть импортированы в других модулях, либо в главном модуле (собрание переменных, к которым есть доступ в сценарии, который непосредственно запускается, и в интерактивном режиме). Модуль — это файл, содержащий определения и операторы Python. Именем файла является имя модуля с добавленным суффиксом <tt>.py</tt>. Внутри модуля, имя модуля (в качестве строки) доступно в виде значения глобальной переменной с именем <code>__name__</code>. Например, используя ваш любимый текстовый редактор, создайте в текущем каталоге файл с именем <tt>fibo.py</tt> со следующим содержимым: <syntaxhighlight lang="python">"""Модуль вычисления чисел Фибоначчи""" def fib(n): # вывести числа Фибоначчи вплоть до n a, b = 0, 1 while b < n: print(b, end=' ') a, b = b, a+b print() def fib2(n): # вернуть числа Фибоначчи вплоть до n result = [] a, b = 0, 1 while b < n: result.append(b) a, b = b, a+b return result</syntaxhighlight> Теперь можно войти в интерпретатор Python и импортировать этот модуль следующей командой: <syntaxhighlight lang="python">>>> import fibo</syntaxhighlight> Это действие не переводит имена определённых в модуле функций в текущую таблицу символов, а лишь имя модуля <code>fibo</code>. Используя имя модуля, вы можете получить доступ к функциям: <syntaxhighlight lang="python">>>> fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo'</syntaxhighlight> Если вы собираетесь использовать функцию часто, можно присвоить её локальному имени: <syntaxhighlight lang="python">>>> fib = fibo.fib >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377</syntaxhighlight> === Подробнее о модулях === Помимо определений функций модуль может содержать исполняемые операторы. Назначение этих операторов — инициализация модуля: они выполняются при первом импортировании модуля где-либо<ref>Фактически, определения функций — те же «исполняемые» «операторы». Выполнение помещает имя функции в ''глобальную таблицу символов''.</ref>. Каждый модуль имеет свою собственную ''таблицу символов'', которая используется в качестве глобальной всеми определёнными в модуле функциями. Таким образом, автор модуля может использовать глобальные символы в модуле, не опасаясь неожиданных совпадений с глобальными переменными пользователя. С другой стороны, если вы знаете, что делаете, можно сослаться на глобальные переменные модуля, пользуясь той же нотацией, которая применялась для ссылок на его функции: <tt>''&lt;имя_модуля>''.''&lt;имя_элемента>''</tt>. Модули могут импортировать другие модули. Не требуется указывать все операторы <code>import</code> в начале модуля (или сценария, с той же целью), но обычно так и делается. Имена из импортированного модуля добавляются в ''глобальную таблицу символов'' модуля его импортирующего. Есть вариант оператора <code>import</code>, который переносит имена из модуля прямо в таблицу символов импортирующего модуля. Например: <syntaxhighlight lang="python">>>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377</syntaxhighlight> При этом имя самого модуля, из которого переносятся имена элементов, не добавляется в ''локальную таблицу символов'' (так, в этом примере, имя <code>fibo</code> не определено) И есть даже способ импортировать все имена, которые определяет данный модуль: <syntaxhighlight lang="python">>>> from fibo import * >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377</syntaxhighlight> Импортируются все имена, кроме тех, которые начинаются на подчёркивание (<code>_</code>). В большинстве случаев программисты на Python не используют эту возможность, поскольку она внедряет в интерпретатор целый набор новых неизвестных имён и может скрыть некоторые объекты, которые вы уже определили. {{Info2|Для повышения эффективности, каждый модуль импортируется лишь единожды за сеанс работы с интерпретатором. Поэтому, если вы изменили ваши модули, вам придётся перезапустить интерпретатор. Или, если вам нужно перезагрузить конкретный модуль, можно использовать <code>imp.reload()</code> таким образом: <code>import imp; imp.reload(<имя_модуля>)</code>}} ==== Выполнение модулей в качестве сценариев ==== Когда вы запускаете модуль Python в виде <syntaxhighlight lang="python">python fibo.py <параметры></syntaxhighlight> то код в этом модуле будет исполнен в момент его импортирования, но значением <code>__name__</code> будет строка <code>"__main__"</code>. Это значит, что добавляя следующий код в конец сценария: <syntaxhighlight lang="python">if __name__ == "__main__": import sys fib(int(sys.argv[1]))</syntaxhighlight> вы можете сделать возможным запуск файла и в качестве сценария, и в качестве импортируемого модуля. Это возможно, поскольку разбирающий командную строку код выполняется только при исполнении модуля как ''основного'' (<tt>main</tt>) файла: <syntaxhighlight lang="python">$ python fibo.py 50 1 1 2 3 5 8 13 21 34</syntaxhighlight> Если модуль импортируется, код не будет выполнен: <syntaxhighlight lang="python">>>> import fibo >>></syntaxhighlight> Такой приём часто используется, чтобы предоставить удобный пользовательский интерфейс к модулю или для тестирования (выполнение модуля в качестве сценария запускает набор тестов). ==== Путь поиска модулей ==== Если импортируется модуль с именем <code>spam</code>, интерпретатор ищет файл с именем <tt>spam.py</tt> в текущем каталоге, а затем в каталогах, указанных в переменной окружения <code>PYTHONPATH</code>. У неё такой же синтаксис, как и у переменной шелла <code>PATH</code>, которая, в свою очередь, является перечислением каталогов. Когда переменная <code>PYTHONPATH</code> не установлена, или файл не найден в описанных в ней местах, поиск продолжается по пути по умолчанию, зависящему от указанного при установке; на Unix это обычно <tt>.:/usr/local/lib/python</tt>. В действительности поиск модулей производится в списке каталогов в переменной <code>sys.path</code>, которая обычно содержит: каталог, в котором находится сценарий на входе (или текущий каталог), <code>PYTHONPATH</code> и умолчанием для каталога, указанного при установке. Это позволяет программам на Python (если программист знает, что делает) изменять или подменять путь поиска модулей. Заметьте: поскольку каталог, содержащий запускаемый вами сценарий, также находится в пути поиска, важно, чтобы в нем не было сценариев с именем стандартного модуля. Иначе, когда этот модуль будет импортироваться, Python будет пытаться загрузить в виде модуля сам сценарий, что в большинстве случаев вызовет ошибку. Для более подробной информации обратитесь к разделу [[Учебник Python 3.1#Стандартные модули|Стандартные модули]]. ==== «Скомпилированные» файлы Python ==== Интерпретатор Python применяет один важный приём для ускорения запуска программы: если в каталоге, где располагается файл с некоторым модулем <tt>spam.py</tt>, находится также файл <tt>spam.pyc</tt>, предполагается, что это уже скомпилированная в байт-код («<tt>byte-compiled</tt>») версия модуля <code>spam</code>. В файле <tt>spam.pyc</tt> зафиксировано время изменения файла <tt>spam.py</tt> версии, использовавшейся для создания <tt>spam.pyc</tt>. Если версии не совпадают — файл <tt>.pyc</tt> игнорируется. В обычном случае, вам не нужно ничего делать для создания файла <tt>spam.pyc</tt>. Каждый раз, когда <tt>spam.py</tt> успешно компилируется, предпринимается попытка записать скомпилированную версию в <tt>spam.pyc</tt>. Не считается ошибкой, если попытка неудачна: если по какой-либо причине файл не записан полностью, результирующий файл <tt>spam.pyc</tt> будет считаться некорректным и по этой причине в дальнейшем игнорироваться. Содержимое файла <tt>spam.pyc</tt> платформо-независимо, благодаря чему каталог модулей Python может использоваться параллельно машинами с различной архитектурой. Несколько советов экспертам: * Когда интерпретатор Python запускается с флагом <tt>'''-O'''</tt>, в файлах <tt>.pyo</tt> сохраняется сгенерированный оптимизированный код. На данный момент оптимизатор помогает не сильно — он лишь удаляет операторы <code>assert</code>. В случае использования <tt>'''-O'''</tt> оптимизируется весь ''байт-код'' (<tt>bytecode</tt>); файлы <tt>.pyc</tt> игнорируются, а файлы <tt>.py</tt> компилируются в оптимизированный байт-код. * Передача двух флагов <tt>'''-O'''</tt> интерпретатору Python (<tt>'''-OO'''</tt>) принуждает компилятор байт-кода выполнять оптимизации, в редких случаях результат выполнения которых оказывается некачественно функционирующей программой. На данный момент из байт-кода удаляются только строки <code>__doc__</code>, в результате получаются более компактные файлы <tt>.pyo</tt>. Поскольку некоторые программы могут рассчитывать на их (строк) доступность, следует использовать эту возможность только в том случае, если вы знаете что делаете. * Программа сама по себе не работает хоть сколь-нибудь быстрее, будучи прочитанной из файла <tt>.pyc</tt> или <tt>.pyo</tt>, чем если бы она была прочитана из файла <tt>.py</tt>. Единственный процесс, оказывающийся более быстрым при использовании файлов <tt>.pyc</tt> или <tt>.pyo</tt> — это скорость их подгрузки. * Если сценарий запущен из командной строки, его байт-код никогда не будет записан в файл <tt>.pyc</tt> или <tt>.pyo</tt>. Таким образом, время запуска сценария может быть уменьшено за счёт перемещения большей части его кода в модули или использования небольшого загрузочного сценария, импортирующего этот модуль. Кроме того, можно указывать файл <tt>.pyc</tt> или <tt>.pyo</tt> прямо в командной строке. * Можно иметь в наличии файл с именем <tt>spam.pyc</tt> (или <tt>spam.pyo</tt>, когда используется <tt>'''-O'''</tt>), не имея файла <tt>spam.py</tt> для того же модуля. Таким образом можно распространять библиотеки кода Python в том виде, из которого трудно восстановить исходный код. * Модуль <tt>[[Справочник по библиотеке Python 3.1#compileall|compileall]]</tt> может создать файлы <tt>.pyc</tt> (или файлы <tt>.pyo</tt>, когда используется <tt>'''-O'''</tt>) для всех модулей в каталоге. === Стандартные модули === Python поставляется с библиотекой стандартных модулей, описанной в отдельном документе, [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке Python]] (далее — «Справочнику по библиотеке»). Некоторые модули встроены в интерпретатор. Они обеспечивают доступ к операциям, не входящим в ядро языка, и встроены для большей эффективности и предоставления доступа к основным средствам операционной системы, таким как ''системные вызовы'' (<tt>system calls</tt>). Набор таких модулей — выбор настройки, зависимый от используемой платформы. Например, модуль <code>winreg</code> предоставляется только на системах с Windows. Один конкретный модуль заслуживает большего внимания: модуль <tt>[[Справочник по библиотеке Python 3.1#sys|sys]]</tt>, встроенный в каждую версию интерпретатора Python. Переменные <code>sys.ps1</code> и <code>sys.ps2</code> определяют строки, использующиеся в качестве основного и вспомогательного приглашений: <syntaxhighlight lang="python">>>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>> sys.ps1 = "Вводите: " Вводите: print('Ох!') Ох! Вводите: </syntaxhighlight> Эти две переменные определены только для интерактивного режима интерпретатора. Переменная <code>sys.path</code> представляет собой список строк, определяющий путь поиска модулей интерпретатора. Она инициализируется значением пути по умолчанию, взятым из переменной окружения <tt>PYTHONPATH</tt>, или встроенным значением по умолчанию, если <tt>PYTHONPATH</tt> не установлен. Вы можете изменить её значение, используя стандартные операции со списками: <syntaxhighlight lang="python">>>> import sys >>> sys.path.append('/ufs/guido/lib/python')</syntaxhighlight> === Функция <code>dir()</code> === Встроенная функция <code>dir()</code> используется для получения имён, определённых в модуле. Она возвращает отсортированный список строк: <syntaxhighlight lang="python">>>> import fibo, sys >>> dir(fibo) ['__name__', 'fib', 'fib2'] >>> dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'callstats', 'copyright', 'displayhook', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions']</syntaxhighlight> Будучи использованной без аргументов, функция <code>dir()</code> возвращает список имён, определённых в данный момент. <syntaxhighlight lang="python">>>> a = [1, 2, 3, 4, 5] >>> import fibo >>> fib = fibo.fib >>> dir() ['__builtins__', '__doc__', '__file__', '__name__', 'a', 'fib', 'fibo', 'sys']</syntaxhighlight> Обратите внимание, что список состоит из имён всех типов: переменных, модулей, функций и т. д. В возвращаемом функцией <code>dir()</code> списке не содержится встроенных функций и переменных. Если вы хотите получить ''их'' список, то они определены в стандартном модуле <code>builtins</code>: <syntaxhighlight lang="python">>>> import builtins >>> dir(builtins) ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'Buffer Error', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Excep tion', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError ', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImp lemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecatio nWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', ' UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueE rror', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__' , '__import__', '__name__', 'abs', 'all', 'any', 'basestring', 'bin', 'bool', 'b uffer', 'bytes', 'chr', 'chr8', 'classmethod', 'cmp', 'compile', 'complex', 'cop yright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'ex ec', 'exit', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'h ash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', ' len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'o bject', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr ', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'st r', 'str8', 'sum', 'super', 'trunc', 'tuple', 'type', 'vars', 'zip']</syntaxhighlight> === Пакеты === Пакеты — способ структурирования ''пространств имён'' (<tt>namespaces</tt>) модулей Python за счёт использования имён модулей, разделённых точками («<tt>dotted module names</tt>»). Например, имя модуля <code>A.B</code> означает — подмодуль<ref>''(Прим. перев.)'' ''подмодуль'' (<tt>submodule</tt>), ''зд.'' — модуль, находящийся в пакете. ''подпакет'' (<tt>subpackage</tt>), ''зд.'' — пакет, расположенный в пакете.</ref> с именем <code>B</code> в пакете с именем <code>A</code>. Так же как использование модулей позволяет авторам различных модулей не заботиться о пересекающихся именах среди глобальных переменных, использование именования через точку позволяет авторам многомодульных пакетов (таких как <tt>NumPy</tt> или <tt>Python Imaging Library</tt>) не заботиться о конфликтах имён модулей. Допустим, вы собираетесь разработать набор модулей (''пакет'', <tt>package</tt>) для унифицированной работы со звуковыми файлами и звуковыми данными. Существует множество форматов звуковых файлов (обычно их можно распознать по расширению, например: <tt>.wav</tt>, <tt>.aiff</tt>, <tt>.au</tt>). Таким образом, вам может понадобиться создать и поддерживать разрастающуюся коллекцию модулей для конвертирования между различными форматами файлов. Также вам наверняка захочется иметь побольше операций для обработки звуковых данных (таких как смешивание, добавление эха, применение функции эквалайзера, создание искусственного стерео-эффекта), поэтому в дополнение к этому вы будете писать нескончаемый поток модулей для исполнения этих операций. Вот возможная структура вашего пакета (выраженная в терминологии иерархической файловой системы): <pre style="color:#00008b;">sound/ Пакет верхнего уровня __init__.py Инициализация пакета работы со звуком (sound) formats/ Подпакет для конвертирования форматов файлов __init__.py wavread.py (чтение wav) wavwrite.py (запись wav) aiffread.py (чтение aiff) aiffwrite.py (запись aiff) auread.py (чтение au) auwrite.py (запись au) ... effects/ Подпакет для звуковых эффектов __init__.py echo.py ( эхо ) surround.py ( окружение ) reverse.py ( обращение ) ... filters/ Подпакет для фильтров __init__.py equalizer.py ( эквалайзер ) vocoder.py ( вокодер ) karaoke.py ( караоке ) ...</pre> При импорте пакета Python ищет подкаталог пакета в каталогах, перечисленных в <code>sys.path</code>. Файлы <tt>__init__.py</tt> необходимы для того, чтобы Python трактовал эти каталоги как содержащие пакеты. Это сделано во избежание нечаянного сокрытия правомерных модулей, встречающихся в дальнейшем по пути поиска, каталогами с часто используемыми именами, таким как «<code>string</code>». В наипростейшем случае файл <tt>__init__.py</tt> может быть пустым, но в более сложных может содержать код инициализации пакета или устанавливать значение описанной ниже переменной <code>__all__</code>. Пользователи пакета могут импортировать из него конкретные модули, например: <syntaxhighlight lang="python">import sound.effects.echo</syntaxhighlight> Таким образом подгружается подмодуль <code>sound.effects.echo</code>. Ссылаться на него нужно используя его полное имя: <syntaxhighlight lang="python">sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)</syntaxhighlight> Другой способ импортирования подмодуля: <syntaxhighlight lang="python">from sound.effects import echo</syntaxhighlight> Так тоже подгружается подмодуль <code>echo</code>, но теперь он доступен без префикса пакета, поэтому может использоваться следующим образом: <syntaxhighlight lang="python">echo.echofilter(input, output, delay=0.7, atten=4)</syntaxhighlight> И еще один вариант — прямое импортирование желаемой функции или переменной: <syntaxhighlight lang="python">from sound.effects.echo import echofilter</syntaxhighlight> Опять же, таким образом подгружается подмодуль <code>echo</code>, но теперь его функция <code>echofilter()</code> может быть вызвана непосредственно: <syntaxhighlight lang="python">echofilter(input, output, delay=0.7, atten=4)</syntaxhighlight> Заметьте, что при использовании выражения <code>from ''пакет'' import ''элемент''</code>, ''элементом'' может быть подмодуль (или подпакет) пакета или любое другое имя, определённое в пакете — например, функция, класс или переменная. Оператор <code>import</code> сначала проверяет, определён ли элемент в пакете; если нет — он трактует его как модуль и пытается загрузить. Если не удается его найти, порождается исключение <code>ImportError</code>. Напротив, при использовании синтаксиса в стиле <code>import ''элемент''.''подэлемент''.''подэлемент''</code>, все элементы кроме последнего должны быть пакетами; последний элемент может быть модулем или пакетом, но не может быть классом, функцией или переменной, определёнными в предыдущем элементе. ==== Импорт <code>*</code> из пакета ==== Что происходит, когда пользователь пишет <code>from sound.effects import *</code> ? В идеале, мы бы надеялись, что таким образом код выходит в файловую систему и находит какие подмодули существуют в пакете, импортируя их все. К сожалению, такой метод не очень хорошо работает на платформах Windows, поскольку у файловой системы не всегда есть корректная информация о регистре имён файлов. На этих платформах нет гарантированного способа узнать, нужно ли импортировать файл <tt>ECHO.PY</tt> в качестве модуля <code>echo</code>, <code>Echo</code> или <code>ECHO</code>. (Например, у Windows 95 есть назойливая привычка показывать имена всех файлов с заглавной буквы.) Ограничение DOS на имя файла в формате 8+3 добавляет забавную проблему, связанную с длинными именами модулей. Единственный выход для автора пакета — предоставить его подробное содержание. Оператор <code>import</code> использует следующее соглашение: если в коде файла <tt>__init__.py</tt> текущего пакета определён список <code>__all__</code>, то он полагается списком имён модулей, которые нужно импортировать в случае <code>from ''пакет'' import *</code>. На совести автора поддержка этого списка в соответствующем состоянии в каждой новой версии пакета. Впрочем, авторы пакета могут его не поддерживать вообще, если не видят смысла в импортировании <code>*</code> из их пакета. Например, файл <code>sounds/effects/__init__.py</code> может содержать следующий код: <syntaxhighlight lang="python">__all__ = ["echo", "surround", "reverse"]</syntaxhighlight> Это будет значить, что выражение <code>from sound.effects import *</code> импортирует три именованных подмодуля из пакета <code>sound</code>. Если список <code>__all__</code> не определён, оператор <code>from Sound.Effects import *</code> не импортирует все подмодули пакета <code>sound.effects</code> в текущее пространство имён: он лишь убеждается, что импортирован пакет <code>sound.effects</code> (возможно, выполняя код инициализации из <tt>__init__.py</tt>), а затем импортирует все определённые в пакете имена. В этот список попадают любые имена, определённые (и загруженные явно подмодулями) в <tt>__init__.py</tt>. В него также попадают все явно загруженные предшествующими операторами <code>import</code> подмодули. Рассмотрим следующий код: <syntaxhighlight lang="python">import sound.effects.echo import sound.effects.surround from sound.effects import *</syntaxhighlight> В этом примере модули <code>echo</code> и <code>surround</code> импортируются в текущее пространство имён, поскольку они определены в пакете <code>sound.effects</code> на тот момент, когда исполняется оператор <code>from ... import</code>. (И это также работает если определён <code>__all__</code>.) Обратите внимание, что в общем случае импортирование <code>*</code> из модуля не приветствуется, поскольку в результате часто получается плохо-читаемый код. Однако, вполне нормально использовать его в интерактивных сессиях, чтобы меньше печатать, а определённые модули разработаны для экспорта только тех имён, которые следуют определённым шаблонам. Помните: в использовании <code>from ''пакет'' import ''определённый_подмодуль''</code> нет ничего плохого. На самом деле — это рекомендованная запись, до тех пор пока при импортировании модуля не нужно использовать подмодули с одинаковым именем из разных пакетов. ==== Ссылки внутри пакета ==== Когда пакеты структурированы в подпакеты (например, в случае пакета <code>sound</code>), для того, чтобы сослаться на пакеты-потомки вы можете использовать абсолютное импортирование (<tt>absolute imports</tt>). Например, если модуль <code>sound.filters.vocoder</code> нуждается в модуле <code>echo</code> из пакета <code>sound.effects</code>, он должен использовать <code>from sound.effects import echo</code>. Вы можете также использовать ''относительное импортирование'' (<tt>relative imports</tt>), применяя следующую форму оператора <code>import</code>: <code>from ''модуль'' import ''имя''</code> . При таком способе импортирования для описания текущего и родительского пакетов используется символ точки. Например, для модуля <code>surround</code> вы можете написать: <syntaxhighlight lang="python">from . import echo from .. import formats from ..filters import equalizer</syntaxhighlight> Обратите внимание, что относительное импортирование основано на имени текущего модуля. Поскольку имя главного модуля всегда «<code>__main__</code>», модули, предназначенные для использования в качестве главных модулей приложения на Python, должны всегда использовать ''абсолютное импортирование'' (<tt>absolute imports</tt>). ==== Пакеты в нескольких каталогах ==== Пакеты поддерживают ещё один специальный аттрибут: <code>__path__</code>. Перед исполнением файла <tt>__init__.py</tt> этого пакета, он инициализируется списком, содержащим имя каталога, в котором этот файл находится. Изменив переменную, можно повлиять на ход поиска модулей и подпакетов, содержащихся в пакете. Хотя эта возможность нужна не так часто, она может быть использована для расширения набора модулей, находящихся в пакете. == Ввод и вывод == Ознакомить пользователя с выводом программы можно различными способами — данные могут быть выведены в читаемом виде или записаны в файл для последующего использования. Часть возможностей будет обсуждена в этой главе. === Удобное форматирование вывода === На данный момент мы выяснили два способа вывода значений: ''операторные выражения'' (<tt>expression statements</tt>) и функция <code>print()</code>. (Третий способ — использование метода <code>write()</code> объектов файлов; на файл стандартного вывода можно сослаться как на <code>sys.stdout</code>. Более подробную информацию по этому пункту смотрите в [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке]].) Часто возникает желание иметь больший контроль над форматированием вывода, чем обычная печать значений разделённых пробелами. Есть два способа форматирования вашего вывода. Первый способ — выполнять самостоятельно всю работу над строками: используя срезы строк и конкатенацию вы можете создать любой шаблон, какой пожелаете. Стандартный модуль <code>string</code> содержит много полезных операций для выравнивания строк по определённой ширине колонки (скоро мы их кратко рассмотрим). Второй способ — использование метода <code>str.format()</code>. Модуль <code>string</code> содержит класс <code>Template</code>, который предоставляет ещё один способ подстановки значений в строки. Остаётся, конечно, один вопрос: каким образом конвертировать значения в строки? К счастью, в Python есть два способа для преобразования любого значения в строку — это функции <code>repr()</code> и <code>str()</code>. Предназначение функции <code>str()</code> — возврат значений в довольно-таки читабельной форме; в отличие от <code>repr()</code>, чьё назначение — генерирование форм<ref>(''Прим. перев.'') ''representation'' {{ref-en}} — представление, образ, форма</ref>, которые могут быть прочитаны интерпретатором (или вызовут ошибку <code>SyntaxError</code>, если эквивалентного синтаксиса не существует). Для тех объектов, у которых нет формы для человеческого прочтения функция <code>str()</code> возвратит такое же значение, как и <code>repr()</code>. У многих значений, таких как числа или структуры, вроде списков и словарей, одинаковая форма для обеих функций. Строки и числа с плавающей точкой, в частности, имеют по две разных формы. Несколько примеров: <syntaxhighlight lang="python">>>> s = 'Привет, мир.' >>> str(s) 'Привет, мир.' >>> repr(s) "'Привет, мир.'" >>> str(0.1) '0.1' >>> repr(0.1) '0.10000000000000001' >>> x = 10 * 3.25 >>> y = 200 * 200 >>> s = 'Значение x - ' + repr(x) + ', а y - ' + repr(y) + '...' >>> print(s) Значение x - 32.5, а y - 40000... >>> # Функция repr(), применённая к строке, добавляет кавычки и обратные слэши: ... hello = 'привет, мир\n' >>> hellos = repr(hello) >>> print(hellos) 'привет, мир\n' >>> # Параметром функции repr() может быть объект Python: ... repr((x, y, ('фарш', 'яйца'))) "(32.5, 40000, ('фарш', 'яйца'))"</syntaxhighlight> Вот два способа вывести таблицу квадратов и кубов: <syntaxhighlight lang="python">>>> for x in range(1, 11): ... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ') ... # Обратите внимание на использование end в предыдущей строке ... print(repr(x*x*x).rjust(4)) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 >>> for x in range(1, 11): ... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000</syntaxhighlight> (Обратите внимание, что в первом примере единичные пробелы между колонками добавлены функцией <code>print()</code>: она всегда вставляет пробелы между своими параметрами) Этот пример демонстрирует работу метода строковых объектов <code>rjust()</code>, выравнивающего строку по правому краю в поле переданной ширины, отступая пробелами слева. Имеются также похожие методы <code>ljust()</code> и <code>center()</code>. Эти методы не выводят ничего, они лишь возвращают новую строку. Если строка на входе чересчур длинная, то они не усекают её, что обычно является меньшим из зол. (Для усечения можно добавить операцию среза, например: <code>x.ljust(n)[:n]</code>.) Есть другой метод — <code>zfill()</code>, который заполняет нулями пространство слева от числовой строки. Он распознаёт знаки плюс и минус: <syntaxhighlight lang="python">>>> '12'.zfill(5) '00012' >>> '-3.14'.zfill(7) '-003.14' >>> '3.14159265359'.zfill(5) '3.14159265359'</syntaxhighlight> Основной способ применения метода <code>str.format()</code> выглядит так<ref>''(Прим. перев.)'' We are the knights who say «Ni!» (''Мы — те рыцари, что говорят «Ни!»'') — цитата из [http://www.mwscomp.com/movies/grail/grail-13.htm сцены 13-й] фильма Монти Пайтон и Святой Грааль (Monty Python and Holy Grail)</ref>: <syntaxhighlight lang="python">>>> print('Мы — те {0}, что говорят "{1}!"'.format('рыцари', 'Ни')) Мы — те рыцари, что говорят "Ни!"</syntaxhighlight> Скобки с символами внутри (их называют ''полями форматирования'' (<tt>format fields</tt>)) заменяются на объекты, переданные методу <code>format</code>. Номер в скобках обозначает позицию объекта в списке параметров, переданных методу <code>format</code>. <syntaxhighlight lang="python">>>> print('{0} и {1}'.format('фарш', 'яйца')) фарш и яйца >>> print('{1} и {0}'.format('фарш', 'яйца')) яйца и фарш</syntaxhighlight> Если в методе <code>format</code> используются именованные параметры, можно ссылаться на их значения, используя имя соответствующего аргумента<ref>''(Прим. перев.)'' <tt>вывести('Этот {пища} — {прилагательное}.'.format(пища='фарш', прилагательное='непередаваемо ужасен'))</tt></ref>. <syntaxhighlight lang="python">>>> print('Этот {food} — {adjective}.'.format( ... food='фарш', adjective='непередаваемо ужасен')) Этот фарш — непередаваемо ужасен.</syntaxhighlight> Позиционные и именованные параметры можно произвольно совмещать<ref>''(Прим. перев.)'' <tt>вывести('История о {0}, {1}, и {другой}.'.format('Билл', 'Манфред', другой='Георг'))</tt></ref>: <syntaxhighlight lang="python">>>> print('История о {0}е, {1}е, и {other}е.'.format('Билл', 'Манфред', other='Георг')) История о Билле, Манфреде, и Георге.</syntaxhighlight> После имени поля может следовать необязательный спецификатор формата ‘<code>:</code>’. С его помощью можно управлять форматированием значения. Следующий пример оставляет у числа Пи только три цифры после десятичного разделителя<ref>''(Прим. перев.)'' В качестве десятичного разделителя в Python используется точка, в соответствии со стандартами большинства стран.</ref>. <syntaxhighlight lang="python">>>> import math >>> print('Значение ПИ — примерно {0:.3f}.'.format(math.pi)) Значение ПИ — примерно 3.142.</syntaxhighlight> После спецификатора ‘<code>:</code>’ можно указать число — минимальную ширину поля, выраженную в количестве символов. Это удобно использовать для создания красивых таблиц: <syntaxhighlight lang="python">>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678} >>> for name, phone in table.items(): ... print('{0:10} ==> {1:10d}'.format(name, phone)) ... Jack ==> 4098 Dcab ==> 7678 Sjoerd ==> 4127</syntaxhighlight> Если ваша строка с форматами очень длинна, а вы не хотите разбивать её на подстроки, было бы неплохо если бы вы могли ссылаться на переменные, предназначенные для форматирования, не по позиции, а по имени. Это можно сделать, просто передав словарь и используя квадратные скобки ‘<tt>[]</tt>’ для доступа к ключам. <syntaxhighlight lang="python">>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; ' 'Dcab: {0[Dcab]:d}'.format(table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678</syntaxhighlight> Тоже самое можно сделать, передав словарь именованных параметров, используя нотацию «<code>**</code>»: <syntaxhighlight lang="python">>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678</syntaxhighlight> В частности, такой приём удобно использовать в сочетании со встроенной функцией <code>vars()</code>, которая возвращает словарь с локальными переменными. Подробное описание форматирования строк с применением метода <code>str.format()</code> описано в разделе [[Справочник по библиотеке Python 3.1#Синтаксис строк форматирования|Синтаксис строк форматирования]]. ==== Форматирование строк в старом стиле ==== Для форматирования строк можно использовать и операцию <code>%</code>. Она интерпретирует левый операнд как строку форматирования в стиле <code>sprintf</code>, которую следует применить к правому операнду, и возвращает строку, получившуюся в результате этого преобразования. Например: <syntaxhighlight lang="python">>>> import math >>> print 'Значение ПИ — примерно %5.3f.' % math.pi Значение ПИ — примерно 3.142.</syntaxhighlight> Поскольку метод <code>str.format()</code> довольно нов, большая часть исходных кодов Python всё ещё использует операцию <code>%</code>. Однако, со временем, форматирование строк будет удалено из языка, поэтому в большинстве случаев следует использовать <code>str.format()</code>. Больше информации можно найти в разделе [[Справочник по библиотеке Python 3.1#Операции форматирования строк в старом стиле|Операции форматирования строк в старом стиле]]. === Запись и чтение файлов === Функция <code>open()</code> возвращает объект файла и в большинстве случаев используется с двумя аргументами: <code>open(''имя_файла'', ''режим'')</code>. <syntaxhighlight lang="python">>>> f = open('/tmp/workfile', 'w')</syntaxhighlight> Первый параметр — строка, содержащая имя файла. Второй — другая строка, содержащая несколько символов, описывающих способ использования файла. Значение параметра ''режим'' может быть символом <code>'r'</code>, если файл будет открыт только для чтения, <code>'w'</code> — открыт только для записи (существующий файл с таким же именем будет стёрт) и <code>'a'</code> — файл открыт для добавления: любые данные, записанные в файл автоматически добавляются в конец. <code>'r+'</code> открывает файл и для чтения, и для записи. Параметр ''режим'' необязателен: если он опущен — предполагается, что он равен <code>'r'</code>. В обычном случае файлы открываются в ''текстовом режиме'' (<tt>text mode</tt>) — это значит что вы читаете из файла и записываете в файл строки в определённой кодировке (по умолчанию используется <tt>UTF-8</tt>). Если добавить к режиму файла символ ‘<code>b</code>’, файл открывается в ''двоичном режиме'' (<tt>binary mode</tt>): теперь данные считываются и записываются в виде двоичных объектов. Этот режим следует использовать для всех файлов, которые не содержат текст. При использовании текстового режима, все окончания строк, по умолчанию, специфичные для платформы (<code>\n</code> в Unix, <code>\r\n</code> в Windows) усекаются до символа <code>\n</code>, при чтении из файла, и конвертируются обратно из <code>\n</code> в вид, специфичный для платформы, при записи в файл. Эти закулисные изменения в файловых данных корректно работают в случае текстовых файлов, но испортят двоичные данные в файлах вроде <code>JPEG</code> или <code>EXE</code>. Внимательно следите за тем, чтобы использовать двоичный режим при чтении и записи таких файлов. ==== Методы объектов-файлов ==== В примерах ниже подразумевается, что заранее создан файловый объект с именем <code>f</code>. Чтобы прочитать содержимое файла, вызовите <code>f.read(''размер'')</code> — функция читает некоторое количество данных и возвращает их в виде строки или байтового объекта. <code>''размер''</code> — необязательный числовой параметр. Если <code>''размер''</code> опущен или отрицателен, будет прочитано и возвращено всё содержимое файла; если файл по величине в два раза больше оперативной памяти вашего компьютера, то решение этой проблемы остаётся на вашей совести. В противном случае, будет прочитано и возвращено максимум <code>''размер''</code> байт. Если был достигнут конец файла, <code>f.read()</code> вернёт пустую строку (<code>''</code>). <syntaxhighlight lang="python">>>> f.read() 'Это всё содержимое файла.\n' >>> f.read() ''</syntaxhighlight> <code>f.readline()</code> читает одну строку из файла; символ новой строки (<code>\n</code>) остаётся в конце прочитанной строки и отсутствует при чтении последней строки файла только если файл не оканчивается пустой строкой. За счёт этого возвращаемое значение становится недвусмысленным: если <code>f.readline()</code> возвращает пустую строку — достигнут конец файла, в то же время незаполненная строка, представленная посредством <code>'\n'</code>, содержит лишь символ новой строки.<ref>''(Прим. перев.)'' В источнике, в большинстве случаев, разделяется понятие ''строки'' как типа данных и ''строки'' как строки текста (ср., ''строчка'') применением слов ''string'' и ''line'' соответственно. В русском языке это различие передать сложно, тем не менее я старался по возможности избежать двусмысленностей.</ref> <syntaxhighlight lang="python">>>> f.readline() 'Это первая строка файла.\n' >>> f.readline() 'Вторая строка файла\n' >>> f.readline() ''</syntaxhighlight> <code>f.readlines()</code> возвращает список, содержащий все строки с данными, обнаруженные в файле. Если передан необязательный параметр <code>подсказка_размера</code>, функция читает из файла указанное количество байт, плюс некоторое количество байт сверх того, достаточное для завершения строки, и формирует список строк из результата. Функция часто используется для более эффективного (файл не загружается в память полностью) построчного чтения больших файлов. Возвращены будут только полные (завершённые) строки. <syntaxhighlight lang="python">>>> f.readlines() ['Это первая строка файла.\n', 'Вторая строка файла\n']</syntaxhighlight> Альтернативный способ построчного чтения — организация цикла по файловому объекту. Он быстр, рационально использует память и имеет простой код в результате: <syntaxhighlight lang="python">>>> for line in f: print(line, end='') Это первая строка файла. Вторая строка файла</syntaxhighlight> Альтернативный способ проще, но не предоставляет тонкого контроля над происходящим. Поскольку оба этих способа работают с буферизацией строк по-разному, их не следует смешивать. <code>f.write(''строка'')</code> записывает содержимое ''строки'' в файл и возвращает количество записанных байтов. <syntaxhighlight lang="python">>>> f.write('This is a test\n') 15</syntaxhighlight> Чтобы записать в файл нечто отличное от строки, предварительно это нечто нужно в строку сконвертировать<ref>''(Прим. перев.)'' Возможно, подразумевается [[w:ru:Ответ на главный вопрос жизни, вселенной и всего такого|ответ на главный вопрос жизни, вселенной и всего такого]]</ref>: <syntaxhighlight lang="python">>>> value = ('ответ', 42) >>> s = str(value) >>> f.write(s) 18</syntaxhighlight> <code>f.tell()</code> возвращает целое, представляющее собой текущую позицию в файле <code>f</code>, измеренную в байтах от начала файла. Чтобы изменить позицию объекта-файла, используйте <code>f.seek(''смещение'', ''откуда'')</code>. Позиция вычисляется прибавлением смещения к точке отсчёта; точка отсчёта выбирается из параметра <code>''откуда''</code>. Значение <code>0</code> параметра <code>''откуда''</code> отмеряет смещение от начала файла, значение <code>1</code> применяет текущую позицию в файле, а значение <code>2</code> в качестве точки отсчёта использует конец файла. Параметр <code>''откуда''</code> может быть опущен и по умолчанию устанавливается в <code>0</code>, используя начало файла в качестве точки отсчёта. <syntaxhighlight lang="python">>>> f = open('/tmp/workfile', 'rb+') >>> f.write(b'0123456789abcdef') 16 >>> f.seek(5) # Перейти к шестому байту в файле 5 >>> f.read(1) b'5' >>> f.seek(-3, 2) # Перейти к третьему байту с конца 13 >>> f.read(1) b'd'</syntaxhighlight> При работе с текстовыми файлами (открытыми без символа <code>b</code> в строке режима), выполнять позиционирование (<code>seek</code>) позволяется только от начала файла (за исключением прокрутки в конец файла с использованием <code>seek(0, 2)</code>). Когда вы закончили все действия над файлом, вызовите <code>f.close()</code> чтобы закрыть его и освободить все системные ресурсы, использованные при открытии этого файла. Все попытки использовать объект-файл после вызова <code>f.close()</code> приведут к возникновению исключения. <syntaxhighlight lang="python">>>> f.close() >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: I/O operation on closed file</syntaxhighlight> Считается хорошей манерой использовать ключевое слово <code>with</code> при работе с файловыми объектами. Преимущество этого способа в том, что файл всегда корректно закрывается после выполнения блока, либо если при выполнении было порождено исключение. Кроме того, получающийся код намного короче, чем эквивалентная форма с блоками <tt><code>try</code>-<code>finally</code></tt>: <syntaxhighlight lang="python">>>> with open('/tmp/workfile', 'r') as f: ... read_data = f.read() >>> f.closed True</syntaxhighlight> У объектов-файлов есть ещё несколько дополнительных методов, таких как <code>isatty()</code> и <code>truncate()</code>, которые используются не так часто; обратитесь к [[Справочник по библиотеке Python 3.1|Справочнику по библиотеке]] для более полного обзора по файловым объектам. ==== Модуль <code>pickle</code> ==== Строки могут с лёгкостью быть записаны в файл и прочитаны из файла. В случае чисел нужно применить несколько больше усилий: метод <code>read()</code> возвращает только строки, которые придётся передать функции вроде <code>int()</code>, которая принимает строку вида <code>'123'</code> и возвращает её числовое значение: <code>123</code>. Однако если вы намереваетесь сохранить более сложные типы данных, такие как списки, словари или экземпляры классов, всё становится несколько запутаннее. Вместо того чтобы принуждать программиста постоянно писать и отлаживать код для замысловатых типов данных, Python предоставляет стандартный модуль под названием <code>pickle</code>. Это замечательный модуль, который может принять любой объект Python (даже некоторые формы кода на Python!) и конвертировать его в строковое представление: этот процесс называется ''консервацией'' (<tt>pickling</tt>). Восстановление объекта из его строкового представления называется ''расконсервацией'' (<tt>unpickling</tt>): строка, описывающая объект, может быть сохранена в файл, добавлена к некоторым данным, или отослана через соединение по сети на удаленный компьютер.<ref>''(Прим. перев.)'' ''Консервирование'' в Python можно рассматривать как частный случай [[w:ru:Сериализация|сериализации]]; ещё про ''консервирование'' можно почитать [http://www.ibm.com/developerworks/ru/library/l-pypers/index.html здесь].</ref> Если у вас есть некоторый объект <code>x</code> и объект файла <code>f</code>, открытый на запись в двоичном режиме (binary mode, с параметром 'wb'), простейший способ ''законсервировать'' объект требует одной-единственной строки кода: <syntaxhighlight lang="python">pickle.dump(x, f)</syntaxhighlight> Чтобы снова расконсервировать объект, при условии что <code>f</code> — объект файла, открытого для чтения (так же в двоичном режиме, с параметром 'rb'): <syntaxhighlight lang="python">x = pickle.load(f)</syntaxhighlight> (Существуют варианты выполнения этих операций, применяемые при ''расконсервации'' нескольких объектов или когда вам требуется записать ''консервированные'' данные в файл; обратитесь к документации по модулю [[Справочник по библиотеке Python 3.1#pickle|pickle]] из [[Справочник по библиотеке Python 3.1|Справочника по библиотеке]].) [[Справочник по библиотеке Python 3.1#pickle|pickle]] — стандартный способ для создания объектов Python, которые могут быть повторно использованы другими программами или будущими версиями этой же программы; для них есть технический термин — ''устойчивый объект'' (<tt>persistent object</tt>). Поскольку [[Справочник по библиотеке Python 3.1#pickle|pickle]] используется часто, многие авторы расширений для Python заботятся о том, чтобы новые типы данных, такие как матрицы, могли быть корректно ''законсервированы'' и ''расконсервированы''. == Ошибки и исключения == До этого момента сообщения об ошибках лишь упоминались, но если вы пробовали примеры на практике — возможно, вы уже видели некоторые. Существует (как минимум) два различимых вида ошибок: ''синтаксические ошибки'' (<tt>syntax errors</tt>) и ''исключения'' (<tt>exceptions</tt>). === Синтаксические ошибки === Синтаксические ошибки, также известные как ошибки разбора кода (''парсинга'', <tt>parsing</tt>) — вероятно, наиболее привычный вид жалоб компилятора, попадающихся вам при изучении Python: <syntaxhighlight lang="python">>>> while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^ SyntaxError: invalid syntax</syntaxhighlight> Парсер<ref>''(Прим. перев.)'' ''Parser'' {{ref-en}} — программа синтаксического анализа, синтаксический анализатор; программа грамматического разбора</ref> повторно выводит ошибочную строку и отображает небольшую «стрелку», указывающую на самую первую позицию в строке, где была обнаружена ошибка. Причина ошибки (или по крайней мере место обнаружения) находится в символе<ref>''(Прим. перев.)'' ''Token'' {{ref-en}} — некоторая смысловая единица выражения: оператор, ключевое слово, значение переменной, …</ref>, предшествующем указанному: в приведённом примере ошибка обнаружена на месте вызова функции <code>print()</code>, поскольку перед ним пропущено двоеточие (<code>':'</code>). Также здесь выводятся имя файла и номер строки, благодаря этому вы знаете в каком месте искать, если ввод был сделан из сценария. === Исключения === Даже если выражение или оператор синтаксически верны, они могут вызвать ошибку при попытке их исполнения. Ошибки, обнаруженные при исполнении, называются ''исключениями'' (<tt>exceptions</tt>). Они не фатальны: позже вы научитесь перехватывать их в программах на Python. Большинство исключений, правда, как правило, не обрабатываются программами и приводят к сообщениям об ошибке, таким как следующие: <syntaxhighlight lang="python">>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in ? ZeroDivisionError: int division or modulo by zero >>> 4 + spam*3 Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: coercing to Unicode: need string or buffer, int found</syntaxhighlight> Последняя строка сообщения об ошибке описывает произошедшее. Исключения представлены различными типами и тип исключения выводится в качестве части сообщения: в примере это типы <code>ZeroDivisionError</code>, <code>NameError</code> и <code>TypeError</code>. Часть строки, описывающая тип исключения — это имя произошедшего встроенного исключения. Такое утверждение верно для всех встроенных исключений, но не обязано быть истинным для исключений, определённых пользователем (однако, само соглашение — довольно полезное). Имена стандартных исключений — это встроенные идентификаторы (не ключевые слова). Оставшаяся часть строки описывает детали произошедшего на основе типа исключения, которое было его причиной. Предшествующая часть сообщения об ошибке показывает контекст, где произошло исключение, в форме стека вызовов. В общем случае она содержит стек, состоящий из списка строк исходного кода; тем не менее, в неё не войдут строки, прочитанные из стандартного ввода. В разделе [[Справочник по библиотеке Python 3.1#Встроенные исключения|Встроенные исключения]] [[Справочник по библиотеке Python 3.1|Справочника по библиотеке]] вы найдёте список встроенных исключений и их значений. === Обработка исключений === Существует возможность написать код, который будет перехватывать избранные исключения. Посмотрите на представленный пример, в котором пользователю предлагают вводить число до тех пор, пока оно не окажется корректным целым. Тем не менее, пользователь может прервать программу (используя сочетание клавиш <tt>Control-C</tt> или какое-либо другое, поддерживаемое операционной системой); заметьте — о вызванном пользователем прерывании сигнализирует исключение <code>KeyboardInterrupt</code>. <syntaxhighlight lang="python">>>> while True: ... try: ... x = int(input("Введите, пожалуйста, число: ")) ... break ... except ValueError: ... print("Ой! Это некорректное число. Попробуйте ещё раз...") ...</syntaxhighlight> Оператор <code>try</code> работает следующим образом: * В начале исполняется ''блок <code>try</code>'' (операторы между ключевыми словами <code>try</code> и <code>except</code>). * Если при этом не появляется исключений, ''блок <code>except</code>'' не выполняется и оператор <code>try</code> заканчивает работу. * Если во время выполнения блока <code>try</code> было возбуждено какое-либо исключение, оставшаяся часть блока не выполняется. Затем, если тип этого исключения совпадает с исключением, указанным после ключевого слова <code>except</code>, выполняется блок <code>except</code>, а по его завершению выполнение продолжается сразу после оператора <code>try-except</code>. * Если порождается исключение, не совпадающее по типу с указанным в блоке <code>except</code> — оно передаётся внешним операторам <code>try</code>; если ни одного обработчика не найдено, исключение считается ''необработанным'' (<tt>unhandled exception</tt>), и выполнение полностью останавливается и выводится сообщение, схожее с показанным выше. Оператор <code>try</code> может иметь более одного блока <code>except</code> — для описания обработчиков различных исключений. При этом будет выполнен максимум один обработчик. Обработчики ловят только те исключения, которые возникают внутри соответствующего блока <code>try</code>, но не те, которые возникают в других обработчиках этого же самого оператора <code>try-except</code>. Блок <code>except</code> может указывать несколько исключений в виде заключённого в скобки кортежа, например: <syntaxhighlight lang="python">... except (RuntimeError, TypeError, NameError): ... pass</syntaxhighlight> В последнем блоке <code>except</code> можно не указывать имени (или имён) исключений. Тогда он будет действовать как обработчик группы исключений. Используйте эту возможность с особой осторожностью, поскольку таким образом он может с лёгкостью перехватить и фактическую ошибку программиста! Также такой обработчик может быть использован для вывода сообщения об ошибке и порождения исключения заново (позволяя при этом обработать исключение коду, вызвавшему обработчик): <syntaxhighlight lang="python">import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except IOError as err: print("I/O error: {0}".format(err)) except ValueError: print("Не могу преобразовать данные в целое.") except: print("Неожиданная ошибка:", sys.exc_info()[0]) raise</syntaxhighlight> У оператора <code>try-except</code> есть необязательный ''блок <code>else</code>'', который, если присутствует, должен размещаться после всех блоков <code>except</code>. Его полезно использовать при наличии кода, который должен быть выполнен, если блок <code>try</code> не породил исключений. Например: <syntaxhighlight lang="python">for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print('не могу открыть', arg) else: print(arg, 'содержит', len(f.readlines()), 'строк') f.close()</syntaxhighlight> Использование блока <code>else</code> предпочтительнее, чем добавление дополнительного кода к блоку <code>try</code>, поскольку исключает неожиданный перехват исключения, которое появилось не по причине выполнения кода, защищенного оператором <code>try-except</code>. При появлении исключения, оно может иметь ассоциированное значение, также известное как ''аргумент'' (<tt>argument</tt>) исключения. Присутствие и тип аргумента зависят от типа самого исключения. В блоке <code>except</code> можно указать переменную, следующую за именем исключения. Переменная связывается с экземпляром исключения, аргументы которого хранятся в <code>instance.args</code>. Для удобства, экземпляр исключения определяет метод <code>__str__()</code>, так что вывод аргументов может быть произведён явно, без необходимости отсылки к <code>.args</code>. Таким образом, вы также можете создать/взять экземпляр исключения перед его порождением и добавить к нему атрибуты по желанию. <syntaxhighlight lang="python">>>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print(type(inst)) # экземпляр исключения ... print(inst.args) # аргументы хранятся в .args ... print(inst) # __str__ позволяет вывести args явно, ... # но может быть переопределён в подклассах исключения ... x, y = inst # распаковка args ... print 'x =', x ... print 'y =', y ... <class 'Exception'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs</syntaxhighlight> Если у исключения есть аргументы, они выводится в качестве последней («детальной») части сообщения о необработанном исключении. Обработчики исключений перехватывают не только исключения, появившиеся прямо в блоке <code>try</code>, но также и возбужденные внутри функций, которые были в блоке <code>try</code> вызваны (даже неявно). Например: <syntaxhighlight lang="python">>>> def this_fails(): ... x = 1/0 ... >>> try: ... this_fails() ... except ZeroDivisionError as err: ... print('Перехват ошибки времени исполнения:', err) ... Перехват ошибки времени исполнения: integer division or modulo by zero</syntaxhighlight> === Порождение исключений === Оператор <code>raise</code> позволяет программисту принудительно породить исключение. Например: <syntaxhighlight lang="python">>>> raise NameError('ПриветТам') Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: ПриветТам</syntaxhighlight> Единственный аргумент оператора <code>raise</code> определяет исключение, которое нужно возбудить. Им может быть либо экземпляр исключения, либо класс исключения (класс, дочерний к классу <code>Exception</code>). Если вам нужно определить, было ли возбуждено исключение, не перехватывая его — упрощённая форма оператора <code>raise</code> позволит возбудить исключение заново: <syntaxhighlight lang="python">>>> try: ... raise NameError('ПриветТам') ... except NameError: ... print('Исключение пролетело мимо!') ... raise ... Исключение пролетело мимо! Traceback (most recent call last): File "<stdin>", line 2, in ? NameError: ПриветТам</syntaxhighlight> === Исключения, определённые пользователем === В программах можно определять свои собственные исключения — посредством создания нового класса исключения. В общем случае, исключения должны быть унаследованы от класса <code>Exception</code>: явно или неявно. Например: <syntaxhighlight lang="python">>>> class MyError(Exception): ... def __init__(self, value): ... self.value = value ... def __str__(self): ... return repr(self.value) ... >>> try: ... raise MyError(2*2) ... except MyError as e: ... print('Поймано моё исключение со значением:', e.value) ... Поймано моё исключение со значением: 4 >>> raise MyError('ой!') Traceback (most recent call last): File "<stdin>", line 1, in ? __main__.MyError: 'ой!'</syntaxhighlight> В этом примере был перегружен конструктор по умолчанию <code>__init__()</code> класса <code>Exception</code>. Новое поведение отличается лишь созданием нового атрибута <code>value</code> и заменяет поведение по умолчанию, при котором создаётся атрибут <code>args</code>. Классы исключений могут определять любые действия, которые могут делать все другие классы. Однако, обычно их внутренняя структура довольно проста, и предоставляет лишь некоторые атрибуты, позволяющие обработчикам исключений выяснить информацию об ошибке подробно. При создании модуля, который может породить различные ошибки, обычной практикой будет создание базового класса для исключений, определённых в этом модуле, и подклассов для различных ошибочных состояний: <syntaxhighlight lang="python">class Error(Exception): """Базовый класс для всех исключений в этом модуле.""" pass class InputError(Error): """Исключение порождается при ошибках при вводе. Атрибуты: expression -- выражение на вводе, в котором обнаружена ошибка message -- описание ошибки """ def __init__(self, expression, message): self.expression = expression self.message = message class TransitionError(Error): """Порождается, когда операция пытается выполнить неразрешённый переход из одного состояния в другое. Attributes: previous -- состояние в начале перехода next -- новое состояние, попытка принять которое была принята message -- описание, по какой причине такой переход невозможен """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message</syntaxhighlight> Большинство исключений имеет имя, заканчивающееся на «<code>Error</code>», подобно стандартным исключениям. Много стандартных модулей определяют собственные исключения, сообщающие об ошибках, которые могут появиться в определяющих их модулях. Больше информации о классах представлено в главе 1.10, [[Учебник Python 3.1#Классы|Классы]] === Определение действий при подчистке === У оператора <code>try</code> есть другой необязательный блок, предназначенный для операций подчистки, которые нужно выполнить независимо от условий: <syntaxhighlight lang="python">>>> try: ... raise KeyboardInterrupt ... finally: ... print('Прощай, мир!') ... Прощай, мир! Traceback (most recent call last): File "<stdin>", line 2, in ? KeyboardInterrupt</syntaxhighlight> ''Блок <code>finally</code>'' исполняется всегда, когда интерпретатор покидает оператор <code>try</code>, независимо — были исключения или нет. Если в блоке <code>try</code> появилось исключение, которое не было обработано в блоке <code>except</code> (или появилось в самих блоках <code>except</code> или <code>else</code>) — оно порождается заново после выполнения блока <code>finally</code>. Также блок <code>finally</code> исполняется «по пути наружу», если какой-либо другой блок оператора <code>try</code> был покинут за счёт одного из операторов: <code>break</code>, <code>continue</code> или <code>return</code>. Более сложный пример: <syntaxhighlight lang="python">>>> def divide(x, y): ... try: ... result = x / y ... except ZeroDivisionError: ... print("деление на ноль!") ... else: ... print("результат: ", result) ... finally: ... print("выполнение блока finally") ... >>> divide(2, 1) результат: 2 выполнение блока finally >>> divide(2, 0) деление на ноль! выполнение блока finally >>> divide("2", "1") выполнение блока finally Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str'</syntaxhighlight> Как видите, блок <code>finally</code> выполняется при любом событии. Ошибка <code>TypeError</code> порождается при делении двух строк и не перехватывается блоком <code>except</code>, и поэтому порождается заново сразу после выполнения блока <code>finally</code>. В приложениях реального мира, блок <code>finally</code> применяется для освобождения внешних ресурсов (таких как файлы или сетевые соединения), независимо от того, было ли их использование удачным. === Предопределённые действия по подчистке === Некоторые объекты определяют стандартные действия при подчистке, применяемые если объект больше не нужен, независимо от того, удачна была операция использования объекта или нет. Посмотрите на следующий пример, в которым мы пытаемся открыть файл и вывести его содержимое на экран. <syntaxhighlight lang="python">for line in open("myfile.txt"): print(line)</syntaxhighlight> Проблема этого кода в том, что он оставляет файл открытым на неопределённое количество времени после выполнения данной части кода. В простых сценариях это не является проблемой, но может стать ей в больших приложениях. Оператор <code>with</code> позволяет использовать объекты (такие как, например, файлы) таким образом, чтобы вы всегда могли быть уверены в том, что ресурсы будут сразу и корректно очищены. <syntaxhighlight lang="python">with open("myfile.txt") as f: for line in f: print(line)</syntaxhighlight> После выполнения оператора, файл ''<code>f</code>'' всегда закрывается, даже если при прочтении строк обнаружилась проблема. В документации к объектам, которые поддерживают предопределённые действия по подчистке, таким как файлы, эта их способность будет явно указана. == Классы == За счёт механизма классов Python в язык с минимальным использованием нового синтаксиса и семантики добавляется возможность создания классов. Это смесь классовых механизмов, заимствованных из C++ и Modula-3. Как и в случае модулей, классы в Python не устанавливают абсолютного барьера между определением и программистом, рассчитывая больше на аккуратность и вежливость последнего — чтобы он не «врывался в определения». Наиболее важные возможности классов, тем не менее, содержат в себе всю возможную мощь: механизм наследования классов поддерживает несколько предков для класса, производный класс может переопределять любые методы своего предка или предков, а любой его метод может вызвать метод предка с таким же именем. Объекты могут содержать произвольное количество закрытых (<tt>private</tt>) данных. В терминологии C++, члены класса (включая данные-члены), обычно, открыты (<tt>public</tt>) (исключая [[Учебник Python 3.1#Приватные переменные|Приватные переменные]], описанные ниже), а все функции-члены — виртуальны. Нет специальных конструкторов и деструкторов. Как в Modula-3, нет краткой ссылки на члены объекта из его методов: функция-метод определяется с явным первым аргументом, описывающим объект, который неявно передаётся при вызове. Как в Smalltalk, классы сами по себе являются объектами, хотя и в более широком смысле: в Python все типы данных — объекты. Таким образом обеспечивается семантика для импортирования и переименования. В отличие от C++ и Modula-3 встроенные типы могут использоваться в качестве предков для расширения возможностей пользователем. Кроме того, как в C++, но не как в Modula-3, большинство встроенных операторов со специальным синтаксисом (арифметические операторы, индексирование и т. д.) могут быть переопределены для экземпляров классов. === Пара слов о терминологии === Обходя стороной поддерживаемую всем миром терминологию, применимую к разговорам о классах, в нашем случае я буду говорить в терминах C++ и Smalltalk. (Предпочёл бы использовать термины языка Modula-3, поскольку Python ближе к ней по объектно-ориентированной семантике, чем к C++, но предполагаю, что немногие читатели слышали о нём.) Объекты обладают индивидуальностью, и с одним объектом может быть связано несколько имён (в нескольких областях видимости). Такая практика в других языках известна как ''совмещение имён'' (<tt>aliasing</tt>). На первый взгляд, совмещение малозаметно в Python, и его можно без последствий игнорировать при работе с основными неизменяемыми типами (числами, строками, кортежами). Тем не менее, совмещение имён влияет на семантику программного кода Python, работающего с изменяемыми объектами: списками, словарями и большинством типов, описывающих сущности вне программы (файлы, окна и т. п.). Обычно такая практика считается полезной, поскольку псевдонимы работают подобно указателям и вероятно даже превосходят их возможности. Например, передача объекта — дешевая операция, поскольку по реализации передаётся только указатель. Если функция изменяет переданный в качестве аргумента объект, это будет заметно и в месте вызова. За счёт этого пропадает необходимость в двух различных механизмах передачи аргументов. === Области видимости и пространства имён в Python === Прежде чем заняться классами необходимо получить представление о правилах областей видимости в Python. Определения классов проделывают над пространствами имён некоторые ловкие трюки. Чтобы полностью понимать происходящее, нужно знать о принципах работы областей видимости и пространств имён. Эти знания не помешают любому профессиональному программисту на Python. Давайте начнём с нескольких определений. ''Пространство имён'' (<tt>namespace</tt>) — это набор связей имён с объектами<ref>''(Прим. перев.) A namespace is a mapping from names to objects {{ref-en}} — ''(букв.)'' пространство имён суть отображение имён на объекты''</ref>. В настоящий момент большинство пространств имён реализованы в виде словарей Python, но не стоит заострять на этом внимание (если только по поводу производительности): возможно, в будущем реализация изменится. Примеры пространств имён: набор встроенных имён (функции вроде <code>abs()</code> и имён встроенных исключений); глобальные имена в модуле; локальные имена при вызове функции. Важная вещь, которую необходимо знать о пространствах имён — это то, что нет абсолютно никакой связи между именами в разных пространствах имён: например, два разных модуля могут без проблем определять функцию «<code>maximize</code>», так как пользователи модулей будут использовать имена модулей в качестве префиксов. Кстати, слово ''атрибут'' (<tt>attribute</tt>) я применяю к любому имени, следующему за точкой. Например, в выражении <code>z.real</code>, <code>real</code> — это атрибут объекта <code>z</code>. Строго говоря, ссылки на имена в модуле являются ссылками на атрибуты: в выражении <code>''имя_модуля''.''имя_функции''</code> под ''имя_модуля'' скрывается объект модуля, а под ''имя_функции'' — его атрибут. В таком случае обнаруживается прямая связь между атрибутами модуля и глобальными именами, определёнными в модуле: они разделяют между собой одно и тоже пространство имён<ref>Исключая одну тонкость. У объектов модулей есть скрытый, только для чтения, атрибут под именем <code>__dict__</code>, возвращающий словарь, использовавшийся для формирования пространства имён модуля; имя <code>__dict__</code> является атрибутом, но не глобальным именем. Очевидно, что всё это нарушает абстракцию реализации пространства имён и его использование следует ограничить вещами вроде посмертных отладчиков</ref>. Запись в атрибуты может быть запрещена (''атрибут только для чтения'', <tt>read-only attribute</tt>) или разрешена (''перезаписываемый атрибут'', <tt>writable attribute</tt>). В последнем случае присваивание атрибуту является возможным. Атрибуты модуля перезаписываемы: вы можете написать «<code>modname.the_answer = 42</code>»<ref>''(Прим. перев.)'' Снова [[w:ru:Ответ на главный вопрос жизни, вселенной и всего такого|ответ на главный вопрос жизни, вселенной и всего такого]]</ref>. Перезаписываемые атрибуты могут также быть удалены оператором <code>del</code>. Например, код «<code>del modname.the_answer</code>» удалит атрибут <code>the_answer</code> из объекта с именем <code>modname</code>. Пространства имён создаются в различные моменты и имеют разное время жизни. Пространство имён, содержащее встроенные имена создаётся при запуске интерпретатора и не удаляется никогда. Глобальное пространство имён модуля создаётся при вычитке определения модуля. Обычно, пространства имён модулей также «живут» до выхода из интерпретатора. Выражения, выполняемые верхне-уровневым порождением интерпретатора, прочитанные из файла сценария или интерактивно, рассматриваются как часть модуля под названием <code>__main__</code>, поэтому у них есть своё собственное глобальное пространство имён. (Встроенные имена по факту также живут в модуле, он называется <code>builtins</code>). Локальное пространство имён функции создаётся при её вызове и удаляется когда функция возвращает значение либо порождает исключение, внутри неё не перехваченное. (На самом деле, лучшим способом объяснить, что происходит на самом деле, было бы «забывание»). Конечно же, рекурсивные порождения имеют свои пространства имён каждое. ''Область видимости'' (<tt>scope</tt>) — это текстовая область в программе на Python, из которой прямым образом доступно пространство имён. «Прямым образом доступно» подразумевает, что явная ссылка на имя вынуждает интерпретатор искать это имя в пространстве имён. Несмотря на то, что области видимости определяются статически, используются они динамически. В любой момент во время выполнения существует как минимум три вложенных области видимости, чьи пространства имён доступны прямым образом: самая внутренняя<ref>''(Прим. перев.)'' ''Innermost scope'', ''outermost scope'' {{ref-en}} — самая внутренняя и самая внешняя области видимости</ref> область видимости (по ней поиск осуществляется в первую очередь) содержит локальные имена; пространства имён всех объемлющих [данный код] функций, поиск по которым начинается с ближайшей объемлющей [код] области видимости; область видимости среднего уровня, по ней следующей проходит поиск и она содержит глобальные имена текущего модуля; и самая внешняя область видимости (заключительный поиск) — это пространство имён, содержащее встроенные имена. Если имя определено глобально, тогда все ссылки и присваивания уходят прямо в область видимости среднего уровня, содержащую глобальные имена модуля. Чтобы сменить привязку у всех переменных, найденных вне самой внутренней области видимости, можно использовать оператор <code>nonlocal</code>; если такая переменная не объявлена как <code>nonlocal</code>, то она используется только для чтения (попытка записать значение в такую переменную создаст новую локальную переменную в самой внутренней области видимости, оставляя идентично названную вовне переменную без изменений). Обычно локальная область видимости ссылается на локальные имена текущей (на уровне текста) функции. Вне функций локальная область видимости ссылается на то же пространство имён, что и глобальная область видимости: пространство имён модуля. Определения классов помещают в локальную область видимости ещё одно пространство имён. Важно осознавать, что области видимости ограничиваются на текстовом уровне: глобальная область видимости функции, определённая в модуле, является пространством имён этого модуля, независимо от того, откуда или по какому псевдониму была эта функция вызвана. С другой стороны, фактический поиск имён осуществляется динамически, во время выполнения. Как бы то ни было, язык развивается в сторону статического разрешения имён (во время компиляции), так что не стоит полагаться на динамическое разрешение имён. (Фактически, локальные переменные уже определены статично.) Особая хитрость в Python состоит в том, что — при условии, что в данной области не включены операторы <code>global</code> или <code>nonlocal</code> — присваивания именам всегда уходят в самую внутреннюю область видимости. Присваивания не копируют данных, а лишь связывают имена с объектами. То же самое верно и для удалений: оператор «<code>del x</code>» удаляет связь <code>x</code> из пространства имён, на которое ссылается локальная область видимости. В действительности, все операции, вводящие новые имена, используют локальную область видимости: в частности, операторы импорта и описаний функций связывают имя модуля или функции в локальной области видимости соответственно. (Для того, чтобы указать определённой переменной, что она должна быть расположена в глобальной области видимости, может использоваться оператор <code>global</code>.) Оператор <code>global</code> можно использовать для того, чтобы объявить определённые переменные как привязанные к глобальной области видимости и указывает, что их переназначения должны происходить в ней; оператор <code>nonlocal</code> помечает переменные как привязанные к окружающей их области видимости и указывает, что их переназначения должны происходить в ней. === Пример по областям видимости и пространствам имён === Приведём пример, показывающий, каким образом можно ссылаться на разные области видимости и пространства имён и как <code>global</code> и <code>nonlocal</code> влияют на привязку переменной. <syntaxhighlight lang="python">def scope_test(): def do_local(): spam = "локальный спам" def do_nonlocal(): nonlocal spam spam = "нелокальный спам" def do_global(): global spam spam = "глобальный спам" spam = "тестовый спам" do_local() print("После локального присваивания:", spam) do_nonlocal() print("После нелокального присваивания:", spam) do_global() print("После глобального присваивания:", spam) scope_test() print("В глобальной области видимости:", spam)</syntaxhighlight> Вывод кода из примера таков: <syntaxhighlight lang="text">После локального присваивания: тестовый спам После нелокального присваивания: нелокальный спам После глобального присваивания: нелокальный спам В глобальной области видимости: глобальный спам</syntaxhighlight> Заметьте, что локальное присваивание (работающее по умолчанию) не заменяет глобальную привязку на связывание из <code>scope_test</code>. Нелокальное присваивание заменило глобальную привязку на связывание из <code>scope_test</code>, а глобальное присваивание заменило привязку на связывание на уровне модуля. Можно увидеть, что до глобального присваивания у переменной <code>spam</code> не было предшествующих связываний. === Первый взгляд на классы === В описании классов представлено немного нового синтаксиса, три новых типа объектов<ref>''(Прим. перев.)'' ''Class Objects'', ''Instance Objects'', ''Method Objects'' {{ref-en}} — объекты классов, объекты экземпляров, объекты методов; по тексту перевода, хоть и могут восприниматься непривычно, используются термины «объекты-классы», «объекты-экземпляры» и «объекты-методы» — ввиду того, что словосочетание «объект класса» может обозначать и принадлежность объекта классу</ref> и некоторое количество новой семантики. ==== Синтаксис определения класса ==== Простейшая форма определения класса выглядит так: <syntaxhighlight lang="python">class ИмяКласса: <оператор-1> . . . <оператор-N> </syntaxhighlight> Определения классов, как и определения функций (операторы <code>def</code>), должны быть исполнены для того, чтобы определить действие. (Вы можете, предположим, поместить определение класса в ветку оператора <code>if</code> или внутрь функции.) На практике, внутри определения класса обычно помещаются определения функций, но позволено использовать и другие операторы — и иногда с пользой — как мы увидим позже. Определения функций внутри класса имеют особенную форму списка аргументов, в связи с соглашениями по вызову методов — опять же, это будет рассмотрено ниже. При вводе определения класса создаётся новое пространство имён, которое и используется в качестве локальной области видимости. Таким образом, все присваивания локальным переменным происходят в этом новом пространстве имён. В частности, определения функций связываются здесь с именами новых функций. При успешном окончании парсинга определения класса (по достижении конца определения), создаётся ''объект-класс'' (<tt>class object</tt>). По существу, это обёртка вокруг содержимого пространства имён, созданного во время определения класса; подробнее объекты классов мы изучим в следующем разделе. Оригинальная локальная область видимости (та, которая действовала в последний момент перед вводом определения класса) восстанавливается, а объект-класс тут же связывается в ней с именем класса, указанном в заголовке определения класса (в примере — ''<code>ИмяКласса</code>''). ==== Объекты-классы ==== Объекты-классы поддерживают два вида операций: ссылки на атрибуты и создание экземпляра. ''Ссылки на атрибуты'' (<tt>Attribute references</tt>) используют стандартный синтаксис, использующийся для всех ссылок на атрибуты в Python: <code>''объект''.''имя''</code>. Корректными именами атрибутов являются все имена, которые находились в пространстве имён класса при создании объекта-класса. Таким образом, если определение класса выглядело так: <syntaxhighlight lang="python">class MyClass: """Простой пример класса""" i = 12345 def f(self): return 'привет мир'</syntaxhighlight> то <code>MyClass.i</code> и <code>MyClass.f</code> являются корректными ссылками на атрибуты, возвращающими целое и ''объект-функцию'' (<tt>function object</tt>) соответственно. Атрибутам класса можно присваивать значение, так что вы можете изменить значение <code>MyClass.i</code> через присваивание. <code>__doc__</code> также является корректным атрибутом, возвращающим строку документации, принадлежащей классу: <code>"Простой пример класса"</code>. Создание экземпляра класса использует синтаксис вызова функции. Просто представьте, что объект-класс — это непараметризированная функция, которая возвращает новый экземпляр класса. Например (предполагая класс, приведённый выше): <syntaxhighlight lang="python">x = MyClass()</syntaxhighlight> создаёт новый экземпляр класса и присваивает этот объект локальной переменной <code>x</code>. Операция ''создания экземпляра'' (<tt>instantiation</tt>) создаёт объект данного класса. Большая часть классов предпочитает создавать экземпляры, имеющие определённое начальное состояние. Для этого класс может определять специальный метод под именем <code>__init__()</code>, например так: <syntaxhighlight lang="python">def __init__(self): self.data = []</syntaxhighlight> Когда в классе определён метод <code>__init__()</code>, при создании экземпляра автоматически вызывается <code>__init__()</code> нового, только что созданного объекта. Так, в этом примере, новый инициализированный экземпляр может быть получен за счёт выполнения кода: <syntaxhighlight lang="python">x = MyClass()</syntaxhighlight> Конечно же, для большей гибкости, метод <code>__init__()</code> может иметь параметры. В этом случае аргументы, переданные оператору создания экземпляра класса, передаются методу <code>__init__()</code>. Например, <syntaxhighlight lang="python">>>> class Complex: ... def __init__(self, realpart, imagpart): ... self.r = realpart ... self.i = imagpart ... >>> x = Complex(3.0, -4.5) >>> x.r, x.i (3.0, -4.5)</syntaxhighlight> ==== Объекты-экземпляры ==== Теперь, что же мы можем делать с объектами-экземплярами? Единственные операции, доступные объектам-экземплярам — это ссылки на атрибуты. Есть два типа корректных имён атрибутов — это атрибуты-данные и методы. ''Атрибуты-данные'' (<tt>data attributes</tt>) аналогичны «переменным экземпляров» в Smalltalk и «членам-данным» в C++. Атрибуты-данные не нужно описывать: как и переменные, они начинают существование в момент первого присваивания. Например, если <code>x</code> — экземпляр созданного выше <code>MyClass</code>, следующий отрывок кода выведет значение <code>16</code>, не вызвав ошибок: <syntaxhighlight lang="python">x.counter = 1 while x.counter < 10: x.counter = x.counter * 2 print(x.counter) del x.counter</syntaxhighlight> Другой тип ссылок на атрибуты экземпляра — это ''метод'' (<tt>method</tt>). Метод — это функция, «принадлежащая» объекту. (В Python термин не уникален для экземпляров класса: другие объекты также могут иметь методы. Например, объекты-списки имеют методы <code>append</code>, <code>insert</code>, <code>remove</code>, <code>sort</code> и т. п. Тем не менее, ниже под термином «метод» мы будем понимать только методы объектов-экземпляров классов, пока отдельно не будет указано иное.) Корректные имена методов объектов-экземпляров зависят от их класса. По определению, все атрибуты класса, являющиеся объектами-функциями, описывают соответствующие методы его экземпляров. Так, в нашем примере, <code>x.f</code> является корректной ссылкой на метод, а <code>x.i</code> ей не является, поскольку не является и <code>MyClass.i</code>. Но при этом <code>x.f</code> — это не то же самое, что <code>MyClass.f</code>: это объект-метод, а не объект-функция. ==== Объекты-методы ==== Обычно, метод вызывают сразу после его связывания [с функцией]: <syntaxhighlight lang="python">x.f()</syntaxhighlight> На примере <code>MyClass</code> такой код возвратит строку <code>'привет мир'</code>. Однако, не обязательно вызывать метод так уж сразу: <code>x.f</code> — это объект-метод, он может быть отложен и вызван когда-либо позже. Например: <syntaxhighlight lang="python">xf = x.f while True: print(xf())</syntaxhighlight> будет печатать <code>'привет мир'</code> до конца времён. Что конкретно происходит при вызове метода? Вы, возможно, заметили, что <code>x.f()</code> выше был вызван без аргументов, хотя в описании функции <code>f</code> аргумент был указан. Что же случилось с аргументом? Несомненно, Python порождает исключение когда функция, требующая присутствия аргумента, вызвана без единого — даже, если он на самом деле не используется… Теперь вы, возможно, догадались: отличительная особенность методов состоит в том, что в качестве первого аргумента функции передаётся объект. В нашем примере вызов <code>x.f()</code> полностью эквивалентен вызову <code>MyClass.f(x)</code>. В общем случае, вызов метода со списком из ''n'' аргументов эквивалентен вызову соответствующей функции со списком аргументов, созданным за счёт вставки объекта, вызвавшего метод, перед первым аргументом. Если вы всё ещё не поняли, как работают методы, взгляд на реализацию возможно прояснит происходящее. Когда атрибут экземпляра ссылается на что-либо, не являющееся атрибутом-данными, производится поиск по классу. Если имя указывает корректный атрибут класса, являющийся объектом-функцией, создаётся метод: через упаковку (указателя на) объекта-экземпляра и найденного объекта-функции в абстрактный объект, получается объект-метод. Когда объект-метод вызывается со списком аргументов, он снова распаковывается и новый список аргументов конструируется из объекта-экземпляра и оригинального списка аргументов, и затем уже с новым списком аргументов вызывается объект-функция. === Различные замечания === Атрибуты-данные переопределяют атрибуты-методы с тем же именем; для того, что обезопасить себя от случайных конфликтов имён, которые могут привести к трудно-обнаруживаемым ошибкам в больших программах, разумно использовать какое-нибудь соглашение, которое могло бы уменьшить шансы возникновения конфликтов. Возможные соглашения включают в себя: написание имён методов строчными буквами, предварение имени атрибутов-данных некоторой короткой уникальной строкой (предположим, лишь символом подчёркивания («<code>_</code>»)), или использование глаголов для именования методов и существительных для именования данных. Методы могут ссылаться на атрибуты-данные также как и обычные пользователи («клиенты») объекта. Другими словами, классы не подходят для разработки чистых абстрактных типов данных. Фактически же в Python нет ничего, вынуждающего вас скрывать данные: сокрытие основано на соглашении между программистами. (С другой стороны, реализация Python, написанная на C, может полностью скрывать детали разработки и, если нужно, контролировать доступ к объекту, это можно делать в расширениях для Python, написанных на C.) Клиенты должны использовать атрибуты-данные с осторожностью, так как иначе они могут нарушить инварианты, подразумеваемые методами класса при использовании атрибутов-данных. Заметьте, что обычно клиенты могут добавлять собственные атрибуты-данные к объектам-экземплярам, не нарушая работы методов, если не происходит конфликтов имён. Опять же, соглашение об именовании может избавить вас от головной боли и в этих случаях. ''(Прим. перев.)'' Автором здесь не упомянут механизм свойств (<tt>property</tt>). Свойство синтаксически является атрибутом-данным, но за кулисами с ним могут быть связаны отдельные методы для чтения, записи и удаления. Документация к функции-декоратору <code>property</code> хорошо проясняет суть дела: <syntaxhighlight lang="python">>>> print(property.__doc__) property(fget=None, fset=None, fdel=None, doc=None) -> property attribute fget - функция для чтения, fset - для записи, fdel - для удаления атрибута. Типичный пример использования для управляемого атрибута x: class C(object): def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "Я - свойство 'x'.") Декораторы упрощают определение новых свойств и изменение существующих: class C(object): @property def x(self): return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x </syntaxhighlight> ''(Конец прим.)'' У методов нет краткой записи для ссылок изнутри на атрибуты-данные (и другие методы!). Я нахожу, что это и вправду повышает читабельность методов: нет шанса спутать локальные переменные и переменные экземпляров при просмотре тела метода. Обычно, первый аргумент метода называется <code>self</code>. Это не более чем соглашение: имя <code>self</code> не имеет абсолютно никакого специального смысла для языка Python. (Однако, обратите внимание, что если вы не следуете соглашениям, ваш код может стать менее читабелен для других программистов; и также, потенциально, программа навигации по классам может опираться на такие соглашения.) Любой объект-функция, являющийся атрибутом класса, определяет метод для экземпляров этого класса. Не так важно, чтобы текст определения функции был заключен в определение класса: присваивание объекта-функции локальной переменной класса также работает неплохо. Например: <syntaxhighlight lang="python"># Функция, определённая вне класса def f1(self, x, y): return min(x, x+y) class C: f = f1 def g(self): return 'привет мир' h = g</syntaxhighlight> Теперь <code>f</code>, <code>g</code> и <code>h</code> — все являются атрибутами класса <code>C</code>, ссылающимися на объекты-функции, и следовательно, все они являются методами экземпляров <code>C</code> — <code>h</code> становится полностью эквивалентен <code>g</code>. Заметьте, что такая практика обычно лишь запутывает читателя программы. Методы могут вызывать другие методы за счёт использования атрибутов-методов аргумента <code>self</code>: <syntaxhighlight lang="python">class Bag: def __init__(self): self.data = [] def add(self, x): self.data.append(x) def addtwice(self, x): self.add(x) self.add(x)</syntaxhighlight> Методы могут ссылаться на глобальные имена таким же образом, как и обычные функции. Глобальная область видимости, связанная с методом — это модуль, содержащий определение класса. (Сам класс никогда не используется в качестве глобальной области видимости!) В то время, как одни редко находят причины для использования глобальных данных в методах, существует множество разумных причин использовать глобальную область видимости: для примера, функции и модули, импортированные в глобальную область видимости, могут использоваться в методах так же, как в функциях и классах, в ней определённых. Обычно класс, содержащий метод, сам определён в этой глобальной области видимости, и в следующем разделе мы найдём пару хороших причин, почему методу может быть необходимо ссылаться на собственный класс! === Наследование === Конечно же, не поддерживай «класс» наследование, не стоило бы называть его «классом». Синтаксис производного класса выглядит так: <syntaxhighlight lang="python">class ИмяПроизводногоКласса(ИмяБазовогоКласса): <оператор-1> . . . <оператор-N></syntaxhighlight> Имя ''<code>ИмяБазовогоКласса</code>'' должно быть определено в области видимости, содержащей определение производного класса. Вместо имени базового класса также позволяется использовать другие выражения. Это может быть полезно, например, когда базовый класс определён в другом модуле: <syntaxhighlight lang="python">class ИмяПроизводногоКласса(имямодуля.ИмяБазовогоКласса):</syntaxhighlight> Использование определения производного класса проходит таким же образом, как и базового. Базовый класс полностью сохраняется по завершению конструирования объекта-класса. Такой метод используется для разрешения ссылок на атрибуты<ref>''(Прим. перев.)'' ''Resolving attribute references'' {ref-en} — разрешение (поиск значений) ссылок на атрибуты</ref>: если запрошенный атрибут не был найден в самом классе, поиск продолжается в базовом классе. Правило применяется рекурсивно, если базовый класс сам является производным от некоторого другого класса. В создании экземпляров производных классов нет ничего особенного: <code>ИмяПроизводногоКласса()</code> создаёт новый экземпляр класса. Ссылки на методы разрешаются следующим образом: производится поиск соответствующего атрибута класса (спускаясь вниз по цепочке базовых классов, если необходимо) и ссылка на метод считается корректной, если она порождает объект-функцию. Производные классы могут перегружать методы своих базовых классов. Поскольку у методов нет особых привилегий при вызове других методов того же объекта, метод базового класса, вызывающий другой метод, определённый в этом же классе, может вызвать перегруженный метод производного класса. (Для программистов на C++: все методы в Python фактически виртуальны.) При перегрузке метода в производном классе возможна не только замена действия метода базового класса с тем же именем, но и его расширение. Существует простой способ вызвать метод базового класса прямым образом: просто вызовите «<code>ИмяБазовогоКласса.имяметода(self, аргументы)</code>». Такой способ будет неожиданно полезным и для клиентов. (Обратите внимание, что он работает только если базовый класс определён и импортирован прямо в глобальную область видимости.) В языке Python есть функции, которые работают с наследованием: * Используйте <code>isinstance()</code> чтобы проверить тип объекта: <code>isinstance(obj, int)</code> возвратит <code>True</code> только если <code>obj.__class__</code> является <code>int</code> или некоторым классом, наследованным от <code>int</code>. * Используйте <code>issubclass()</code> чтобы проверить наследственность класса: <code>issubclass(bool, int)</code> возвратит <code>True</code>, поскольку класс <code>bool</code> является наследником (<tt>subclass</tt>) <code>int</code>. Однако, <code>issubclass(float, int)</code> возвратит <code>False</code>, поскольку класс <code>float</code> не является наследником <code>int</code>. ==== Множественное наследование ==== Python также поддерживает форму ''множественного наследования'' (<tt>multiple inheritance</tt>). Определение класса с несколькими базовыми классами будет выглядеть так: <syntaxhighlight lang="python">class ИмяПроизводногоКласса(Базовый1, Базовый2, Базовый3): <оператор-1> . . . <оператор-N></syntaxhighlight> В простейших случаях и для большинства задач, вы можете представлять себе поиск атрибутов, наследованных от родительского класса в виде «сперва вглубь», затем «слева-направо». Таким образом, если атрибут не найден в ''<code>ИмяПроизводногоКласса</code>'', его поиск выполняется в ''<code>Базовом1</code>'', затем (рекурсивно) в базовых классах ''<code>Базового1</code>'' и только если он там не найден, поиск перейдёт в ''<code>Базовый2</code>'' и так далее. На самом деле всё немного сложнее. Порядок разрешения методов<ref>''(Прим. перев.)'' другими словами — поиска корректной привязки для метода</ref> (<tt>method resolution order</tt>) меняется динамически, чтобы обеспечить возможность сотрудничающих вызовов <code>super()</code>. Этот способ известен в некоторых других языках с поддержкой множественного наследования как «вызов-следующего-метода» («<tt>call-next-method</tt>») и имеет больше возможностей, чем вызов родительского метода в языках с единичным наследованием. Динамическое упорядочивание (<tt>dynamic ordering</tt>) имеет важность, поскольку все вариации множественного наследования проявляют в себе эффект ромбовых отношений (когда как минимум один родительский класс может быть доступен различными путями из низшего в иерархии класса). Например, все классы наследуются от <code>object</code>, так что множественное наследование в любом виде предоставляет более одного пути для того, чтобы достичь <code>object</code>. Чтобы защитить базовые классы от двойных и более запросов, динамический алгоритм «выпрямляет» (<tt>linearizes</tt>) порядок поиска таким образом, что тот сохраняет указанный слева-направо порядок для каждого класса, который вызывает каждый родительский класс только единожды и является монотонным (значит, класс можно сделать наследником, не взаимодействуя с порядком предшествования его родителей). Обобщённые вместе, эти свойства позволяют разрабатывать надёжные и расширяемые классы, используя множественное наследование. С подробностями можно ознакомиться по этой ссылке: http://www.python.org/download/releases/2.3/mro/ ([[Python — Порядок разрешения методов|перевод]]). === Приватные переменные === В Python имеется ограниченная поддержка идентификаторов, приватных для класса. Любой идентификатор в форме <code>__spam</code> (как минимум два предшествующих символа подчёркивания, как максимум один завершающий) заменяется дословно на <code>_classname__spam</code>, где <code>classname</code> — текущее имя класса, лишённое предшествующих символов подчёркивания. Это ''искажение'' (<tt>mangling</tt>) производится без оглядки на синтаксическую позицию идентификатора, поэтому может использоваться для определения переменных, приватных для класса экземпляров, переменных класса, методов, переменных в глобальной области видимости (<tt>globals</tt>), и даже переменных, использующихся в экземплярах, приватных для этого класса на основе экземпляров ''других'' классов. Имя может быть обрезано, если его длина превышает 255 символов. Вне классов, или когда имя состоит из одних символов подчёркивания, искажения не происходит. Предназначение искажения имён состоит в том, чтобы дать классам лёгкую возможность определить «приватные» переменные экземпляров и методы, не беспокоясь о переменных экземпляров, определённых в производных классах, и о забивании кодом вне класса переменных экземпляров. Обратите внимание, что правила искажения имён разработаны, в основном, чтобы исключить неприятные случайности — решительная душа всё ещё может получить доступ или изменить переменные, предполагавшиеся приватными. В некотором особом окружении, таком как отладчик, это может оказаться полезным — и это единственная причина, по которой лазейка не закрыта. (Внимание: наследование класса с таким же именем как и у базового делает возможным использование приватных переменных базового класса.) Заметьте, что код, переданный в <code>exec()</code> или <code>eval()</code>, не предполагает в качестве текущего имени класса имя класса, порождающего вызов — так же, как и в случае эффекта с оператором <code>global</code> — эффекта, который также ограничен для всего побайтно-компилирующегося кода. И, такое же ограничение применимо для функций <code>getattr()</code>, <code>setattr()</code> и <code>delattr()</code>, и также для прямой ссылки на <code>__dict__</code>. === Всякая всячина === Иногда бывает полезен тип данных, похожий на <code>record</code> из языка Pascal или <code>struct</code> из языка C, например, для хранения нескольких поименованных элементов данных. Для этой цели подойдет даже пустое определение класса<ref>''(Прим. перев.)'':<syntaxhighlight lang="python">class Рабочий: pass джон = Рабочий() # Создать пустую запись о рабочем # Заполнить поля записи джон.имя = 'Джон До' джон.отдел = 'компьютерная лаборатория' джон.зарплата = 1000</syntaxhighlight></ref>: <syntaxhighlight lang="python">class Employee: pass john = Employee() # Создать пустую запись о рабочем # Заполнить поля записи john.name = 'John Doe' john.dept = 'computer lab' john.salary = 1000</syntaxhighlight> Фрагменту кода на Python, требующему на входе некоторого абстрактного типа данных, можно дать экземпляр, эмулирующий методы этого типа данных. Например, если имеется функция, умеющая форматировать данные из файлового объекта, то можно определить класс с методами <code>read()</code> и <code>readline()</code> (работающие с данными, скажем, из строкового буфера) и передать ей экземпляр этого класса в качестве аргумента. Объекты-методы экземпляров также имеют атрибуты: <code>m.__self__</code> — исходный объект-экземпляр с методом <code>m()</code>, а <code>m.__func__</code> — объект-функция, соответствующий методу. === Исключения — тоже классы === Исключения, определённые пользователем, могут быть также отождествлены с классами. При использовании этого механизма становится возможным создавать расширяемые иерархии исключений. Оператор <code>raise</code> имеет следующие (синтаксически) правильные формы: <syntaxhighlight lang="python">raise Класс raise Экземпляр</syntaxhighlight> В первой форме, ''<code>Класс</code>'' должен быть экземпляром типа или класса, производного от него. Первая форма является краткой записью следующего кода: <syntaxhighlight lang="python">raise Class()</syntaxhighlight> Класс в блоке <code>except</code> является сопоставимым с исключением, если является этим же классом или самим по себе базовым классом (никаких других способов обхода — описанный в блоке <code>except</code> производный класс не сопоставим с базовым). Например, следующий код выведет B, C, D в этом порядке: <syntaxhighlight lang="python">class B(Exception): pass class C(B): pass class D(C): pass for c in [B, C, D]: try: raise c() except D: print("D") except C: print("C") except B: print("B")</syntaxhighlight> Обратите внимание, что если бы блоки <code>except</code> шли в обратном порядке (начиная с «<code>except B</code>»), код вывел бы B, B, B — сработал бы первый совпадающий блок <code>except</code>. При выводе сообщения об ошибке о необработанном исключении, выводится класс исключения, затем двоеточие и пробел, и наконец экземпляр, приведённый к строке за счёт встроенной функции <code>str()</code>. === Итераторы === К этому моменту вы, возможно, заметили, что используя оператор <code>for</code> можно организовать цикл по большинству объектов-контейнеров: <syntaxhighlight lang="python">for element in [1, 2, 3]: print(element) for element in (1, 2, 3): print(element) for key in {'один':1, 'два':2}: print(key) for char in "123": print(char) for line in open("myfile.txt"): print(line)</syntaxhighlight> Такой стиль доступа к элементам прост, лаконичен и удобен. Использованием ''итераторов'' (<tt>iterators</tt>) пропитан язык Python, и это его выделяет среди других. Негласно, оператор <code>for</code> вызывает метод <code>iter()</code> объекта-контейнера. Функция возвращает объект итератора, который определяет метод <code>__next__()</code>, который по очереди получает доступ к элементам в контейнере, по одному за раз. Если больше не остаётся элементов, метод <code>__next__()</code> порождает исключение <code>StopIteration</code>, которое сообщает оператору <code>for</code> о необходимости завершения прохода. Вы можете вызывать метод <code>__next__()</code> посредством встроенной функции <code>next()</code>; следующий пример показывает, как это работает: <syntaxhighlight lang="python">>>> s = 'абв' >>> it = iter(s) >>> it <iterator object at 0x00A1DB50> >>> next(it) 'а' >>> next(it) 'б' >>> next(it) 'в' >>> next(it) Traceback (most recent call last): File "<stdin>", line 1, in ? next(it) StopIteration</syntaxhighlight> Ознакомившись с механизмами, скрытыми за протоколом итераторов, легко добавить возможность итерирования к вашим классам. Определите метод <code>__iter__()</code>, который возвращает объект с методом <code>next()</code>. Если класс определяет и метод <code>next()</code>, тогда <code>__iter__()</code> может просто возвращать <code>self</code>. <syntaxhighlight lang="python">class Reverse: "Итератор по последовательности в обратном направлении" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def __next__(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index] >>> for char in Reverse('спам'): ... print(char) ... м а п с</syntaxhighlight> === Генераторы === ''Генераторы'' (<tt>generators</tt>) — простой и мощный инструмент для создания итераторов. Они записываются как обычная функция, но где бы им ни было необходимо вернуть данные, используется оператор <code>yield</code>. Каждый раз, когда над ним вызывается <code>__next__()</code>, генератор возвращается к месту, где он был оставлен (он запоминает все значения данных, а также какой оператор был выполнен последним). Пример показывает, что создание генераторов может быть тривиально простым: <syntaxhighlight lang="python">def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] >>> for char in reverse('гольф'): ... print(char) ... ф ь л о г</syntaxhighlight> Всё, что можно сделать с использованием генераторов, может быть сделано с использованием основанных на итераторах классов, как описано в предыдущем разделе. Благодаря автоматическому созданию методов <code>__iter__()</code> и <code>next()</code> генераторы так компактны. Другая важная особенность состоит в том, что между вызовами сохраняются локальные переменные и ''состояние выполнения'' (<tt>execution state</tt>). Это позволяет конструкциям функций быть проще, а получению переменных экземпляров быть намного легче, нежели с использованием <code>self.index</code> и <code>self.data</code>. В дополнение к автоматическому созданию методов и сохранению состояния, когда генераторы заканчивают своё действие, они автоматически порождают исключение <code>StopIteration</code>. В комбинации, эти особенности позволяют легко создавать итераторы не прилагая усилий больших, чем нужно для написания обычной функции. === Выражения-генераторы === Некоторые простые генераторы могут быть сжато закодированы в выражении с использованием синтаксиса, схожего со ''списковыми сборками'', но с круглыми скобками вместо квадратных. Выражения-генераторы разработаны в основном для случаев, когда генератор тут же используется в качестве аргумента функции. Выражения с генераторами более компактные, но менее гибкие чем полные определения генераторов и обычно используют память экономнее, чем эквивалентные ''списковые сборки''. Примеры<ref>''(Прим. перев.)'':<br /> <br /> <code>>>> ''сумма''(i*i '''для''' i '''в''' ''диапазон''(10)) # сумма квадратов<br/> 285<br/> <br/> >>> вектор_а = [10, 20, 30]<br/> >>> вектор_б = [7, 5, 3]<br/> >>> ''сумма''(x*y '''для''' x,y '''в''' ''зип''(вектор_а, вектор_б)) # скалярное произведение<br/> 260<br/> <br/> >>> '''из''' матем '''импорт''' пи, ''синус''<br/> >>> таблица_синусов = {x: ''синус''(x*пи/180)) '''для''' x '''в''' ''диапазон''(0, 91)}<br/> <br/> >>> уникальные_слова = ''набор''(слово&nbsp;&nbsp;'''для''' строка '''в''' страница&nbsp;&nbsp;'''для''' слово '''в''' строка.''разбить''())<br/> <br/> >>> выпускники = ''макс''((студент.ср_балл, студент.имя) '''для''' студент '''в''' окончившие)<br/> <br/> >>> данные = 'гольф'<br/> >>> ''список''(данные[i] '''для''' i '''в''' ''диапазон''(''длина''(данные)-1, -1, -1))<br/> ['ф', 'ь', 'л', 'о', 'г']</code></ref>: <syntaxhighlight lang="python">>>> sum(i*i for i in range(10)) # сумма квадратов 285 >>> xvec = [10, 20, 30] >>> yvec = [7, 5, 3] >>> sum(x*y for x,y in zip(xvec, yvec)) # скалярное произведение 260 >>> from math import sin, radians >>> sine_table = {x: sin(radians(x)) for x in range(0, 91)} >>> unique_words = set(word for line in page for word in line.split()) >>> valedictorian = max((student.gpa, student.name) for student in graduates) >>> data = 'golf' >>> list(data[i] for i in range(len(data)-1, -1, -1)) ['f', 'l', 'o', 'g']</syntaxhighlight> == Краткий обзор стандартной библиотеки == === Взаимодействие с операционной системой === Модуль <tt>os</tt> предоставляет десятки функций для взаимодействия с операционной системой. <syntaxhighlight lang="python">>>> import os >>> os.getcwd() # возвращает путь к текущему каталогу 'C:\\Python31' >>> os.system('dir *.txt') # выполнить указанную команду ОС ...список текстовых файлов, выведенных командой... 0 >>> os.chdir('/server/accesslogs') # сменить текущий каталог </syntaxhighlight> Лучше всего применять <code>import os</code> вместо <code>from os import *</code>. Это предохранит встроенную функцию <code>open()</code> от замещения функцией <code>os.open()</code>, имеющей несколько иное назначение. В интерактивном режиме встроенные функции <code>dir()</code> и <code>help()</code> помогут разобраться с большими модулями вроде <tt>os</tt>: <syntaxhighlight lang="python">>>> import os >>> dir(os) ...список всех атрибутов модуля... >>> help(os) ...страница руководства по модулю на основе строк документации... </syntaxhighlight> Для управления файлами и каталогами удобный высокоуровневый интерфейс предоставляет модуль <tt>shutil</tt>: <syntaxhighlight lang="python">>>> import shutil >>> shutil.copyfile('data.db', 'archive.db') # копировать файл >>> shutil.move('/build/executables', 'installdir') # переместить каталог </syntaxhighlight> === Wildcard-шаблоны для имён файлов === Модуль <tt>glob</tt> предоставляет функцию для получения списка файлов на основе заданного шаблона: <syntaxhighlight lang="python">>>> import glob >>> glob.glob('*.py') ['primes.py', 'random.py', 'quote.py'] </syntaxhighlight> === Аргументы командной строки === Сценарии общего назначения часто нуждаются в аргументах командной строки. Эти аргументы хранятся в атрибуте <tt>argv</tt> модуля <tt>sys</tt> в виде списка. Например, при запуске <code>python demo.py one two three</code> в командной строке шелла для сценария <tt>demo.py</tt>: <syntaxhighlight lang="python">import sys print(sys.argv) </syntaxhighlight> будет выведено <code>['demo.py', 'one', 'two', 'three']</code>. Модуль <tt>getopt</tt> обрабатывает <code>sys.argv</code>, используя соглашения функции <code>getopt()</code> системы Unix. Более мощную и гибкую обработку аргументов командной строки осуществляет модуль <tt>optparse</tt>. === Стандартный вывод. Завершение сценария === Модуль <tt>sys</tt> имеет атрибуты <code>stdin</code>, <code>stdout</code> и <code>stderr</code> (для стандартного ввода, вывода и вывода ошибок соответственно). Последний может быть полезен для вывода предупреждений и сообщений об ошибках когда стандартный вывод перенаправлен<ref>''(Прим. перев.)'' разумеется, если стандартный вывод ошибок перенаправлен не был</ref>: <syntaxhighlight lang="python">>>> sys.stderr.write('Внимание! Файл журнала не найден.\n') Внимание! Файл журнала не найден. 34 </syntaxhighlight> Для завершения сценария можно использовать <code>sys.exit()</code>. === Сравнение строк по шаблонам === Модуль <tt>re</tt> предоставляет инструментарий для работы с регулярными выражениями для нетривиальной обработки текста. С помощью регулярных выражений можно создавать выразительные и оптимизированные решения для поиска и обработки строк. <syntaxhighlight lang="python">>>> import re >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') ['foot', 'fell', 'fastest'] >>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat') 'cat in the hat' </syntaxhighlight> Когда требуются более простые возможности, методы строковых объектов предпочтительнее, так как их легче читать и отлаживать: <syntaxhighlight lang="python">>>> 'чай для двоих'.replace('для', 'на') 'чай на двоих' </syntaxhighlight> === Математические функции === Модуль <tt>math</tt> предоставляет доступ к библиотеке языка C для функций над числами с плавающей запятой: <syntaxhighlight lang="python">>>> import math >>> math.cos(math.pi / 4) 0.70710678118654757 >>> math.log(1024, 2) 10.0 </syntaxhighlight> С помощью модуля <tt>random</tt> можно делать случайный выбор: <syntaxhighlight lang="python">>>> import random >>> random.choice(['яблоко', 'груша', 'банан']) 'яблоко' >>> random.sample(range(100), 10) # выборка без повторений [30, 83, 16, 4, 8, 81, 41, 50, 18, 33] >>> random.random() # случайное число с плавающей запятой 0.17970987693706186 >>> random.randrange(6) # случайное целое из диапазона range(6) 4 >>> random.sample([1, 2, 3, 4, 5], 3) # случайные три элемента из списка [4, 1, 5] </syntaxhighlight> Проект SciPy <http://scipy.org> имеет много других модулей для численных расчётов. === Протоколы интернет === В стандартной библиотеке имеется целый набор модулей для различных сервисов и протоколов интернет. Наиболее употребимыми можно считать <code>urllib.request</code> для получения данных по заданному адресу (URL) и <code>smtplib</code> для отправки сообщений электронной почты: <syntaxhighlight lang="python">>>> from urllib.request import urlopen >>> for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'): ... if 'EST' in line or 'EDT' in line: # временные зоны ... print(line) <BR>Nov. 25, 09:43:32 PM EST >>> import smtplib >>> server = smtplib.SMTP('localhost') >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org', ... """To: jcaesar@example.org ... From: soothsayer@example.org ... ... Beware the Ides of March. ... """) >>> server.quit() </syntaxhighlight> Заметьте, что второй пример требует почтового сервера на той же машине. === Дата и время === Модуль <code>datetime</code> предлагает классы для работы с датами и временем как в простых, так и сложных случаях. Кроме поддержки календарной арифметики, реализация обращает особенное внимание на эффективность вычисления составных частей для вывода и дальнейших манипуляций. Модуль также предлагает объекты с поддержкой временных зон. <syntaxhighlight lang="python"># даты можно легко составлять и выводить в требуемом формате >>> from datetime import date >>> now = date.today() >>> now datetime.date(2009, 2, 3) >>> now.strftime("%d.%m.%Y") '03.02.2009' # даты поддерживают календарную арифметику >>> birthday = date(1964, 7, 31) >>> age = now - birthday >>> age.days 16258 </syntaxhighlight> === Сжатие данных и архивы === Наиболее распространённые форматы сжатия и архивации напрямую поддерживаются модулями стандартной библиотеки: <tt>zlib</tt>, <tt>gzip</tt>, <tt>bz2</tt>, <tt>zipfile</tt> и <tt>tarfile</tt>. <syntaxhighlight lang="python">>>> import zlib >>> s = "Закрой замок на замок, чтобы замок не замок" >>> len(bytes(s, "utf-8")) 78 >>> t = zlib.compress(s) >>> len(t) 54 >>> print(str(zlib.decompress(t), "utf-8")) Закрой замок на замок, чтобы замок не замок >>> zlib.crc32(s) 2392363341 </syntaxhighlight> === Измерение производительности === Некоторым пользователям Python интересно знать относительную производительность различных подходов к решению одной и той же проблемы. Python предлагает инструмент для немедленного ответа на эти вопросы. Например, очень заманчиво использовать присваивание кортежей вместо традиционного подхода к замене значений переменных местами. Модуль <code>timeit</code> быстро продемонстрирует незначительное превосходство кортежей: <syntaxhighlight lang="python">>>> from timeit import Timer >>> Timer('a, b = b, a', 'a=1; b=2').timeit() 0.15707302093505859 >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit() 0.19421601295471191 </syntaxhighlight> В отличие от высокого разрешения модуля <code>timeit</code>, модули <code>profile</code> и <code>pstats</code> предлагают возможность обнаружить критические по времени участки в больших фрагментах кода. === Контроль качества === Один из подходов к разработке высококачественного программного обеспечения заключается в написании тестов для каждой функции при её разработке и регулярном запуске этих тестов во время всего процесса разработки. Модуль <code>doctest</code> имеет средства для просмотра модуля и проверки результатов тестов, заложенных в строках документации. Написание теста для функции заключается в копировании и вставке типичного вызова функции и ее результатов в строку документации. Это улучшает документацию, предоставляя пользователю реальный пример, а модуль <code>doctest</code> проверяет, что код соответствует документации. <syntaxhighlight lang="python">def average(values): """Вычисляет среднее арифметическое списка чисел. >>> print(average([20, 30, 70])) 40.0 """ return sum(values) / len(values) import doctest doctest.testmod() # автоматически проверяет тесты в документации </syntaxhighlight> Модуль <code>unittest</code> не менее прост в использовании чем <code>doctest</code>, но позволяет создавать более полный набор тестов, располагающийся в отдельном файле: <syntaxhighlight lang="python">import unittest class TestStatisticalFunctions(unittest.TestCase): def test_average(self): self.assertEqual(average([20, 30, 70]), 40.0) self.assertEqual(round(average([1, 5, 7]), 1), 4.3) self.assertRaises(ZeroDivisionError, average, []) self.assertRaises(TypeError, average, 20, 30, 70) unittest.main() # Вызов из командной строки выполняет проверку всех тестов этого модуля </syntaxhighlight> === «Батарейки в комплекте» === Python руководствуется философией «батарейки в комплекте». Это можно проследить по сложным и устойчивым к ошибкам возможностям его пакетов побольше. Примеры: * Модули <code>xmlrpc.client</code> и <code>xmlrpc.server</code> делают реализацию удалённых вызовов почти тривиальной задачей. Несмотря на названия, знания об обработке XML не требуются. * Пакет <code>email</code> — это библиотека для работы с сообщениями электронной почты, включая MIME и другие основанные на {{RFC|2822}} документы-сообщения. В отличие от <code>smtplib</code> и <code>poplib</code>, которые занимаются непосредственно отправкой и приёмом сообщений, пакет <code>email</code> является полным набором инструментов для построения и декодирования сообщений сложной структуры (включая вложения) и для реализации интернетного кодирования и протокола заголовков. * Пакеты <code>xml.dom</code> и <code>xml.sax</code> предоставляют ошибко-устойчивую поддержку парсинга XML — этого популярного формата для обмена данными. Аналогично, модуль <code>csv</code> поддерживает чтение и запись в распространённом формате баз данных. Вместе эти модули серьёзно облегчают обмен данными между приложениями на Python и другими приложениями. * Интернационализация поддерживается благодаря ряду модулей, включая <code>gettext</code>, <code>locale</code> и пакет <code>codecs</code>. == Второй краткий обзор стандартной библиотеки == === Форматирование вывода === Модуль <code>reprlib</code> предоставляет версию функции <code>repr()</code>, настроенную на сокращённый вывод больших и многократно вложенных контейнеров: <syntaxhighlight lang="python">>>> import reprlib >>> reprlib.repr(set('supercalifragilisticexpialidocious')) "set(['a', 'c', 'd', 'e', 'f', 'g', ...])" </syntaxhighlight> Модуль <code>pprint</code> предлагает более утончённый контроль над выводом встроенных и определённых пользователем объектов способом, подходящим для интерпретатора. Когда результат не умещается на строке, умный <code>pprint</code> добавляет по необходимости разбивку на строки и отступы, помогающие выделить структуру данных: <syntaxhighlight lang="python">>>> import pprint >>> t = [[[['чёрный', 'бирюзовый'], 'белый', ['зелёный', 'красный']], [['пурпурный', 'жёлтый'], 'голубой']]] >>> pprint.pprint(t, width=30) [[[['чёрный', 'бирюзовый'], 'белый', ['зелёный', 'красный']], [['пурпурный', 'жёлтый'], 'голубой']]] </syntaxhighlight> Модуль <code>textwrap</code> форматирует абзацы текста под определённую ширину: <syntaxhighlight lang="python">>>> import textwrap >>> doc = """Метод wrap() аналогичен fill(), но он возвращает список строк, а не одну большую строку с признаками концов строк.""" >>> print(textwrap.fill(doc, width=40)) Метод wrap() аналогичен fill(), но он возвращает список строк, а не одну большую строку с признаками концов строк. </syntaxhighlight> Модуль <code>locale</code> дает доступ к базе данных форматов различных культурных сред. Например, параметр <code>grouping</code> функции <code>format</code> этого модуля позволяет использовать группировку цифр принятыми в данной культурной среде разделителями: <syntaxhighlight lang="python">>>> import locale >>> locale.setlocale(locale.LC_ALL, 'en_US.UTF8') 'en_US.UTF8' >>> conv = locale.localeconv() # получить отображение соглашений >>> x = 1234567.8 >>> locale.format("%d", x, grouping=True) '1,234,567' >>> locale.format("%s%.*f", (conv['currency_symbol'], conv['frac_digits'], x), grouping=True) '$1,234,567.80' </syntaxhighlight> === Работа с шаблонами === Модуль <code>string</code> включает в себя гибкий класс <code>Template</code>, реализующий шаблоны с простым синтаксисом, доступным для редактирования конечными пользователями. Использование этого класса позволит пользователям настраивать приложения без изменений в них самих. Формат использует имена полей для подстановки, записываемых как знак доллара (<code>$</code>) с последующим идентификатором, состоящим, как и имена в программах на Python, из букв, цифр и подчёркиваний<ref>(''Прим. перев.'') вопреки ожиданиям, имена полей нельзя писать кириллицей.</ref>. Фигурные скобки вокруг идентификатора позволяют использовать алфавитно-цифровые символы сразу после поля подстановки, без дополнительных пробелов. Собственно знак доллара необходимо записывать сдвоенно: <code>$$</code>. <syntaxhighlight lang="python">>>> from string import Template >>> t = Template('${village}folk send $$10 to $cause.') >>> t.substitute(village='Nottingham', cause='the ditch fund') 'Nottinghamfolk send $10 to the ditch fund.' </syntaxhighlight> Метод <code>substitute()</code> возбуждает <code>KeyError</code> в случае, когда значение для поля отсутствует в переданных параметрах. Для приложений вроде массовой персонализированной рассылки, часть данных может отсутствовать. В таком случае лучше использовать метод <code>safe_substitute()</code>: он оставит разметку полей подстановки в случае отсутствия данных.<ref>(''Прим. перев.'') разумеется, ещё лучше позаботиться, чтобы у полей были удачные значения по умолчанию.</ref> <syntaxhighlight lang="python">>>> t = Template('Return the $item to $owner.') >>> d = dict(item='unladen swallow') >>> t.substitute(d) Traceback (most recent call last): . . . KeyError: 'owner' >>> t.safe_substitute(d) 'Return the unladen swallow to $owner.'</syntaxhighlight> Производные от <code>Template</code> классы могут переопределить разделитель. Например, утилита переименования файлов просмотрщика фотографий может использовать знаки процента в разметке полей подстановки: текущая дата, номер изображения по порядку, формат файла: <syntaxhighlight lang="python">>>> import time, os.path >>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg'] >>> class BatchRename(Template): ... delimiter = '%' >>> fmt = input('Введите стиль переименования (%d - дата, %n - номер п/п, %f - формат): ') Введите стиль переименования (%d - дата, %n - номер п/п, %f - формат): Ashley_%n%f >>> t = BatchRename(fmt) >>> date = time.strftime('%d%b%y') >>> for i, filename in enumerate(photofiles): ... base, ext = os.path.splitext(filename) ... newname = t.substitute(d=date, n=i, f=ext) ... print('{0} --> {1}'.format(filename, newname)) img_1074.jpg --> Ashley_0.jpg img_1076.jpg --> Ashley_1.jpg img_1077.jpg --> Ashley_2.jpg</syntaxhighlight> Другое приложение для использования шаблонов — отделение логики от деталей реализации различных выходных форматов. Это даёт возможность строить шаблоны для XML-файлов, текстовых отчётов и веб-отчётов на HTML. === Работа с записями двоичных данных === Модуль <code>struct</code> предлагает функции <code>pack()</code> и <code>unpack()</code> для работы с форматами двоичных записей переменной длины. Следующий пример показывает как можно получить заголовочную информацию из ZIP-файла без использования модуля <code>zipfile</code>. Коды <code>"H"</code> и <code>"I"</code> представляют двух- и четырехбайтовых беззнаковых числа соответственно. Код <code>"<"</code> обозначает, что числа стандартного размера и байты записаны в порядке «сначала младший» (little-endian): <syntaxhighlight lang="python">import struct data = open('myfile.zip', 'rb').read() start = 0 for i in range(3): # показать первые три заголовка start += 14 fields = struct.unpack('<IIIHH', data[start:start+16]) crc32, comp_size, uncomp_size, filenamesize, extra_size = fields start += 16 filename = data[start:start+filenamesize] start += filenamesize extra = data[start:start+extra_size] print(filename, hex(crc32), comp_size, uncomp_size) start += extra_size + comp_size # пропустить до следующего заголовка </syntaxhighlight> === Многопоточность === Потоки (threads) могут использоваться для разделения задач, которые могут выполняться по времени независимо друг от друга. Разделение на потоки может применяться для улучшения времени отклика приложений, ведущих диалог с пользователем пока другие задачи выполняются в фоновом режиме. Похожая ситуация с произведением ввода-вывода одновременно с вычислениями в другом потоке. Следующий пример показывает, как высокоуровневый модуль <code>threading</code> может выполнять фоновые задачи, продолжая выполнение основной программы: <syntaxhighlight lang="python">import threading, zipfile class AsyncZip(threading.Thread): def __init__(self, infile, outfile): threading.Thread.__init__(self) self.infile = infile self.outfile = outfile def run(self): f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) f.write(self.infile) f.close() print('Завершён фоновый zip для:', self.infile) background = AsyncZip('mydata.txt', 'myarchive.zip') background.start() print('Главная программа на переднем плане.') background.join() # Ждём завершения фоновой задачи print('Главная программа дождалась завершения фоновой задачи.') </syntaxhighlight> Основной трудностью многопоточных приложений является координирование потоков, разделяющих общие данные или другие ресурсы. В помощь этому модуль <code>threading</code> предлагает целый ряд простых средств: замки́, события, переменные условий, семафоры и другие. Несмотря на достаточную мощь представленных средств, даже небольшие погрешности в дизайне многопоточного приложения могут вызвать трудноповторимые проблемы. Таким образом, рекомендуемым подходом к координированию задач является централизация доступа к некоторому ресурсу в одном потоке и использование модуля <code>queue</code> для направления запросов из других потоков. Приложения, использующие Queue-объекты для межпотоковой связи и координирования, легче проектировать, сопровождать исходный код, они более надёжны. === Запись в журнал === Модуль <code>logging</code> предлагает богатую возможностями и гибкую систему ведения журнала. В простейшем случае сообщения отправляются на стандартный вывод ошибок — <code>sys.stderr</code>: <syntaxhighlight lang="python">import logging logging.debug('Отладочная информация') logging.info('Для информации') logging.warning('Предупреждение: файл %s не найден', 'server.conf') logging.error('Произошла ошибка!') logging.critical('Критическая ошибка - выход')</syntaxhighlight> Результат выполнения этого примера: <syntaxhighlight lang="text">WARNING:root:Предупреждение: файл server.conf не найден ERROR:root:Произошла ошибка! CRITICAL:root:Критическая ошибка - выход </syntaxhighlight> Без дополнительной настройки информационные и отладочные сообщения подавляются, а вывод направляется в <code>sys.stderr</code>. Другие варианты вывода: отправка сообщений по электронной почте, дейтаграммами, сокеты, на HTTP сервер. Другие фильтры могут выбирать различные варианты доставки в зависимости от приоритета: <tt>DEBUG</tt>, <tt>INFO</tt>, <tt>WARNING</tt>, <tt>ERROR</tt> или <tt>CRITICAL</tt>. Система записи в журнал может быть сконфигурирована напрямую из Python. Конфигурация также может быть загружена из конфигурационного файла и не требовать изменений в коде приложения. === Слабые ссылки === Python имеет автоматическое управление памятью: подсчёт ссылок для большинства объектов и сборка мусора для удаления циклов. Память освобождается сразу после того, как была удалена последняя ссылка на объект. Этот подход отлично работает для большинства приложений, но иногда возникает необходимость вести учёт объектов только когда они используются где-нибудь ещё. К сожалению, само слежение за объектами уже создает ссылку и тем самым объекты остаются в памяти. Модуль <code>weakref</code> (от англ. weak reference — слабая ссылка) даёт средство для учёта объектов без создания ссылок на них. Когда объект больше не нужен, он автоматически удаляется из таблицы слабых ссылок и производится обратный вызов <code>weakref</code>-объектов. Типичное применение модуля — кэширование объектов, которые затратно воспроизвести снова. <syntaxhighlight lang="python">>>> import weakref, gc >>> class A: ... def __init__(self, value): ... self.value = value ... def __repr__(self): ... return str(self.value) ... >>> a = A(10) # создаёт ссылку >>> d = weakref.WeakValueDictionary() # словарь, использующий слабые ссылки >>> d['primary'] = a # не создаёт ссылки >>> d['primary'] # достать объект, если он все ещё "жив" 10 >>> del a # удалить одну ссылку >>> gc.collect() # произвести сборку мусора 0 >>> d['primary'] # запись была автоматически удалена Traceback (most recent call last): File "<stdin>", line 1, in <module> d['primary'] File "C:/python31/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' </syntaxhighlight> === Работа со списками === В Python список может заменить многие структуры данных. Однако иногда необходимы альтернативные реализации, которые имеют другое компромиссное решение в отношении производительности. Модуль <code>array</code> (массив) предоставляет объект <code>array</code>, отличающийся от списка лишь возможностью более компактно хранить однородные данные. Следующий пример показывает массив чисел, хранимый в виде двухбайтных беззнаковых чисел (типокод «<code>H</code>»), а не в обычном списке, где каждый элемент типа <code>int</code> обычно занимает 16 байт: <syntaxhighlight lang="python">>>> from array import array >>> a = array('H', [4000, 10, 700, 22222]) >>> sum(a) 26932 >>> a[1:3] array('H', [10, 700])</syntaxhighlight> Модуль <code>collections</code> (коллекции) среди прочего предоставляет объект <code>deque</code> (дек, двухсторонняя очередь). Объекты этого типа имеют более быстрые операции вставки (append) и извлечения (pop) слева, но более медленный поиск внутренних элементов. Эти объекты хорошо подходят для реализации очередей и деревьев поиска в ширину: <syntaxhighlight lang="python">>>> from collections import deque >>> d = deque(["задача1", "задача2", "задача3"]) >>> d.append("task4") >>> print("Обрабатывается", d.popleft()) Обрабатывается задача1 unsearched = deque([starting_node]) def breadth_first_search(unsearched): node = unsearched.popleft() for m in gen_moves(node): if is_goal(m): return m unsearched.append(m) </syntaxhighlight> В дополнение к альтернативным реализациям списков библиотека также предлагает средства вроде модуля <code>bisect</code> с функциями для манипуляции отсортированными списками: <syntaxhighlight lang="python">>>> import bisect >>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')] >>> bisect.insort(scores, (300, 'ruby')) # вставка значения в отсортированный список >>> scores [(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')] </syntaxhighlight> Модуль <code>heapq</code> имеет функции для реализации кучи, основанной на обычных списках. Элемент с наименьшим значением всегда находится в позиции с индексом 0. Это свойство может с успехом быть задействовано в приложениях, где особенно частый доступ необходим к наименьшему элементу, но полную сортировку проводить накладно. <syntaxhighlight lang="python">>>> from heapq import heapify, heappop, heappush >>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] >>> heapify(data) # сделать из списка кучу >>> heappush(data, -5) # добавить новый элемент >>> [heappop(data) for i in range(3)] # извлечь три наименьших значения [-5, 0, 1] </syntaxhighlight> === Десятичная арифметика чисел с плавающей запятой === Модуль <code>decimal</code> предоставляет тип данных <code>Decimal</code> для десятичной арифметики с плавающей запятой. В сравнении со встроенной двоичной арифметикой, новый класс особенно полезен в финансовых приложениях и других случаях, требующих точного десятичного представления, управления точностью, округлением c соблюдением законодательных и нормативных требований, отслеживания количества значащих цифр или для приложений, от которых ожидается совпадение с результатами, проделанными «вручную». Например, вычисление 5%-ного налога на 70 копеечный телефонный счет даёт различные результаты при использовании десятичной и двоичной арифметик. Разница становится значащей при округлении до ближайшей копейки: <syntaxhighlight lang="python">>>> from decimal import * >>> Decimal('0.70') * Decimal('1.05') Decimal("0.7350") >>> .70 * 1.05 0.73499999999999999 </syntaxhighlight> == Что дальше? == Чтение этого учебника, возможно, усилило ваш интерес к применению Python, и вы жаждете использовать этот язык для решения конкретных задач. Где можно пополнить знания о Python? Этот учебник является частью набора документации Python. В этом наборе есть и другие документы. ---- '''Сноски:''' <references /> 14e70awlfgll8o8kpex9uose3cp094g Понятие о помехах и методы борьбы с ними 0 7884 270431 262110 2026-10-27T07:12:46Z Jcb 79968 270431 wikitext text/x-wiki {{Название учебника |Категория = Информатика, Физика |Тип = Одностраничный }} == Помехи: понятие и характеристики == '''Помехой''' называется стороннее возмущение, действующее в системе передачи и препятствующее правильному приёму сигналов. Источники помех могут находиться как вне, так и внутри самой системы передачи. Если помеха регулярна и известна, то борьба с ней не представляет затруднений. Например, фон переменного тока может быть устранён компенсацией; помеха от определенной радиостанции с модуляционным спектром нормальной ширины устраняется соответствующим фильтром. Борьба же со случайными помехами представляет наибольшее затруднение. В общем виде влияние помехи <math>\xi</math> на передаваемый сигнал <math>s</math> может быть выражено оператором : <math>x=f(s,\;\xi).\qquad\qquad(1)</math> В том частном случае, когда этот оператор вырождается в сумму : <math>x=s+\xi\qquad\qquad(2)</math> помеха <math>\xi</math> называется '''аддитивной'''. Аддитивную помеху часто называют '''шумом'''. Если же <math>x</math> может быть представлен в виде : <math>x=\nu s,\qquad\qquad(3)</math> где случайный процесс (см. ниже) <math>\nu(t)</math> неотрицателен, то помеху <math>\nu</math> называют '''мультипликативной'''. Если <math>\nu</math> — медленный (по сравнению с <math>s</math>) процесс, то явление, вызываемое мультипликативной помехой, носит название '''замирание''' ('''фединг'''). В более общем случае оператор <math>f</math> не может быть приведён к основным формам (2) и (3). При одновременном наличии шума и мультипликативной помехи удобно ввести два случайных процесса, выражающих оба вида помехи: : <math>x=\nu s+\xi.\qquad\qquad(4)</math> С физической точки зрения случайные помехи порождаются различного рода флуктуациями. '''Флуктуациями''' в физике называют случайные отклонения тех или иных физических величин от их средних значений. Так, источником шума в электрических цепях постоянного тока могут являться флуктуации тока около среднего значения, обусловленные дискретной природой носителей заряда (ионов и электронов). Это явление носит название '''дробового эффекта'''. Наиболее универсальной причиной шума являются флуктуации, обусловленные тепловым движением. Случайное тепловое движение носителей заряда в любом проводнике вызывает случайную разность потенциалов на его концах. Эта разность потенциалов флуктуирует около среднего значения, равного нулю; её средний квадрат пропорционален абсолютной температуре. Возникающая помеха называется '''тепловым шумом'''. Из сказанного видно, что флуктуации и обусловленные ими помехи заложены глубоко в природе вещей. Флуктуации есть результат дискретного строения вещества и статистической природы ряда физических величин. Многие физические величины представляют результат усреднения по большому числу индивидуальных частиц, поведение и действие которых подчиняется законам случая. Поэтому флуктуации этих физических величин принципиально неустранимы, и можно лишь ставить вопрос о том, какова относительная величина флуктуации и каким образом мы можем на неё повлиять находящимися в нашем распоряжении средствами. Имеется ещё один источник принципиально неустранимого шума, возникающего из-за дискретной природы электромагнитного излучения. Согласно современным воззрениям излучение совершается дискретными порциями — квантами, энергия которых равна <math>h\nu</math>, где <math>h</math> — постоянная Планка, <math>\nu</math> — частота. Квант электромагнитного излучения называется фотоном. В настоящее время в технике имеются две ясные тенденции: к увеличению расстояний и к повышению частоты. Увеличение расстояний означает уменьшение потока энергии, а повышение частоты — укрупнение фотонов. Таким образом, при определённых условиях не только начинает ощущаться дискретная фотонная структура излучения, но обусловленный этой причиной шум может превзойти все остальные помехи. Канал, работающий при таких условиях, получил название '''фотонного канала'''. Выше перечисленные шумы являются аддитивными, но имеется обширный класс мультипликативных помех. Природа этих помех состоит в случайном изменении параметров канала передачи. При передаче сигнал подвергается искажениям вследствие того, что коэффициент передачи канала не является постоянным числом; свойства канала описываются частотными или временны́ми характеристиками, определяющими так называемые линейные искажения. Кроме того, канал может вносить и нелинейные искажения, обусловленные нелинейностью тех или иных звеньев канала. Как линейные, так и нелинейные искажения обусловлены известными характеристиками канала, а потому, по крайней мере в принципе, могут быть устранены путем надлежащей коррекции. Поэтому искажения следует чётко отделить от действия помехи случайного характера, которая заранее не может быть известна. Если же коэффициент передачи канала претерпевает случайные изменения, то влияние этих изменений следует уже рассматривать как действие случайной помехи, которая и является мультипликативной помехой. Примером медленной мультипликативной помехи является изменение силы принимаемого сигнала, обусловленное интерференцией при многолучевом распространении (замирание). Быстрая мультипликативная помеха возникает при использовании шума в качестве переносчика.<ref>{{книга|автор=Варакин, Л. Е.|заглавие=Теория систем сигналов|место={{М.}}|издательство=Советское радио|год=1978|страниц=375}}</ref> Помеха представляется случайной функцией времени. Случайную функцию дискретного времени называют '''случайной последовательностью''', случайную функцию непрерывного времени — '''случайным процессом'''. Случайные функции характеризуются своими распределениями. Применяются также числовые характеристики в виде моментов распределения. Обычно рассматриваются стационарные случайные процессы. Важнейшей характеристикой канала с аддитивной помехой является отношение средних мощностей сигнала <math>E_s</math> и помехи <math>E_n</math> : <math>\frac{E_s}{E_n}.\qquad\qquad(5)</math> Это отношение, кратко называемое '''отношение «сигнал/помеха»''', играет большую роль в теории помехоустойчивости. На практике отношение «сигнал/помеха» выражают в логарифмических безразмерных единицах — децибелах (dB, дБ): : <math>\mathrm{dB}=10\,\mathrm{lg}\frac{E_s}{E_n}.\qquad\qquad(6)</math> Случайные процессы характеризуются определённым набором показателей. Момент первого порядка ('''первый момент''') : <math>M\xi=\int\limits_{-\infty}^{+\infty}xw(x)\,dx\qquad\qquad(7)</math> выражает '''математическое ожидание''', или '''постоянную составляющую процесса'''. Центральный момент второго порядка ('''второй момент''') называется дисперсией и равен: : <math>D\xi=\int\limits_{-\infty}^{+\infty}(x-M\xi)^2w(x)\,dx=M(\xi^2)-(M\xi)^2=\sigma^2.\qquad\qquad(8)</math> Дисперсия выражает '''мощность переменной составляющей''', а средний квадрат <math>M(\xi^2)</math> — '''общую мощность'''. В большинстве случаев <math>M\xi=0</math>, так что дисперсия совпадает со средним квадратом. Смешанный второй момент : <math>M[\xi(t)\xi(t+\tau)]=\int\limits_{-\infty}^{+\infty}\int\limits_{-\infty}^{+\infty}x_1x_2w(x_1,\;x_2)\,dx_1dx_2=R(\tau).\qquad\qquad(9)</math> называется '''функцией автокорреляций процесса''' <math>\xi(t)</math>. Величина <math>R(0)</math> есть мощность процесса. Действительно : <math>R(0)=M(\xi^2)=E.\qquad\qquad(10)</math> Многие случайные процессы, встречающиеся в практике, обладают свойством '''эргодичности'''. Это свойство состоит в том, что средние по множеству (то есть математические ожидания, вычисляемые по распределениям) с вероятностью единица совпадают со средними по времени, найденными по одной реализации процесса. Тогда для эргодических процессов имеем : <math>\begin{cases}a=\lim\limits_{T\to\infty}\dfrac{1}{2T}\int\limits_{-T}^T\xi(t)\,dt, \\ P=\lim\limits_{T\to\infty}\dfrac{1}{2T}\int\limits_{-T}^T\xi^2(t)\,dt, \\ R(\tau)=\lim\limits_{T\to\infty}\dfrac{1}{2T}\int\limits_{-T}^T\xi(t)\xi(t+\tau)\,dt.\end{cases}\qquad\qquad(11)</math> '''Спектральная плотность мощности''' <math>G(\omega)</math> (или просто '''спектр''') связана с функцией автокорреляции парой преобразований Фурье: : <math>\begin{cases}G(\omega)=\dfrac{2}{\pi}\int\limits_0^{+\infty}R(\tau)\cos\omega\tau\,d\tau, \\ R(\tau)=\int\limits_0^{+\infty}G(\omega)\cos\omega\tau\,d\omega.\end{cases}\qquad\qquad(12)</math> Положив во второй формуле <math>\tau=0</math>, получим соотношение, поясняющее смысл функции : : <math>R(0)=\int\limits_0^{+\infty}G(\omega)\,d\omega=E.\qquad\qquad(13)</math> Наряду с <math>G(\omega)</math> часто пользуются функцией <math>A(f)=2\pi G(\omega)</math> — мощность, приходящаяся на полосу 1 Гц. Поэтому удобнее записать (12) в виде : <math>\begin{cases}A(f)=4\int\limits_0^{+\infty}R(\tau)\cos 2\pi f\tau\,d\tau, \\ R(\tau)=\int\limits_0^{+\infty}A(f)\cos2\pi f\tau\,df.\end{cases}\qquad\qquad(14)</math> Задание <math>G(\omega)</math> исчерпывающим образом характеризует любой случайный процесс. == Некоторые виды шумов == === Гауссов шум === Среди всех случайных процессов особое место занимает процесс с нормальным распределением ('''гауссов процесс'''). Дело в том, что большое число действительных случайных процессов является гауссовыми. Это обстоятельство находит себе объяснение в известной теореме Ляпунова, согласно которой распределение суммы независимых случайных величин (при некоторых достаточно широких условиях) сходится к нормальному, вне зависимости от характера распределения слагаемых. '''Гауссов шум''', или '''гауссов случайный процесс''', возникает при суммировании статистически независимых белых шумов (см. ниже). Он преобладает в практических задачах. Случайный процесс <math>x(t)</math> называется '''гауссовым''', если для любого набора фиксированных моментов времени <math>t_n</math> случайные величины <math>x_n</math> подчиняются нормальному распределению. Плотность вероятностей мгновенных значений <math>x(t)</math> гауссова процесса определяется выражением: : <math>w(x)=\frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}},\qquad\qquad(15)</math> где <math>\mu</math> — среднее значение; <math>\sigma^2</math> — стандартное (среднеквадратичное) отклонение. Среднее значение для гауссова распределения равно математическому ожиданию: : <math>\mu=\int\limits_{-\infty}^{+\infty}xw(x)\,dx.\qquad\qquad(16)</math> Стандартное (среднеквадратичное) отклонение: : <math>\sigma^2=\int\limits_{-\infty}^{+\infty}(x-\mu)^2w(x)\,dx.\qquad\qquad(17)</math> [[Файл:Зависимость формы распределения Гаусса от среднеквадратичного отклонения.png|frame|center|Рисунок 1 — Зависимость формы распределения Гаусса от среднеквадратичного отклонения.]] Следовательно, плотность вероятностей гауссова процесса полностью характеризуется спектральной плотностью, по которой можно определить значение дисперсии процесса. На рисунке 1 показана зависимость формы распределения Гаусса от среднеквадратичного отклонения. === Белый шум === Помеху, представляющую собой случайный процесс с равномерным спектром, то есть : <math>A(f)=A_0=\mathrm{const},\qquad\qquad(18)</math> называют '''белым шумом'''. Мощность белого шума в полосе <math>F</math> равна : <math>E_F=\int\limits_0^F A(f)\,df=A_0F.\qquad\qquad(19)</math> По-другому, белый шум (рисунок 2) можно определить как стационарный случайный процесс <math>x(t)</math> с постоянной спектральной плотностью <math>G(\omega)=\sigma^2</math>, равной дисперсии значений <math>D(x)</math> — все спектральные составляющие белого шума имеют одинаковую энергию (отсюда аналогия с белым цветом, который содержит все цвета видимого спектра). Как уже было сказано выше, по своему физическому смыслу спектральная плотность — это мощность процесса, которая приходится на 1 Гц полосы частот. Но тогда идеального белого шума на практике не может существовать, так как для него должно было бы выполняться условие: : <math>R(0)=\int\limits_0^{+\infty}G(\omega)\,d\omega=\frac{\sigma^2}{2}\delta(0)=+\infty,\qquad\qquad(20)</math> где <math>\delta(0)</math> — дельта-функция Дирака. Таким образом, мощность белого шума равна бесконечности, а значения шума не коррелированны для любых <math>\tau\neq 0</math>, так как корреляционная функция представляет собой дельта-импульс. Тем не менее, многие помехи в радиотехнике, в технике связи и в других отраслях рассматривают как белый шум, если выполняется следующее соотношение между шириной спектров полезных сигналов <math>B_s</math> и шумов <math>B_n</math> : <math>\frac{B_s}{B_n}\ll 1\qquad\qquad(21)</math> и спектральная плотность шумов слабо изменяется в интервале спектра сигнала. [[Файл:Выборка белого шума.png|frame|center|Рисунок 2 — Выборка белого шума.]] Примером белого шума может служить тепловой шум. Согласно формуле Найквиста мощность теплового шума, приходящаяся на полосу длиною <math>B</math>, равна: : <math>E_F=4kTB,\qquad\qquad(22)</math> где <math>k</math> — постоянная Больцмана, <math>T</math> — абсолютная температура. Таким образом, <math>A_0=akT</math>. === Периодический случайный шум === '''Периодический случайный шум''' представляет собой результат суммирования синусоид с одинаковыми амплитудами и случайными фазами. Шум содержит все частоты, которые могут быть представлены целым числом периодов на определённом числе выборок. Распределение периодического шума при большом количестве выборок стремится к гауссову шуму. Часто периодический шум рассматривают как выборку гауссова шума, ограниченную по величине следующими значениями: : <math>\begin{cases}A\left(\dfrac{N}{2}-1\right), & N=2k,\;k=1,\;2,\;\ldots; \\ A\left(\dfrac{N-1}{2}\right), & N=2k-1,\;k=1,\;2,\;\ldots, \end{cases}\qquad\qquad(23)</math> где <math>A</math> — заданная амплитуда спектра; <math>N</math> — выборка. [[Файл:Частотная характеристика периодического случайного шума.png|thumb|center|400px|Рисунок 3 — Частотная характеристика периодического случайного шума.]] Таким образом, периодический случайный шум имеет импульсный характер, а следовательно дискретную частотную характеристику (рисунок 3). == Способы проникновения шумов == === Типичные пути проникновения шумов === Из рисунка 4 видно, что проблема шумоподавления возникает при наличии трёх необходимых элементов: во-первых, должен быть источник шумов; во-вторых, должна быть схема-приёмник, чувствительная к шумам; в-третьих, необходимо наличие канала связи для передачи шумов от источника к приемнику. [[Файл:Принципиальная схема системы с шумами.png|thumb|center|500px|Рисунок 4 — Принципиальная схема системы с шумами.]] При анализе проблемы шумов, прежде всего, следует определить, что является источником шумов, что служит их приёмником и каким образом источник и приёмник связаны друг с другом. Отсюда вытекает, что возможны три способа устранения прохождения шумов: # подавление шумов в источнике; # создание приёмника, нечувствительного к шумам; # минимизация передачи шумов через канал связи. В некоторых случаях необходимо применять два или даже все три указанных способа подавления шумов. === Шумы, наводимые на провода === Одним из наиболее очевидных, но часто упускаемых из виду путей проникновения шумов в схему являются провода. Проходя через «зашумлённое» пространство, проводник получает шумовые наводки, а затем передаёт их другой схеме. Это вызывает помехи. Решение состоит в защите проводника от шумов или в обеспечении развязки, благодаря которой шумы отводятся с проводника прежде, чем попадут в чувствительную схему. Основным примером такого вида связи являются шумы, проникающие в схему по проводам сети. В случае, если разработчик не имеет возможности контролировать сеть или если к сети подключают и другую аппаратуру, возникает необходимость в развязке проводов сети по шумам до их подсоединения к схеме. === Связь через общее сопротивление === Связь через общее сопротивление встречается там, где токи от двух различных схем проходят через одно сопротивление. При этом падение напряжения, создаваемое каждой из схем на этом сопротивлении, является для другой схемы помехой. Классический пример такого рода связи показан на рисунке 5, а. Оба возвратных тока (1 и 2) проходят на землю через общее сопротивление. Что касается схемы 1, то потенциал ее общей точки относительно земли модулируется возвратным током 2, протекающим через общее сопротивление шины земли. Поэтому от схемы 2 к схеме 1 через общее сопротивление поступает некоторый шумовой сигнал. <center><gallery widths="400px" perrow=2> Файл:Схема с общей шиной.png|а) Файл:Схема с общим источником питания.png|б) </gallery> Рисунок 5 — Примеры связей: а) — связь двух схем через общую шину заземления; б) — связь двух схем через общий источник питания.</center> Другим примером проблемы такого рода является представленная на рисунке 5, б схема разводки питания. Любое изменение тока, потребляемого схемой 2, будет изменять напряжение на зажимах питания схемы 1 из-за наличия общих сопротивлений шин питания и внутреннего сопротивления источника питания. Положение можно несколько улучшить, подключив схему 2 ближе к выходным зажимам источника питания и уменьшив тем самым величину общего сопротивления шин питания. Однако связь через внутреннее сопротивление источника питания остаётся. === Электрические и магнитные поля === Еще один вид связи представляет собой излучение электрического и магнитного полей. Все элементы схем, включая проводники, при движении по ним электрических зарядов излучают электромагнитные поля. Кроме такого не предусмотренного разработкой излучения, существует проблема преднамеренного излучения от таких источников, как радиовещательные и радиолокационные станции. Когда приёмник расположен вблизи источника (в ближнем поле), электрическое и магнитное поля рассматривают раздельно. Если же приемник находится далеко от источника (в дальнем поле), излучение рассматривается как комбинация электрического и магнитного полей, то есть как электромагнитное излучение. [[Файл:Схема с шумами.png|thumb|center|500px|Рисунок 6 — Воздействие шумов от электродвигателя на цепь с сигналами низкого уровня.]] Это имеет место, например, в схеме, показанной на рисунке 6. В этой схеме экранированный двигатель постоянного тока соединен со схемой управления. Шумы от двигателя вызывают помехи в слаботочной схеме, расположенной в той же установке. Шумовые токи, возникающие на коллекторе двигателя, выходят за пределы экрана, проходя по проводам к схеме управления. Провода излучают шумы, наводя их на слаботочные цепи. В этом примере источником шумов является искрение между щетками и коллектором двигателя. Канал связи состоит из двух частей: проводов, подведённых к двигателю, и излучения от этих проводов. Приёмником служит слаботочная цепь. В данном случае шумы источника и приёмника практически не устранимы. Поэтому помехи должны быть подавлены в канале связи. Можно блокировать шумы, проходящие по проводам за пределы экрана, или подавить излучение проводов. === Второстепенные источники шумов === '''Гальванический процесс.''' При использовании в слаботочной сигнальной цепи разнородных металлов в результате образования из них гальванической пары могут возникать напряжения шумов. При наличии на стыке двух металлов загрязнений или водяных паров создается электрохимический элемент. Развиваемая им ЭДС зависит от используемых металлов, то есть от их расположения в, так называемом, гальваническом ряду. Чем дальше в этом ряду металлы отстоят друг от друга, тем больше будет развиваемое ими напряжение. Если контакт образован одноимёнными металлами, разность потенциалов между ними отсутствует. При использовании разнородных металлов, помимо возникновения напряжения шумов, может существовать и проблема коррозии. Гальваническая коррозия приводит к тому, что положительные ионы одного металла переносятся в другой металл. Это постепенно разрушает материал анода. Скорость коррозии зависит от степени загрязнения окружающей среды и от того, насколько далеко отстоят друг от друга металлы в гальваническом ряду. Чем дальше они расположены в этом ряду, тем быстрее происходит перенос ионов. Самой распространённой комбинацией металлов является медь и алюминий. При этом алюминий в конце концов разъедается. Однако, если медь покрыта оловянно-свинцовым припоем, реакция замедляется, поскольку медь и оловянно-свинцовый припой расположены в гальваническом ряду ближе, чем медь и алюминий. Для гальванического процесса необходимо наличие четырёх элементов: # материала анода; # электролита (здесь — в виде загрязнения); # материала катода; # электропроводного соединения между анодом и катодом (обычно представляет собой цепь утечки). Гальванический процесс может иметь место даже в том случае, если между анодом и катодом нет загрязнения. Всё, что необходимо для возникновения гальванического процесса, это некоторое количество грязи на поверхности соприкосновения двух металлов. '''Электролитический процесс.''' Другой вид коррозии обусловлен электролитическим процессом. Он вызывается постоянным током, протекающим между двумя металлами при наличии между ними электролита (в качестве последнего может фигурировать грязь даже со слабыми кислотными свойствами). Коррозия такого типа не зависит от вида применяемых металлов и наблюдается даже между однородными металлами. Скорость коррозии зависит от величины тока и проводимости электролита. '''Трибоэлектрический эффект.''' В том случае, если диэлектрик внутри кабеля не имеет контакта с проводниками кабеля, на нём может накапливаться заряд. Это явление называется трибоэлектрическим эффектом. Обычно он вызывается механическим изгибом кабеля. Такой заряд действует как источник напряжения шумов, находящийся внутри кабеля. Трибоэлектрический эффект минимизируют, избегая резких перегибов кабеля и его перемещения. Выпускается специальный «малошумящий» кабель, в котором диэлектрик проходит специальную химическую обработку, сводящую к минимуму возможность накопления на нём заряда. '''Перемещение проводника.''' Если проводник движется в магнитном поле, на концах его возникает разность потенциалов. Паразитные магнитные поля, вызванные наличием больших токов в силовых цепях, а также в других схемах, имеются почти в любой точке окружающего пространства. Данная проблема усугубляется при наличии вибрации. Решается она устранением перемещения проводников путём закрепления кабелей скобами и другими приспособлениями. === Индустриальные помехи === Вопросу изучения явлений, порождающих индустриальные помехи, и методов предотвращения их возникновения в последнее время уделяется значительное внимание. Проведенные исследования показали, что как плотности, так и спектральный состав помех промышленного происхождения существенно отличаются в различных, подчас близко расположенных друг к другу районах. Наиболее высокие плотности этих помех наблюдаются в больших городах и прилегающих к ним местностях. Источники помех здесь можно разделить на две большие группы. К первой группе относятся устройства, генерирующие относительно регулярные высокочастотные колебания, не предназначенные для излучения, такие, как системы развертки электронно-лучевых трубок, различного рода промышленные, медицинские высокочастотные установки и так далее. Помехи, излучаемые такими источниками, как на основной рабочей частоте, так и на гармониках представляют собой колебания, близкие к синусоидальным. Эти источники относительно легко определяются, допускают простое прогнозирование эффектов, порождаемых их воздействием, но нелегко контролируются. К источникам второй группы, являющейся наиболее обширной, относятся различные электрические устройства, не вырабатывающие периодических высокочастотных сигналов. К ним относятся линии передачи электроэнергии, системы зажигания автомобильных двигателей, высокочастотная аппаратура для дуговой сварки, газоразрядные устройства, динамомашины, генераторы электрического тока, индукционная и переключающая аппаратура. Исследования показали, что «удельные веса» той или иной группы источников помех оказываются приблизительно одинаковыми в различных районах с примерно одинаковым уровнем развития промышленности. Так, в крупных промышленных центрах и прилегающих к ним районах основными источниками помех рассматриваемого типа являются системы зажигания двигателей внутреннего сгорания, линии электропередачи и аппаратура, используемая при дуговой сварке. На частотах, превышающих 30 МГц, помехи, порождаемые системами зажигания, обычно преобладают над помехами, создаваемыми другими источниками. На частотах же, меньших 30 МГц, преобладающими обычно являются помехи, порождаемые линиями электропередачи. '''Помехи от системы зажигания''' автомобильного двигателя представляют собой приблизительно периодический импульсный сигнал сложной формы. При скоплении в различных точках большого числа автомобилей, движущихся с различными скоростями, измеряющая аппаратура регистрирует серии импульсов со случайными амплитудами и временны́ми интервалами. Длительность регистрируемых групп импульсов колеблется в пределах от нескольких микросекунд до нескольких миллисекунд, а длительность отдельных импульсов от 1 до 6 нс. В современном городе общая интенсивность помех рассматриваемого типа характеризуется суточными изменениями приблизительно в 16 дБ (между периодами максимальной и минимальной плотности движения). При этом наблюдается корреляция абсолютного уровня помех с численностью населения в городе. Рассматриваемый вид индустриальных помех практически всегда преобладает над другими их типами в полосах местности шириной 60—80 м, прилегающих к автострадам и шоссе с интенсивным автомобильным движением. '''Помехи от линий электропередач.''' Высоковольтная аппаратура и линии передачи электроэнергии создают помехи, которые достигают максимальной интенсивности во время дождя, снега, тумана и высокой относительной влажности воздуха. В засушливых районах увеличению интенсивности помех способствует большая турбулентность воздуха и повышенный уровень солнечной радиации. Уровень помех резко возрастает при неисправности линии передачи. Помехи от высоковольтных линий передачи носят случайный характер и имеют форму непрямоугольных импульсов, длительность которых существенно превосходит ширину помеховых импульсов, вызываемых работой систем зажигания автомобильных двигателей. Частоты же следования помеховых импульсов от линий электропередач значительно ниже частот следования помеховых импульсов от систем зажигания. Причиной возникновения помех от линий электропередачи являются переходные процессы, вызываемые электрическими разрядами, которые хаотически возникают на поверхностях проводников и изоляторов линии. Импульсные токи, появляющиеся при таких разрядах, распространяются вдоль линии, которая может выступать либо в качестве коаксиального волновода (в этом случае поток энергии ограничивается внутренним проводом и оплеткой), либо в качестве одиночной линии над земной поверхностью. '''Помехи от аппаратуры дуговой сварки.''' Аппаратура дуговой сварки создает помехи очень высокого уровня. Только тот факт, что в пределах каждого локального района одновременно может работать, как правило, лишь незначительное количество таких аппаратов, не делает эту аппаратуру основным источником индустриальных помех. Чего нельзя сказать о машиностроительных предприятиях с интенсивным использованием сварочной техники. Спектры помех, возникающих при работе аппаратуры различной конструкции, не совпадают друг с другом. Результаты измерений, проведенных с большим числом аппаратов разной конструкции, показали наличие трёх широких резонансных полос, центры которых соответствуют частотам 750 кГц, 3 МГц и 20 МГц. Спектр излучения каждого отдельно взятого аппарата не обязательно включает в себя все три резонансные полосы. == Технические методы устранения помех == В своей работе «Методы подавления шумов и помех в электронных системах»<ref>{{книга|автор=Отт, Г.|заглавие=Методы подавления шумов и помех в электронных системах|ответственный=Пер. с англ|место={{М.}}|издательство=Мир|год=1979|страниц=318}}</ref> Г. Отт перечислил основные методы и дал практические рекомендации по борьбе с помехами: # экранирование; # заземление; # балансировка; # фильтрация; # изоляция; # разнесение и ориентация; # регулировка величины полного сопротивления схемы; # выбор кабеля; # подавление (в частотной или временной области). === Подавление шумов в источнике === # Необходимо заключать источники шумов в экран. # Необходимо подключать фильтры ко всем проводникам, проходящим в зашумленном пространстве. # Необходимо ограничивать время нарастания импульса. # Для катушек реле следует предусмотреть цепи подавления выбросов напряжения. # Необходимо скручивать шумящие проводники. # Необходимо экранировать витые пары шумящих проводов. # Необходимо заземлять оба конца экранов, используемых для подавления помех излучения (экраны не обязательно должны быть изолированы). === Устранение связи по шумам === # Необходимо скручивать проводники с малым уровнем сигнала. # Необходимо располагать малосигнальные проводники ближе к шине (особенно при высоком уровне полного сопротивления цепи). # Необходимо скручивать и экранировать сигнальные проводники (на высоких частотах можно использовать коаксиальный кабель). # В экранированных кабелях, используемых для защиты малосигнальных проводов, экраны следует заземлять только с одного конца (на высоких частотах можно применять коаксиальный кабель с экраном, заземленным с обоих концов). # Необходимо изолировать экран сигнальных проводов от случайного заземления в непредусмотренной точке. # Когда малосигнальные и шумящие провода проходят через общий разъём, необходимо их разделять, помещая между ними заземлённые провода. # Необходимо пропускать экранирующую оплётку сигнальных проводов через отдельный контакт разъёма. # Необходимо избегать использования общих проводов заземления для устройств с высоким и низким уровнями сигнала. # Необходимо выполнять заземление оборудования так, чтобы оно было отделено от земель схем. # Необходимо выполнять заземление возможно более короткими проводами. # Для защиты металлических поверхностей необходимо применять проводящие покрытия. # Необходимо разносить шумящие и не создающие шумов проводники. # Необходимо заземлять цепи только в одной точке (кроме высокочастотных цепей). # Необходимо избегать ненадёжных или случайных заземлений. # Для очень чувствительных схем необходимо использовать источник и нагрузку, симметричные относительно земли. # Необходимо заключать чувствительные устройства в экранирующие корпуса. # Необходимо ставить фильтры или цепи развязки на любой проводник, входящий в корпус с заключённым в нем чувствительным устройством. # Необходимо делать чувствительные проводники как можно короче. # Необходимо делать как можно короче проводники, выходящие за пределы экрана кабеля. # Необходимо применять для разводки питания шины с малым полным сопротивлением. # Необходимо избегать образования контуров заземления. # Необходимо внимательно рассмотреть использование для разрыва контуров заземления следующих устройств: #* изолирующих трансформаторов; #* нейтрализующих трансформаторов; #* оптронов; #* дифференциальных усилителей; #* усилителей с защитным экранированием; #* балансных схем. === Подавление шумов в приёмнике === # Не следует делать полосу пропускания шире, чем это необходимо. # По возможности необходимо использовать селективные частотные фильтры. # Необходимо обеспечивать соответствующую развязку по питанию. # Необходимо шунтировать электролитические конденсаторы с малой ёмкостью, работающие на высокой частоте. # Необходимо разделять сигнальные, шумящие и корпусные земли. # Необходимо применять экранирующие корпуса. # У трубчатых конденсаторов необходимо заземлять внешнюю обкладку. == Методы защиты от помех офисных и промышленных сетей == Различают локальные вычислительные сети (ЛВС) для офисного (домашнего) и промышленного применения. В офисных приложениях ЛВС к ним предъявляются в основном требования по скорости передачи данных (особенно это актуально для мультимедиа-приложений реального времени). В офисных и домашних условиях уровень помех не так сильно велик, по сравнению с производственными, поэтому в правильно сконфигурированных сетях коллизии возникают редко. Минимальные простои, связанные с повторной передачей искаженных и потерянных пакетов данных, не так критичны, как в промышленных сетях. В приложениях интернет-вещания в режиме реального времени неправильные кадры могут быть восстановлены по экстраполяционному принципу, основываясь на предыдущих данных, так как обычно искажения такого рода малозаметны или имеют приемлемый характер. К сетям полевого уровня (''fieldbus''), напротив, предъявляются жесткие требования по помехоустойчивости и предсказуемости. Обычно к промышленным сетям предъявляются следующие требования: # жёсткая детерминированность поведения; # обеспечение функций реального времени; # работа на длинных линиях с использованием недорогих физических сред (в частности, витой пары); # повышенная надёжность физического и канального уровней передачи данных в условиях производственной среды (например, при наличие мощных электромагнитных помех); # наличие специальных высоконадежных механических соединений компонентов, обеспечивающих защиту контактов от агрессивной производственной среды. В настоящий момент в промышленности пользуется популярностью расширение «офисного» ''Ethernet'' (IEEE 802.3) — ''Industrial Ethernet''. Стандарт ''Industrial Ethernet'' определяет проводные соединения и электрические сигналы на физическом уровне, формат пакетов и протоколы управления доступом к среде. В ''Industrial Ethernet'' применяются промышленные витые пары ({{lang-en|Industrial Twisted Pair}}, ITP) с двойным экранированием, IE FC TP-кабелей для быстрого монтажа и ТР-кордов или стеклянные оптоволоконные кабели. Дополнение стека протоколов TCP/IP протоколом {{RFC|1006}} обеспечивает регулярную и частую передачу по сети небольших объемов информации, что свойственно для обмена данными между промышленными контроллерами. C помощью специальных коммутаторов можно организовать кольцевую топологию, которая при обрыве восстанавливает связь, то есть находит новый путь для передачи данных значительно быстрее, чем применяемый в обычных сетях «алгоритм избыточного дерева». При этом используется алгоритм резервирования, который позволяет провести реконфигурацию сети за 0,3 с. Метод управления доступом — множественный доступ с контролем несущей и обнаружением коллизий ({{lang-en|Carrier Sense Multiple Access with Collision Detection}}, CSMA/CD). Скорость передачи данных для ''Industrial Ethernet'' составляет 10 Мбит/с, а для ''Industrial Fast Ethernet'' (IEEE 802.3u) — 100 Мбит/с, размер пакета данных — от 72 до 1526 байт. Для защиты от помех в офисных и промышленных ЛВС применяют следующие методы: # Применение витой пары в качестве среды передачи данных. Витые пары с двойным экранированием позволяют подавить синфазную помеху на 70 дБ.<ref name="ZiminWW">{{книга|автор=Зимин, В. В.|заглавие=Промышленные сети: Учеб. пособие для студентов вузов|место=Н. Новгород|издательство=НГТУ им. Р. Е. Алексеева|год=2008|страниц=252|isbn=978-5-93272-554-2}}.</ref> # Применение волоконно-оптических кабелей в качестве среды передачи данных, которые менее подвержены электромагнитным помехам. Но с другой стороны, этот метод сопряжен с накладными расходами по приобретению дополнительных модулей сопряжения с оптическими устройствами.<ref name="ZiminWW"></ref> # Применение кодирования (см. [[#Устранение помех канальным кодированием|ниже]]): ## В сетях классического ''Ethernet'' для передачи данных используется импульсная модуляция на основе манчестерского кодирования. Это импульсный код с самосинхронизацией: логическая единица кодируется перепадом потенциала от низкого уровня сигнала к высокому, а логический ноль — наоборот. Уровень высокого сигнала составляет плюс 0,85 В, низкого — минус 0,85 В. В ''Fast Ethernet'' и ''Gigabit Ethernet'' применяется избыточное кодирование: 4B/5B для первого и 8B/10B — для второго.<ref>{{книга|автор=Таненбаум, Э.|заглавие=Компьютерные сети|издание=4-е изд|место=Спб.|издательство=Питер|год=2003|страниц=992|isbn=5-318-00492-X}}.</ref> ## На уровне физического кодирования в сетях ''TokenRing'' (IEEE 802.5) применяется дифференциальное манчестерское кодирование.<ref>{{книга|автор=Гук, М.|заглавие=Аппаратные средства локальных сетей. Энциклопедия|место=Спб.|издательство=Питер|год=2000|страниц=576|isbn=5-8046-0113-X}}.</ref> ## В промышленной сети PROFIBUS ({{lang-en|PROcess FIeld BUS}}), описанной в EN 50170, используется способ передачи RS-485, базирующийся на полудуплексной, асинхронной синхронизации. Для физического кодирования используется код без возврата к нулю ({{lang-en|Non-Return to Zero}}, NRZ). ## В сетях CAN ({{lang-en|Controller Area Network}}, ISO 11898) также применяется NRZ-кодирование. ## В ЛВС для связи устройств АСУТП ''Foundation Fieldbus'' (IEC 61158-2) сигналы полевой шины шифруются кодом Манчестер biphase-L ({{lang-en|Manchester bi-φ-L}}). # В некоторых случаях при передаче данных на физическом уровне OSI применяется скремблирование. '''Скремблирование''' — это приведение информации к виду, по различным характеристикам похожему на случайные данные, что выравнивает спектр сигнала, частоты появления различных символов и их цепочек, а это позволяет подавить слишком сильные спектральные составляющие сигнала, которые вызывают нежелательные наводки на соседние линии и излучение в окружающую среду. # Для достоверности принятой информации на канальном уровне применяют дополнение пакета данных некой служебной информацией о целостности пакета. Это может быть простая контрольная сумма, выраженная в виде бита чётности (см. [[#Структурированные последовательности|ниже]]) или же набор битов. Наиболее распространенным методом верификации принятых данных является избыточный циклический контроль CRC ({{lang-en|Cycled Redundancy Control}}), и в частности, его 16-битная реализация — CRC16. # Для увеличения надёжности применяют резервирование линий передачи данных. Например, в сетях ''TokenRing'' используется топология типа «кольцо», которая имеет преимущество по сравнению с другими типами топологий в том, что при обрыве одной связывающей линии данные будут передаваться через другую. Протокол Ethernet не позволяет использовать данный способ напрямую, но контроллеры сети ''Industrial Ethernet'' имеют возможность использовать некоторые свои входы/выходы для целей резервирования и включать их в работу во время обрыва основной линии. # Переход в АСУТП на полевом уровне от аналогового сигнала (чаще всего, 4—20 мА) к цифровому позволяет повысить достоверность показаний измерительных приборов, так как в цифровой сигнал имеет конечное количество состояний. # Имеется возможность совместного использования аналоговых и цифровых сигналов. Такую возможность предоставляет протокол первичной связи HART ({{lang-en|Highway Addressable Remote Transducer}} — адресуемый дистанционный магистральный преобразователь). Данный протокол основан на методе передачи данных с помощью частотной модуляции ({{lang-en|Frequency Shift Keying}}, FSK, ЧМ) в соответствие со стандартом Bell 202. Цифровая информация передаётся частотами 1200 Гц (логическая единица) и 2200 Гц (логический ноль), которые накладываются на аналоговый токовый сигнал. Так как частотно-модулированный сигнал является двуполярным, то при применении однополосной низкочастотной фильтрации аналоговые приборы не будут чувствительны к цифровому сигналу (фильтр с полосой пропускания 10 Гц вносит искажение в исходный сигнал в ±0,01 % от максимального значения аналогового сигнала).<ref name="ZiminWW"></ref> == Устранение помех канальным кодированием == Под ''кодированием'' понимается процесс представления определённых данных с помощью ограниченного набора представлений — '''символов'''. Кодовые комбинации образовываются по некой наперёд заданной совокупности правил кодирования. Данная совокупность образует так называемую '''систему кодирования'''. Обратное преобразование информации называется '''декодированием'''. При передаче данных используется так называемое '''канальное кодирование''', которое представляет собой класс преобразований сигнала, выполняемых для повышения качества связи. В результате этого сигнал становится менее уязвимым к шуму, помехам и замираниям. Данный метод позволил более чем на 10 дБ повысить производительность при значительно меньших затратах по сравнению с другими методами, например методами увеличения мощности передатчика или размера антенны. === Кодирование сигнала и структурированные последовательности === Тему канального кодирования можно условно разделить на два раздела: кодирование (или обработка) сигнала и структурированные последовательности (или структурированная избыточность). Кодирование сигнала означает преобразование сигнала в некий «улучшенный сигнал», позволяющий сделать процесс детектирования менее подверженным ошибкам. Метод структурированных последовательностей — это преобразование последовательности данных в новую, «улучшенную последовательность», обладающую структурной избыточностью (которая вмещает избыточные биты). Эти избыточные разряды служат для определения и исправления ошибок. На выходе процедуры кодирования получается закодированный (формой сигнала или структурированной последовательностью) сигнал, имеющий лучшие пространственные характеристики, чем некодированный. Для оценки целесообразности применения кодирования вводится понятие '''эффективности кодирования'''. При данной вероятности битовой ошибки эффективность кодирования определяется как уменьшение нормированного отношения «сигнал/шум» <math>E_b/N_0</math>, которое достигается при использовании кодирования. Эффективность кодирования <math>G</math> выражается в децибелах: : <math>G\;(\mathrm{dB})=\left(\frac{E_b}{N_0}\right)_\mathrm{s}\;(\mathrm{dB})-\left(\frac{E_b}{N_0}\right)_\mathrm{c}\;(\mathrm{dB}),\qquad\qquad(24)</math> где <math>(E_b/N_0)_\mathrm{s}</math> и <math>(E_b/N_0)_\mathrm{c}</math> — значения для исходного и кодированного сигнала соответственно. Нормированное отношение «сигнал/шум» <math>E_b/N_0</math> определяется как : <math>\frac{E_b}{N_0}=\frac{E_sT_b}{E_n/B}=\frac{E_s}{E_n}\left(\frac{B}{R_b}\right),\qquad\qquad(25)</math> где <math>E_b</math> — энергия бита; <math>N_0</math> — спектральная плотность мощности шума; <math>T_b</math> — время передачи одного бита; <math>R_b=1/T_b</math> — скорость передачи битов; <math>B</math> — ширина полосы. === Кодирование сигнала === Для кодирования информации используют различные сигналы. Рассмотрим некоторые из них. [[Файл:Пример антиподных сигналов.png|thumb|center|400px|Рисунок 7 — Пример антиподных сигналов.]] '''Антиподные сигналы''' являются зеркальными отображениями друг друга, либо один сигнал является отрицательным по отношению к другому, либо они различаются между собой на 180° (противофазные сигналы). На рисунке 7 изображён набора синусоидальных антиподных сигналов таких, что <math>s_1(t)=-s_2(t)=\sin\omega t</math>, <math>0\leqslant t\leqslant T</math>. Набор равноэнергетических сигналов <math>s_i(t)</math>, <math>i=1,\;2,\;\ldots</math>, называется '''ортонормированным''' ('''ортогональным'''), если выполняется условие: : <math>\rho_{ij}=\frac{1}{E}\int\limits_0^T s_i(t)s_j(t)\,dt=\delta_{ij},\qquad\qquad(26)</math> где <math>\rho_{ij}</math> — коэффициент взаимной корреляции; <math>\delta_{ij}=\begin{cases}1, & i=j, \\ 0, & i\neq j\end{cases}</math> — символ Кронекера; <math>E</math> — энергия сигнала : <math>E=\int\limits_0^T s^2(t)\,dt.\qquad\qquad(27)</math> Примером таких сигналов могут служить гармонические функции. На рисунке 8 изображены сигнал <math>s_1(t)=\sin\omega t</math> и <math>s_2(t)=\cos\omega t=\sin\left(\omega+\frac{\pi}{2}\right)t</math>, <math>0\leqslant t\leqslant T</math>. [[Файл:Пример гармонических ортогональных сигналов.png|thumb|center|400px|Рисунок 8 — Пример гармонических ортогональных сигналов.]] Ортогональными могут быть также наборы импульсных сигналов. На рисунке 9 показан набор ортогональных сигналов, которые имеют вид импульсов, имеющих следующее аналитическое выражение: <math>s_1(t)=p(t)</math> и <math>s_2(t)=p\left(t-\frac{T}{2}\right)</math>, <math>0\leqslant t\leqslant T</math>. Импульс <math>p(t)</math> имеет длительность <math>\tau=\frac{T}{2}</math>, где <math>T</math> — период. [[Файл:Пример импульсного ортогонального сигнала.png|thumb|center|400px|Рисунок 9 — Пример импульсного ортогонального сигнала.]] Если расширить значение коэффициента взаимной корреляции <math>\rho_{ij}</math> в область отрицательных значений, то антиподные сигналы можно считать частным случаем ортогональных сигналов с <math>\rho_{ij}=-1</math>. Временно́е разделение сигналов позволяет осуществлять '''<math>M</math>-арную передачу сигналов''', при которой процессор за один такт работы принимает <math>k</math> бит данных. Процессор указывает модулятору произвести один из <math>M=2^k</math> сигналов. Частным случаем при <math>k=1</math> является '''двоичная передача сигнала'''. При <math>k>1</math> <math>M</math>-арную передачу сигналов можно рассматривать как процедуру кодирования формы сигнала. При ортогональной передаче сигналов увеличение <math>k</math> приводит к повышению достоверности передачи или уменьшению требуемого <math>E_s/E_n</math> за счёт увеличения полосы пропускания. При неортогональной передаче сигналов улучшение эффективности использования полосы пропускания происходит за счёт снижения достоверности передачи или возрастания требуемого <math>E_s/E_n</math>. Как уже было сказано выше, процедура кодирования сигнала состоит в преобразовании набора сигналов (представляющих набор сообщений) в усовершенствованный набор сигналов, но при этом каждый сигнал набора пытаются сделать настолько непохожим на другие, насколько это возможно. Это требование выражает значение коэффициент взаимной корреляции <math>\rho_{ij}</math>, которое должно быть как можно меньше. Строго это условие выполняется тогда, когда сигналы антикоррелируют (при <math>\rho_{ij}=-1</math>). Этого можно добиться только в том случае, если в наборе всего два значения (<math>M=2</math>) и они антиподны друг другу. На практике используют набор сигналов с большим количеством элементов. Поэтому наименьшее значение <math>\rho_{ij}=0</math>, что соответствует системе ортогональных сигналов. === Ортогональные коды === Для набора кодовых слов, состоящего из <math>M</math> сигналов, условие ортогональности примет вид: : <math>z_{ij}=\frac{n_s-n_n}{N}=\delta_{ij},\qquad\qquad(28)</math> где <math>n_s</math> — количество совпавших бит; <math>n_n</math> — количество несовпавших бит; <math>N</math> — общее количество бит в последовательности. Набор однобитовых данных можно преобразовать с помощью ортогональных кодовых слов, состоящих из двух разрядов каждое, которые описываются строками матрицы <math>H_1</math>: {|align=center |align=center|Набор данных||style="width:100px"|&nbsp;||Набор ортогональных<br />кодовых слов |- |align=center|<math>\begin{matrix}0 \\ 1\end{matrix}</math>||style="width:100px"|&nbsp;||<math>H_1=\begin{bmatrix}0 & 0 \\ 0 & 1\end{bmatrix}</math> |} Вообще, для набора <math>k</math>-битовых данных из матрицы <math>H_{k-1}</math> можно построить набор кодовых слов <math>H_k</math> размерностью <math>2^k\times 2^k</math>, который называется '''матрицей Адамара''': : <math>H_k=\begin{bmatrix}H_{k-1} & H_{k-1} \\ H_{k-1} & \overline{H_{k-1}}\end{bmatrix},\qquad\qquad(29)</math> где черта над <math>H_{k-1}</math> означает логическое отрицание. Каждая пара слов в каждом наборе кодовых слов <math>H_1,\;H_2,\;\ldots,\;H_k,\;\ldots,\;H_{2^k}</math> содержит одинаковое количество совпадающих и несовпадающих разрядов, поэтому, в соответствии с уравнением (28), <math>z_{ij}</math> (при <math>i\neq j</math>) и каждый из этих наборов ортогонален. Для одинаковых, равноэнергетических ортогональных сигналов '''вероятность ошибки в кодовом слове (символе)''' <math>P_{\mathrm{err}}</math>, можно оценить сверху, как : <math>P_{\mathrm{err}}(M)\leqslant(M-1)\mathrm{erfc}\left(\sqrt{\frac{E_s}{N_0}}\right),\qquad\qquad(30)</math> где <math>M=2^k</math> — размер набора кодовых слов; <math>k</math> — число информационных бит; <math>E_s=kE_b</math> — энергия кодового слова; <math>E_b</math> — энергия одного бита; <math>N_0</math> — спектральная плотность мощности шума; <math>\mathrm{erfc}(x)</math> — гауссов интеграл ошибки, равный: : <math>\mathrm{erfc}(x)=\frac{1}{2\pi}\int\limits_x^\infty e^{-\frac{t^2}{2}}\,dt.\qquad\qquad(31)</math> '''Вероятность появления ошибочного бита''' <math>P_{\mathrm{erb}}</math> можно определить как: : <math>P_{\mathrm{erb}}=\frac{M}{2}\mathrm{erfc}\left(k\frac{E_s}{N_0}\right).\qquad\qquad(32)</math> Модификацией ортогонального кода является '''биортогональный код'''. Биортогональный набор сигналов, состоящий из <math>M</math> кодовых слов (сигналов), получается из <math>M/2</math> ортогонального набора, состоящего из сигналов, путем дополнения последнего отрицанием каждого сигнала: : <math>B_k=\begin{bmatrix}H_{k-1} \\ \overline{H_{k-1}}\end{bmatrix}.\qquad\qquad(33)</math> Биортогональный набор состоит из комбинации ортогональных и антиподных сигналов, поэтому если использовать коэффициент <math>z_{ij}</math>, то биортогональные коды можно представить следующим образом: : <math>z_{ij}=\begin{cases}1, & i=j; \\ -1, & i\neq j,\;|i-j|=\dfrac{M}{2}; \\ 0, & i\neq j,\;|i-j|\neq\dfrac{M}{2}.\end{cases}\qquad\qquad(34)</math> Одно из преимуществ биортогональных кодов перед ортогональными заключается в том, что при передаче аналогичной информации размер кодового слова биортогональных кодов вдвое меньше размера кодового слова ортогональных кодов. Следовательно, при использовании биортогональных кодов требования к полосе пропускания вдвое слабее, чем при использовании ортогональных кодов. Поскольку антиподные векторы сигналов имеют лучшие пространственные характеристики, чем ортогональные. Для одинаковых, равноэнергетических биортогональных сигналов вероятность ошибки в кодовом слове (символе) можно оценить следующим образом: : <math>P_{\mathrm{err}}(M)\leqslant(M-2)\mathrm{erfc}\left(\sqrt{\frac{E_s}{N_0}}\right)+\mathrm{erfc}\left(\sqrt{\frac{2E_s}{N_0}}\right),\qquad\qquad(35)</math> Для биортогональных кодов довольно трудно получить оценку <math>P_{\mathrm{erb}}</math>, поэтому пользуются следующей аппроксимацией, имеющей место при <math>M>8</math>, или <math>k>3</math>: : <math>P_{\mathrm{erb}}=\frac{1}{2}\left((M-2)\mathrm{erfc}\left(\sqrt{\frac{E_s}{N_0}}\right)+\mathrm{erfc}\left(\sqrt{\frac{2E_s}{N_0}}\right)\right).\qquad\qquad(36)</math> Описанные биортогональные коды значительно снижают <math>P_{\mathrm{erb}}</math> по сравнению с ортогональными кодами и требуют только половину полосы пропускания ортогональных кодов. Код, получаемый из ортогонального ряда путём удаления первого разряда каждого кодового слова, называется '''трансортогональным''', или '''симплексным кодом'''. Такой код описывается следующими значениями <math>z_{ij}</math>: : <math>z_{ij}=\begin{cases}1, & i=j; \\ \dfrac{-1}{M-1}, & i\neq j.\end{cases}\qquad\qquad(37)</math> С точки зрения минимальной энергии, необходимой для поддержания заданной вероятности ошибки, симплексный код эквивалентен равновероятному ортогональному набору. Сравнивая достоверность передачи ортогонального, биортогонального и симплексного кодов, можно сказать, что симплексный код имеет наименьшее требуемое <math>E_b/N_0</math> для получения определенной частоты появления символьных ошибок. Впрочем, при больших <math>M</math> все три схемы очень похожи между собой в смысле достоверности передачи. При этом биортогональное кодирование, по сравнению с другими методами, требует лишь половины полосы пропускания. === Структурированные последовательности === Структурированные последовательности делятся на три подкатегории: * блочные; * свёрточные; * турбокоды. Рассмотрим каждый из этих типов. При использовании '''блочных кодов''' исходные данные делятся на блоки из <math>k</math> бит, которые называют '''информационными битами''', или '''битами сообщения'''. Каждый блок может представлять любое из <math>2^k</math> отдельных сообщений. В процессе кодирования каждый <math>k</math>-битовый блок данных преобразуется в больший блок из <math>n</math> бит, который называется '''кодовым битом''', или '''канальным символом'''. К каждому блоку данных кодирующее устройство прибавляет <math>(n-k)</math> бит, которые называются '''избыточными битами''', или '''контрольными битами'''. Если <math>n-k=1</math>, то контрольный бит называется '''битом чётности''', или '''битом паритета''' (от {{lang-en|parity}} — чётный). Новой информации контрольные биты не несут. Блочные коды обозначаются как <math>(n,\;k)</math>. Отношение числа избыточных бит к числу информационных бит: : <math>\frac{n-k}{k}\qquad\qquad(38)</math> называется '''избыточностью кода'''. Отношение числа бит данных к общему числу бит <math>k/n</math> носит название '''степень кодирования'''. Под степенью кодирования подразумевается доля кода, которая приходится на полезную информацию. Например, в коде со степенью 1/2, каждый кодовый бит несёт 1/2 бита информации. '''Коды с контролем чётности''' для обнаружения или исправления ошибок используют линейную сумму информационных битов, которая представляется одним контрольным битом, который позже прибавляется к блоку информационных битов. Этот бит (бит чётности) может быть равен нулю или единице, причём его значение выбирается так, чтобы сумма всех битов в кодовом слове была чётной или нечётной. В операции суммирования используется арифметика по модулю 2 (операция исключающего ИЛИ). Если бит чётности выбран так, что результат чётный, то говорят, что схема имеет '''положительную чётность'''; в противном случае, говорят об '''отрицательной чётности'''. Расширением кодов с битом паритета является '''прямоугольный''', или '''композиционный код'''. Он создаётся следующим образом. Вначале из битов сообщения строится прямоугольник, состоящий из <math>M</math> строк и <math>N</math> столбцов. Затем к каждой строке и каждому столбцу прибавляется бит чётности, что в результате даёт матрицу размером <math>(M+1)\times(N+1)</math>. Любая отдельная ошибка в разряде приведёт к нарушению чётности в одном столбце и в одной из строк матрицы. Следовательно, прямоугольный код может исправить любую единичную ошибку, поскольку расположение такой ошибки однозначно определяется пересечением строки и столбца, в которых была нарушена чётность. '''Линейные блочные коды''' — это класс кодов с контролем чётности, которые можно описать парой чисел <math>(n,\;k)</math>. В процессе кодирования блок из <math>k</math> символов сообщения ('''вектор сообщения''') преобразуется в больший блок из <math>n</math> символов кодового слова ('''кодовый вектор'''), образованного с использованием элементов данного алфавита. Если алфавит состоит только из двух элементов (0 и 1), код является '''двоичным''' и включает двоичные разряды (биты). Это самые распространённые виды линейных блочных кодов. <math>k</math>-Битовые сообщения формируют набор из <math>2^k</math> последовательностей сообщения, называемых '''<math>k</math>-кортежами''' (последовательностями <math>k</math> цифр). Процедура кодирования сопоставляет с каждым из <math>2^k</math> <math>k</math>-кортежей сообщения один из <math>2^n</math> <math>n</math>-кортежей. Следовательно, линейные блочные коды представляют взаимно однозначное соответствие, которое производится согласно, так называемой, '''таблице соответствия'''. Данный вид кодов используется в расширении сетевой технологии ''Ethernet'': в ''Fast Ethernet'' используется код 4B/5B — кодирование 4 битов информации 5 канальными битами, в ''Gigabit Ethernet'' — 8B/10B (8 бит информации — 10 канальных бит). Важным подклассом линейных блочных кодов являются '''двоичные циклические коды'''. Линейный код <math>(n,\;k)</math> называется '''циклическим''', если он обладает следующим свойством. Если <math>n</math>-кортеж <math>U=(u_0,\;u_1,\;u_2,\;\ldots,\;u_{n-1})</math> является кодовым словом, тогда <math>n</math>-кортеж <math>U(1)=(u_{n-1},\;u_0,\;u_1,\;u_2,\;\ldots,\;u_{n-2})</math>, полученный из <math>U</math> с помощью циклического сдвига, также является кодовым словом. Вообще, <math>U(i)=(u_{n-i},\;u_{n-i+1},\;\ldots,\;u_{n-1}\;u_0,\;u_1,\;\ldots,\;u_{n-i-1})</math>, полученный <math>i</math> циклическими сдвигами, является также является кодовым словом. Данный код легко реализуется на регистре сдвига с обратной связью. '''Коды Хэмминга''' — это простой класс блочных кодов, которые имеют следующую структуру: : <math>(n,\;k)=(2^m-1,\;2^m-1-m),\qquad\qquad(39)</math> где <math>m=2,\;3,\;\ldots</math> Они способны исправлять все однобитовые ошибки или определять все модели из двух ошибок в блоке. Для декодирование кодов Хэмминга особенно хорошо подходят, так называемые, синдромы — матрицы, представляющие собой результат проверки чётности, выполняемой над сигналом для определения его принадлежности заданному набору кодовых слов. Хотя коды Хэмминга не являются слишком мощными, они принадлежат к очень ограниченному классу блочных кодов, называемых '''совершенными'''. Одним из наиболее практичных блочных кодов является '''двоичный расширенный код Голея''' <math>(24,\;12)</math>, который образован путём прибавления битов чётности к совершенному коду <math>(23,\;12)</math>, известному как '''код Голея'''. Эти дополнительные биты дают степень кодирования 1/2, реализовать которую проще (с точки зрения системного тактового генератора), чем степень кодирования кода Голея, равную 12/23. Расширенный код Голея значительно мощнее рассмотренного выше кода Хэмминга. Цена, которую приходится платить за повышение эффективности, заключается в более сложном декодере и, соответственно, более широкой полосе пропускания. '''Коды Боуза — Чоудхури — Хоквенгема''' ('''БЧХ-коды''') являются результатом обобщения кодов Хэмминга, которое позволяет исправлять множественные ошибки. Они составляют мощный класс циклических кодов, который обеспечивает достаточную свободу выбора длины блока, степени кодирования, размеров алфавита и возможностей коррекции ошибок. Коды БХЧ очень важны, поскольку при блоках, длина которых равна порядка несколько сотен, коды БХЧ превосходят своими качествами все другие блочные коды с той же длиной блока и степенью кодирования. В наиболее часто применяемых кодах БХЧ используется двоичный алфавит и блок кодового слова длиной <math>n=2^m-1</math>, где <math>m=3,\;4,\;\ldots</math> '''Коды Рида — Соломона''' — это недвоичные циклические коды, символы которых представляют собой <math>m</math>-битовые последовательности, где <math>m>1</math>. Коды Рида — Соломона определены на <math>m</math>-битовых символах при всех <math>n</math> и <math>k</math>, для которых <math>0<k<n<2^m+2</math>, где <math>k</math> — число информационных битов, подлежащих кодированию, а <math>n</math> — число кодовых символов в кодируемом блоке. Для большинства кодов Рида — Соломона : <math>(n,\;k)=(2^m-1,\;2^m-1-2t),\qquad\qquad(40)</math> где <math>t</math> — количество ошибочных битов в символе, которые может исправить код, а <math>2t=n-2k</math> — число контрольных символов. '''Расширенный код Рида — Соломона''' можно получить при <math>n=2^m</math> или <math>n=2^m+1</math>, но не более того. Коды Рида — Соломона чрезвычайно эффективны для исправления пакетов ошибок, поэтому их разновидность, называемая '''кодом Рида — Соломона с перекрестным чередованием''' ({{lang-en|cross-interleave Reed — Solomon code}}, CIRC), используется в системе цифровой записи на компакт-дисках ({{lang-en|compact disc digital audio}}, CD-DA). В данном случае существует несколько источников канальных ошибок: маленькие нежелательные частички или воздушные пузырьки в материале пластика или неточное расположение впадин при изготовлении диска и отпечатки пальцев или царапины, появившиеся при эксплуатации. Можно сказать, что канал, в основном, склонен вносить пакетоподобные ошибки, поскольку царапины или пятна от пальцев будут вызывать ошибки в нескольких последовательных фрагментах данных. Рассмотрим теперь '''свёрточные коды'''. Для их реализации используются специальные свёрточные кодеры. Рассмотрим принцип их работы. Исходное сообщение на входе обозначается последовательностью <math>\mathbf{m}=m_1,\;m_2,\;\ldots,\;m_i,\;\ldots</math>, где <math>m_i</math> — двоичный знак (бит), а <math>i</math> — индекс времени. Предполагается, что все <math>m_i</math> равновероятно равны единице или нулю и независимы между собой. Будучи независимой, последовательность битов нуждается в некоторой избыточности, то есть знание о бите <math>m_i</math> не даёт никакой информации о бите <math>m_j</math> (при <math>i\neq j</math>). Кодер преобразует каждую последовательность <math>\mathbf{m}</math> в уникальную последовательность кодовых слов <math>\mathbf{U}=G(\mathbf{m})</math>. Даже несмотря на то, что последовательность <math>\mathbf{m}</math> однозначно определяет последовательность <math>\mathbf{U}</math>, ключевой особенностью свёрточных кодов является то, что данный <math>k</math>-кортеж внутри <math>\mathbf{m}</math> не однозначно определяет связанные с ним <math>n</math>-кортежи внутри <math>\mathbf{U}</math>, поскольку кодирование каждого из <math>k</math>-кортежей является функцией не только <math>k</math>-кортежей, но и предыдущих <math>K</math> <math>k</math>-кортежей. Последовательность <math>\mathbf{U}</math> можно разделить на последовательность кодовых слов: <math>\mathbf{U}=U_1,\;U_2,\;\ldots,\;U_i,\;\ldots</math> Каждое кодовое слово <math>U_i</math> состоит из двоичных кодовых символов, часто называемых '''канальными символами''', '''канальными битами''', или '''битами кода''', в отличие от битов входного сообщения, кодовые символы не являются независимыми. [[Файл:Свёрточный кодер.png|thumb|center|500px|Рисунок 10 — Свёрточный кодер с длиной кодового ограничения <math>\scriptstyle{K}</math> и степенью кодирования <math>\scriptstyle{k/n}</math>.]] Обычный свёрточный кодер, показанный на рисунке 10, реализуется <math>kK</math>-разрядным регистром сдвига и <math>n</math> сумматорами по модулю 2, где <math>K</math> — длина кодового ограничения. '''Длина кодового ограничения''' — это количество <math>k</math>-битовых сдвигов, после которых один информационный бит может повлиять на выходной сигнал кодера. В каждый момент времени на место первых <math>k</math> разрядов регистра перемещаются <math>k</math> новых бит. Все биты в регистре смещаются на <math>k</math> разрядов вправо, и выходные данные <math>n</math> сумматоров последовательно дискретизируются, давая, в результате, биты кода. Затем эти символы кода используются модулятором для формирования сигналов, которые будут переданы по каналу. Поскольку для каждой входной группы из <math>k</math> бит сообщения имеется <math>n</math> бит кода, степень кодирования равна <math>k/n</math> бит сообщения на бит кода, где <math>k<n</math>. Наиболее часто используются двоичные свёрточные кодеры, для которых <math>k=1</math>, то есть биты сообщения сдвигаются по одному биту за такт. Таким образом, за <math>i</math>-й момент времени бит сообщения <math>m_i</math> будет перемещён на место первого разряда регистра сдвига, все предыдущие биты в регистре будут смещены на один разряд вправо, а выходной сигнал <math>n</math> сумматоров будет последовательно оцифрован и передан. Поскольку для каждого бита сообщения имеется <math>n</math> бит кода, то степень кодирования равна <math>1/n</math>. Имеющиеся в момент времени <math>t_i</math> <math>n</math> кодовых символов составляют <math>i</math>-е кодовое слово ветви <math>U_1=u_{1i},\;u_{2i},\;\ldots,\;u_{ni}</math>, где <math>u_{ji}</math> (<math>j=1,\;2,\;\ldots,\;n</math>) — это <math>j</math>-й кодовый символ, принадлежащий <math>i</math>-му кодовому слову ветви. Для описания свёрточного кода нужно определить кодирующую функцию <math>G(\mathbf{m})</math>. Для этого существует несколько методов, наиболее наглядный из которых является представление функции в виде древовидной диаграммы, где каждый лист является одной из возможных альтернатив значения <math>u_{ji}</math>. Для приёма сообщений, представленных свёрточными кодами, используются '''свёрточные декодеры'''. При передаче информации по линиям связи в зашумленной среде неизбежно происходит искажение информации. Поэтому цель декодера не просто обратить действие кодера на информацию, но и сделать это с максимально возможной степенью правдоподобия. Принятие решений о том, что принятая искажённая последовательность соответствует переданной, основывается на '''принципе максимального правдоподобия'''. Принцип — это формализация способа принятия решений, основанного на «здравом смысле», когда имеются статистические данные о вероятностях. В основу принципа положено предположение, что если все входные последовательности сообщений равновероятны, то минимальная вероятность ошибки получается при использовании декодера, который сравнивает условные вероятности и выбирает максимальную. Условные вероятности также называются '''функциями правдоподобия''' <math>P\left(\mathbf{Z}\mid\mathbf{U}^{(m)}\right)</math>, где <math>\mathbf{Z}</math> — это принятая последовательность, а <math>\mathbf{U}^{(m)}</math> — одна из возможных переданных последовательностей. Декодер выбирает <math>\mathbf{U}^{(m')}</math>, если : <math>P\bigl(\mathbf{Z}\mid\mathbf{U}^{(m')}\bigr)=\max_{\forall\mathbf{U}^{(m)}}P\left(\mathbf{Z}\mid\mathbf{U}^{(m)}\right).\qquad\qquad(41)</math> Улучшением декодера максимального правдоподобия являются декодеры, построенные по '''алгоритму декодирования Витерби'''. Данный алгоритм уменьшает вычислительную нагрузка за счёт использования особенностей структуры конкретной решётки кода. Преимущество декодирования Витерби, по сравнению с декодированием по методу «грубой силы», заключается в том, что сложность декодера Витерби не является функцией количества символов в последовательности кодовых слов. Алгоритм включает в себя вычисление '''расстояния''' (мера подобия) между сигналом, полученным в момент времени <math>t_i</math> и всеми путями решётки, входящими в каждое состояние в момент времени <math>t_i</math>. В алгоритме Витерби не рассматриваются те пути решётки, которые, согласно принципу максимального правдоподобия, заведомо не могут быть оптимальными. Если в одно и то же состояние входят два пути, выбирается тот, который имеет лучшую метрику; такой путь называется '''выживающим'''. Отбор выживающих путей выполняется для каждого состояния. Таким образом, декодер углубляется в решётку, принимая решения путём исключения менее вероятных путей. Предварительный отказ от маловероятных путей упрощает процесс декодирования. В качестве меры подобия используется '''расстояние Хэмминга''' — метрика различия объектов одинаковой размерности. Расстоянием Хэмминга <math>d(\mathbf{X},\;\mathbf{Y})</math> между двумя двоичными последовательностями <math>\mathbf{X}</math> и <math>\mathbf{Y}</math> длины <math>n</math> называется число позиций, в которых они различны. '''Турбокоды''' впервые были введены в 1993 году Берру, Главье и Цитимаджимой. Турбокод можно считать обновлением структуры каскадного кодирования с итеративным алгоритмом декодирования связанной кодовой последовательности. Схема '''каскадного кодирования''' впервые была предложена Форни как метод получения высокоэффективного кода посредством комбинации двух или более компонуемых (составных) кодов. В результате, такие коды могут корректировать ошибки в значительно более длинных кодах и имеют структуру, которая позволяет относительно легко осуществить декодирование средней сложности. Последовательные каскадные коды часто используются в системах с ограничением мощности, таких как космические зонды. Самая распространенная из этих схем содержит внешний код Рида — Соломона (выполняется первым, убирается последним), который следует за свёрточным внутренним кодом (выполняется последним, убирается первым). Туброкоды могут быть последовательными и параллельными с последующей конкатенацией (объединением) результатов. Кодирование производится как итерационными, так и рекурсивными методами. '''Декодирование турбокодов''' производится методами аналогичными методам декодирования свёрточных кодов. Здесь имеет место быть '''принцип максимума апостериорной вероятности''' ({{lang-en|maximum a posteriori}}, MAP). Аналогом алгоритма Витерби при турбокодирование являются алгоритмы Бала или его модификация — алгоритм Берру. Наличие нескольких декодеров в составе декодера турбокода позволяет осуществлять, так называемую, '''обратную связь декодирования''', которая позволяет влиять результатам декодирования одного декодера на результаты другого. == Методы приёма сигналов == Приём сигналов базируется на следующем утверждении: принимая любой сигнал, мы обязательно что-то о нём знаем и чего-то не знаем. Предварительные сведения о сигнале используются для рационального выбора метода приёма в соответствии с поставленными целями. Если бы о сигнале заранее не было известно абсолютно ничего, то его нельзя было бы принять, так как не известно было бы, чем сигнал отличается от несигнала, в частности, от любой помехи. То, чего мы заранее не знаем, может являться носителем полезной информации. Если бы о сигнале нам абсолютно все было известно наперед, то такой сигнал не нужно было бы и передавать: он не принес бы нам никакой информации. Говоря конкретно, объектом априорного знания или незнания могут являться те или иные физические параметры сигнала, например, интенсивность, несущая частота, время появления, длительность, и так далее. Некоторые из этих параметров остаются неизменными. В таком случае их следует рассматривать как постоянные признаки сигнала, и наличие этих признаков нужно наилучшим образом использовать для различения сигнала и помехи. Другие же параметры можно так или иначе модулировать. Эти параметры называются информационными. В их изменениях, неизвестных заранее на приёмной стороне, заложена переносимая сигналом информация. Обычно известен лишь диапазон возможных изменений информационных параметров. В зависимости от назначения сигналов, задачи приёма сводятся к трём основным: # обнаружение сигнала; # различение сигналов; # восстановление сообщения. === Обнаружение сигнала === Под '''обнаружением''' (детектированием) сигнала понимается установление его наличия. При наличии шума (аддитивной помехи) задача сводится к получению ответа на вопрос — имеется ли на входе приёмника сигнал плюс шум, или только шум? Кратко, обнаружение сигнала — это констатация наличия сигнала. Часто ошибочно полагают, что обнаружение сигнала не требует измерения каких-либо параметров сигнала. Всякое обнаружение неразрывно связано с измерением тех или иных параметров. Более того: обнаружение это, в сущности, и есть измерение, хотя и грубое. В самом деле: когда обнаруживают сигнал, то обнаруживают его не вообще, а в определённой полосе частот, в определённом интервале времени и так далее. Интервалы, в которых заключены значения этих параметров, определяют точность, с которой они измеряются. В дальнейшем, если требуется, точность может быть повышена. Если имеется возможность обнаружить сигнал, то есть отличить наличие сигнала от его отсутствия, то это открывает возможность передачи любой информации при помощи двоичного кода. Наличие сигнала (посылка) будет соответствовать символу 1, отсутствие сигнала (пауза) — символу 0. Такая система носит название '''передачи с пассивной паузой''', так как в паузе передатчик бездействует. В теории приёма-передачи данных важным понятием является «оптимальный приёмник», или применительно к поставленной задаче — «'''оптимальный обнаружитель'''». Под оптимальным обнаружителем понимается теоретически наилучший вид приёмника, позволяющий детектировать наличие заранее известного сигнала при максимальном уровне отношения «сигнал/помеха». В качестве такого может служить '''согласованный фильтр'''. Согласованный фильтр рассчитывается для обнаружения сигнала заранее известной формы, выходной сигнал фильтра при этом не совпадает по форме ни со входным, ни с сигналом, для обнаружения которого фильтр предназначен (кроме импульса с огибающей гауссовой формы). Сигнал, с которым фильтр согласован, детектируется однозначно, поскольку именно при его наличии во входном сигнале с шумом амплитуда выходного сигнала фильтра максимальна.<ref>{{книга|автор=Гоноровский, И. С.|заглавие=Радиотехнические цепи и сигналы: Учебник для вузов|издание=4-е изд., перераб. и доп|место={{М.}}|издательство=Радио и связь|год=1986|страниц=512}}</ref> Передаточная функция фильтра имеет вид: : <math>\mathbf{K}(i\omega)=K(\omega)\cdot e^{i\varphi_K(\omega)},\qquad\qquad(42)</math> где <math>K(\omega)</math> — амплитудно-частотная характеристика (АЧХ) фильтра; <math>\varphi_K(\omega)</math> — фазочастотная характеристика (ФЧХ) фильтра. Для отыскания оптимальной передаточной функции, максимизирующей отношение «сигнал/помеха» на выходе фильтра при наличии помехи с равномерной спектральной плотностью мощности, необходимо составить отношение: : <math>\frac{s_\mathrm{out}(t_0)}{\sigma_\mathrm{out}}=\frac{\left|\dfrac{1}{2\pi}\int\limits_{-\infty}^{+\infty}\mathbf{S}(i\omega)\mathbf{K}(i\omega)e^{i\cdot\omega t_0}\,d\omega\right|}{\sqrt{\dfrac{N_0}{2\pi}\int\limits_{-\infty}^{+\infty}K^2(\omega)\,d\omega}},\qquad\qquad(43)</math> где <math>t_0</math> — момент времени, в который наблюдается максимум выходного сигнала; <math>s_\mathrm{out}(t_0)</math> — пиковое значение сигнала на выходе фильтра; <math>\sigma_\mathrm{out}</math> — среднеквадратичное значение помехи на выходе фильтра; <math>\mathbf{S}(i\omega)</math> — спектральная плотность сигнала. Используя неравенство Буняковского — Шварца, получим: : <math>\frac{s_\mathrm{out}(t_0)}{\sigma_\mathrm{out}}\leqslant\frac{1}{\sqrt{N_0}}\cdot\sqrt{\frac{1}{2\pi}\int\limits_{-\infty}^{+\infty}S^2(\omega)\,d\omega}=\sqrt{\frac{E}{N_0}},\qquad\qquad(44)</math> где <math>E</math> — полная энергия входного сигнала. Неравенство (44) обращается в равенство при : <math>\mathbf{K}(i\omega)e^{i\omega t_0}=A\cdot\mathbf{S}^*(i\omega),\qquad\qquad(45)</math> где <math>A</math> — произвольная постоянная; <math>\mathbf{S}^*(i\omega)</math> — функция, комплексно-сопряженная с <math>\mathbf{S}(i\omega)</math>, Выражение (45) можно представить как : <math>\mathbf{K}(i\omega)e^{i\omega t_0}=A\cdot S(\omega)\cdot e^{-i\cdot(\varphi_S(\omega)+\omega t)},\qquad\qquad(46)</math> где <math>\varphi_S(\omega)</math> — фаза спектральной плотности сигнала; <math>S(\omega)</math> — модуль спектральной плотности сигнала. Отношение (46) определяет передаточную функцию фильтра, обеспечивающего максимум отношения «сигнал/помеха» на выходе. Из принципа физической реализуемости согласованного фильтра следует, что время достижения максимального сигнала на выходе фильтра <math>t_0</math> равно длительности импульса <math>T_s</math>. Для того чтобы достоверно говорить об обнаружении сигнала в смеси «сигнал+шум», необходимо, чтобы выполнялось неравенство<ref>{{книга|автор=Харкевич, А. А.|заглавие=Борьба с помехами|издание=2-е изд., доп. и перераб|место={{М.}}|издательство=Наука|год=1965|страниц=276}}</ref>: : <math>s_\mathrm{out}\geqslant s_p,\qquad\qquad(47)</math> где <math>s_p</math> — некое пороговое значение напряжения, конкретно заданное для каждого вида сигнала. '''Пороговое напряжение''' <math>s_p</math> определяется как: : <math>s_p=E_\mathrm{mix}E_\mathrm{s}\cos\vartheta,\qquad\qquad(48)</math> где <math>E_\mathrm{mix}</math> — энергия смеси «сигнал+шум»; <math>E_\mathrm{s}</math> — энергия сигнала; <math>\cos\vartheta</math> — косинус угла при вершине конуса, образованного векторами системы сигналов. Например, для ортогональных сигналов <math>\cos\vartheta=0</math>. Таким образом, для определения наличия сигнала в смеси, нужно наличие положительного потенциала на выходе согласованного фильтра в момент времени <math>t_0=T_s</math>. === Различение сигналов === При передаче двух различных сигналов, <math>s_1</math> и <math>s_2</math>, положение несколько иное. Здесь речь идёт уже не об обнаружении, а о различении двух сигналов. Дело сводится к ответу на вопрос: имеется ли на входе приёмника сигнал <math>s_1</math> плюс шум, или сигнал <math>s_2</math> плюс шум? Ответ на этот вопрос определяется уже не свойствами каждого сигнала в отдельности, эти свойства в принципе могли бы оставаться неизвестными, а '''физическим различием''' между сигналами. Сигналы могут различаться между собою значениями тех или иных параметров. При выборе двух сигналов нужно стремиться к тому, чтобы различие между ними было по возможности более стойким по отношению к действию помехи. Это значит, прежде всего, что различие должно быть по возможности велико, с тем, что если оно уменьшится в процессе передачи под действием помехи, то оставшееся различие должно быть все же достаточно для уверенного различения сигналов. Но, кроме того, нужно выбирать различие по тому параметру (из всех параметров данного сигнала), который в наименьшей степени подвержен влиянию помехи данного типа. Очевидно, случай обнаружения может рассматриваться как вырожденный случай различения двух сигналов, когда один из них есть тождественный нуль. Передача двоичным кодом, в котором символу 1 соответствует сигнал <math>s_1</math>, а символу 0 — сигнал <math>s_2</math>, называется '''передачей с активной паузой'''. Случай различения многих сигналов в принципиальном отношении мало отличается от случая различения двух сигналов. Все сказанное выше по поводу различения двух сигналов должно быть отнесено в случае набора из нескольких сигналов к любой паре сигналов, входящих в этот набор. Однако техника различения многих сигналов может оказаться существенно отличной от техники различения двух сигналов. === Восстановление сигналов === Задача '''восстановления''' сообщения значительно отличается от задач обнаружения и различения сигналов. Она состоит в том, чтобы получить выходной сигнал <math>y(t)</math>, наименее отличающийся от передаваемого сообщения <math>x(t)</math>. При этом существенно, что сообщение <math>x</math> заранее неизвестно; известно лишь, что оно принадлежит к некоторому множеству. При таких условиях можно рассматривать данное сообщение как одну из реализаций некоторого случайного процесса. Следовательно, заранее известными могут быть только распределения или моменты распределения этого процесса. В частности, на приёмной стороне могут быть заранее известны мощность и спектр случайного процесса, реализацией которого является передаваемое сообщение. Борьба с помехами при такой постановке задачи, конечно, более трудна. При восстановлении сообщения нужно опираться на некоторый '''критерий верности''', на основе которого оценивается уклонение выходного сигнала <math>y</math> от передаваемого сообщения <math>x</math>. Этот критерий должен, вообще говоря, выводиться из требований, предъявляемых к передаче данного вида сообщений. Существует несколько критериев верности: # Часто применяется '''критерий квадратичного уклонения'''. Для непрерывных функций, заданных на интервале <math>(a,\;b)</math>, квадратичное уклонение выражается соотношением: #: <math>\varepsilon_2=\int\limits_a^b [x(t)-y(t)]^2\,dt.\qquad\qquad(49)</math> # Можно применить '''критерий абсолютного уклонения''': #: <math>\varepsilon_\mathrm{abs}=\int\limits_a^b |x(t)-y(t)|\,dt.\qquad\qquad(50)</math> # Можно также воспользоваться '''критерием наибольшего уклонения''': #: <math>\varepsilon_{\max}=\max_{a\leqslant t\leqslant b} |x(t)-y(t)|.\qquad\qquad(51)</math> Нет решительно никаких общих оснований для предпочтения одного критерия другому. Критерий квадратичного уклонения применяется особенно часто только потому, что при пользовании этим критерием получаются, как правило, сравнительно простые выкладки. Если получателем сообщения является человек, то критерий верности должен, естественно, выбираться на основе свойств восприятия человеком данного вида сообщений. Так, например, при передаче звука критерий верности должен строиться на основе психофизиологических свойств слуха, а при передаче изображений — на основе свойств зрения. Если непрерывное сообщение <math>x(t)</math> вырабатывается некой телеметрической системой и отображает изменение во времени наблюдаемой физической величины, то критерий верности сводится к точности измерения, требования к которой выводятся из общего назначения данного измерения и условий применения его результатов. == Понятие помехоустойчивости == Основы теории помехоустойчивости заложены В. А. Котельниковым в работе «Теория потенциальной помехоустойчивости»<ref>{{книга|автор=Котельников, В. А.|заглавие=Теория потенциальной помехоустойчивости|место={{М.}}|издательство=Госэнергонздат|год=1956|страниц=152}}</ref> (1956). В этой работе впервые поставлены и решены многие основные задачи и введён ряд фундаментальных понятий. Она с полным основанием считается классическим исследованием проблемы помехоустойчивости. '''Помехоустойчивость технического устройства (системы)''' — способность устройства (системы) выполнять свои функции при наличии помех. Её оценивают интенсивностью помех, при которых нарушение функций устройства ещё не превышает допустимых пределов.<ref>''Кобзарев, Ю. Б.'' Помехоустойчивость / БСЭ. — 3-е изд. — {{М.}}: Большая советская энциклопедия, 1974. — Т. 46.</ref> Эта общая формулировка должна быть уточнена применительно к различным условиям передачи, то есть должна быть установлена количественная мера помехоустойчивости. Прежде всего, помехоустойчивость понимается как свойство системы передачи в целом. Но из-за сложности данной задачи имеет смысл говорить о помехоустойчивости отдельных звеньев системы. Так, можно говорить о помехоустойчивости кодов, о помехоустойчивости видов модуляции, о помехоустойчивости приёмников. При этом часто достаточно оперировать сравнительной или относительной помехоустойчивостью, что позволяет сравнить между собою различные варианты технических решений. Требования к помехоустойчивости различных устройств отличаются большим разнообразием: так, в радиолокационных системах иногда считают допустимым пропуск отдельных радиолокационных станцией (за время однократного обзора контролируемой ею области пространства) до половины объектов, подлежащих обнаружению, а в системах передачи данных, использующих ЭВМ, часто недопустима потеря даже одного передаваемого бита из порядка <math>10^9</math>. Предельно достижимая помехоустойчивость называется, по В. А. Котельникову, '''потенциальной помехоустойчивостью'''. Сравнение фактической помехоустойчивости каждого конкретного устройства с его потенциальной помехоустойчивостью даёт оценку качества устройства и показывает наличие ещё неиспользованных резервов. Действие помехи проявляется в том, что принятый сигнал (а следовательно, и сообщение) отличается от переданного. Поэтому помехоустойчивость можно характеризовать как степень соответствия принятого сигнала (или сообщения) переданному при заданной помехе. Таким образом, при сравнении нескольких систем та из них будет более помехоустойчивой, в которой при одинаковой помехе различие между принятым и переданным сигналами (или сообщениями) будет меньше. Ввести единое количественное определение помехоустойчивости затруднительно, так как критерий соответствия принятого сигнала переданному и характеристики действующей в системе помехи могут в зависимости от условий передачи существенно различаться. Вместе с тем оказывается полезным ввести определение меры соответствия принятого сигнала переданному. С одной стороны, эта мера зависит от помехи, и характеризует помехоустойчивость с необходимой полнотой. С другой стороны, эта мера, взятая не как функция помехи, а как численный показатель системы, работающей в заданных условиях, представляет собой показатель, вполне характеризующий систему с точки зрения потребителя. Для обозначения степени соответствия принятого сообщения переданному используют термин '''верность'''. Количественную меру соответствия выбирают в зависимости от характера сообщения: дискретный или непрерывный. Рассмотрим первый случай. Пусть сообщение представляет собой последовательность символов из некоторого ансамбля (то есть конечного множества, заданного вместе с априорными вероятностями его элементов). В этом случае влияние помехи проявляется в том, что вместо фактически переданного символа принимается какой-либо другой. Такое событие называют '''ошибкой'''. Так как ошибка есть случайное событие, то верность естественно характеризовать вероятностью отсутствия ошибки, то есть вероятностью правильного приёма. Если вероятность ошибки обозначена <math>P_\mathrm{err}</math>, то вероятность правильного приёма : <math>P_\mathrm{pr}=1-P_\mathrm{err}.\qquad\qquad(52)</math> На практике мера верности или, верность выражается положительным числом <math>S</math>, определяемым как: : <math>S=-\mathrm{lg}\,P_\mathrm{err}=-\mathrm{lg}\,(1-P_\mathrm{pr}).\qquad\qquad(53)</math> В случае передачи непрерывных функций нельзя столь же легко ввести количественную меру верности, так как в этом случае нет простой системы событий (ошибка есть — ошибки нет). При передаче непрерывного сообщения отличие принятого сообщения от переданного имеет также непрерывный характер. Поэтому мерой несоответствия или уклонения может служить некоторая величина <math>\varepsilon</math>, представляющая собой расстояние между принятым и переданным сообщениями, или критерий верности, рассмотренный ранее. Количественную меру верности вводят, определив её возрастающей функцией вероятности: : <math>P=P(\varepsilon\leqslant\varepsilon_0),\qquad\qquad(54)</math> то есть вероятности того, что уклонение <math>\varepsilon</math> не превзойдёт некоторой заранее назначенной величины <math>\varepsilon_0</math>. Выясним связь между верностью и отношением «сигнал/помеха». Верность тем ниже, чем больше относительная интенсивность помехи, то есть чем меньше отношение «сигнал/помеха», или верность есть возрастающая функция отношения «сигнал/помеха». Но что отношение «сигнал/помеха» — не единственный фактор, влияющий на верность. Во-первых, при неизменной мощности сигнала можно выбирать разные системы сигналов — строить множество сигналов с различными расстояниями между элементами этого множества. Выбор расстояний должен быть таков, чтобы помеха с заданными свойствами в наименьшей степени влияла на различимость принятых сигналов. В простейшем случае дело сводится к построению системы сигналов с наибольшими расстояниями. Во-вторых, верность зависит от способа приёма, так что она может быть различной при одном и том же отношении «сигнал/помеха». Часто отношение «сигнал/помеха» в некотором звене приёмника больше, чем то же отношение на входе приёмника. Канал же характеризуется именно отношением «сигнал/помеха» на выходе линии, то есть на входе приёмника. Правильно сконструированный приёмник может увеличить отношение «сигнал/помеха», и притом весьма значительно. Как уже было сказано выше, следует говорить о помехоустойчивости отдельных звеньев системы передачи. Под '''помехоустойчивостью кода''' нужно понимать верность при заданном отношении «сигнал/помеха» и при определённом способе приёма. '''Помехоустойчивость системы модуляции''' непосредственно характеризуется относительным изменением модулируемого параметра под действием данной помехи. Можно сравнивать различные системы модуляции по относительному увеличению отношения «сигнал/помеха», даваемому некоторым идеализированным приёмником. '''Помехоустойчивость приёмника''' также удобно выражать относительным увеличением отношения «сигнал/помеха», сравнивая значение этого отношения на выходе звена приемника, производящего основную обработку сигнала, со значением того же отношения на входе приёмника. Более широким понятием, чем помехоустойчивость, является '''помехозащищённость'''. Это способность системы связи противостоять воздействию мощных помех. Помехозащищённость включает в себя скрытность системы связи и ее помехоустойчивость, так как для создания мощных помех надо сначала обнаружить систему связи и измерить основные параметры её сигналов, а затем организовать мощную, наиболее сильнодействующую помеху. Чем выше скрытность и помехоустойчивость, тем выше помехозащищённость системы связи. == Литература == # {{книга|автор=Бойерле, Х. П., Беценар, Г. Бах|заглавие=Коммуникация в технике автоматизации|издание=Пер. с нем|место=Берлин, Мюнхен|издательство=АО Siemens|год=1991|страниц=155|isbn=3-8009-1563-4}}. # {{книга|автор=Варакин, Л. Е.|заглавие=Теория систем сигналов|место={{М.}}|издательство=Советское радио|год=1978|страниц=375}} # {{книга|автор=Гоноровский, И. С.|заглавие=Радиотехнические цепи и сигналы: Учебник для вузов|издание=4-е изд., перераб. и доп|место={{М.}}|издательство=Радио и связь|год=1986|страниц=512}} # {{книга|автор=Гук, М.|заглавие=Аппаратные средства локальных сетей. Энциклопедия|место=Спб.|издательство=Питер|год=2000|страниц=576|isbn=5-8046-0113-X}}. # {{книга|заглавие=Защита от радиопомех|ответственный=Под ред. М. В. Максимова|место={{М.}}|издательство=Советское радио|год=1976|страниц=496}} # {{книга|автор=Зимин, В. В.|заглавие=Промышленные сети: Учеб. пособие для студентов вузов|место=Н. Новгород|издательство=НГТУ им. Р. Е. Алексеева|год=2008|страниц=252|isbn=978-5-93272-554-2}}. # {{книга|автор=Олифер, В. Г., Олифер, Н. А.|заглавие=Компьютерные сети. Принципы, технологии, протоколы: Учебник для вузов|издание=3-е изд|место=СПб.|издательство=Питер|год=2006|страниц=958|isbn=5-469-00504-6}}. # {{книга|автор=Осмоловский, С. А.|заглавие=Стохастические методы передачи данных|место={{М.}}|издательство=Радио и связь|год=1991|страниц=240}} # {{книга|автор=Отт, Г.|заглавие=Методы подавления шумов и помех в электронных системах|ответственный=Пер. с англ|место={{М.}}|издательство=Мир|год=1979|страниц=318}} # {{книга|автор=Скляр, Б.|заглавие=Цифровая связь. Теоретические основы и практическое применение|ответственный=Пер. с англ|издание=2-е изд, испр|место={{М.}}|издательство=Издательский дом «Вильямс»|год=2003|страниц=1104|isbn=5-8459-0497-8}}. # {{книга|автор=Таненбаум, Э.|заглавие=Компьютерные сети|издание=4-е изд|место=Спб.|издательство=Питер|год=2003|страниц=992|isbn=5-318-00492-X}}. # {{книга|автор=Трахтман, А. М., Трахтман, В. А.|заглавие=Основы теории дискретных сигналов на конечных интервалах|место={{М.}}|издательство=Советское радио|год=1975|страниц=208}} # {{книга|автор=Тузов, Г. И.|заглавие=Статистическая теория приёма сложных сигналов|место={{М.}}|издательство=Советское радио|год=1977|страниц=400}} # {{книга|автор=Финк, Л. М.|заглавие=Теория передачи дискретных сообщений|издание=2-е изд., перераб. и доп|место={{М.}}|издательство=Советское радио|год=1970|страниц=728}} # {{книга|автор=Харкевич, А. А.|заглавие=Борьба с помехами|издание=2-е изд., доп. и перераб|место={{М.}}|издательство=Наука|год=1965|страниц=276}} # {{книга|автор=Хармут, Х. Ф.|заглавие=Передача информации ортогональными функциями|место={{М.}}|издательство=Связь|год=1975|страниц=272}} # {{книга|автор=Хелд, Г.|заглавие=Технология передачи данных|издание=7-е изд|место=СПб.|издательство=Питер|год=2003|страниц=720|isbn=5-94723-472-6}}. == Примечания == {{примечания}} qrgu6k0jeadyly8kpvg1jxsm8xciw6v Iptables 0 10981 270435 256788 2026-10-27T07:38:31Z Jcb 79968 270435 wikitext text/x-wiki {{Название учебника |Категория = Программное обеспечение |Тип = Одностраничный |Готовность = 50% }} {{Википедия}} '''iptables''' — утилита командной строки, является стандартным интерфейсом управления работой межсетевого экрана '''{{w |netfilter}}''' для [[w:Ядро Linux|ядер Linux]] версий 2.4, 2.6, 3.x, 4.x. Иногда под словом iptables имеется в виду и сам межсетевой экран netfilter. == История == Изначально разработка netfilter и iptables шла совместно, поэтому в ранней истории этих проектов есть много общего. Подробности см. в статье про {{w |netfilter}}. Предшественниками iptables были проекты {{w |ipchains}} (применялась для администрирования фаервола ядра Linux версии 2.2) и [[ipfwadm]] (аналогично для ядер Linux версий 2.0). Последний был основан на {{w |BSD}}-утилите {{w |ipfw}}. iptables сохраняет идеологию, ведущую начало от ipfwadm: функционирование фаервола определяется набором правил, каждое из которых состоит из критерия и действия, применяемого к пакетам, подпадающим под этот критерий. В ipchains появилась концепция ''цепочек'' — независимых списков правил. Были введены отдельные цепочки для фильтрации входящих (INPUT), исходящих (OUTPUT) и транзитных (FORWARD) пакетов. В продолжении этой идеи, в iptables появились ''таблицы'' — независимые группы цепочек. Каждая таблица решала свою задачу — цепочки таблицы filter отвечали за фильтрацию, цепочки таблицы nat — за преобразование сетевых адресов ({{w |NAT}}), к задачам таблицы mangle относились прочие модификации заголовков пакетов (например, изменение [[w:Time to live|TTL]] или [[w:Тип обслуживания|TOS]]). Кроме того, была слегка изменена логика работы цепочек: в ipchains все входящие пакеты, включая транзитные, проходили цепочку INPUT. В iptables через INPUT проходят только пакеты, адресованные самому хосту. Такое разделение функциональности позволило iptables при обработке отдельных пакетов использовать информацию о соединениях в целом (ранее это было возможно только для NAT). В этом iptables значительно превосходит ipchains, так iptables может отслеживать состояние соединения и перенаправлять, изменять или отфильтровывать пакеты, основываясь не только на данных из их заголовков (источник, получатель) или содержимом пакетов, но и на основании данных о соединении. Такая возможность фаервола называется stateful-фильтрацией, в отличие от реализованной в ipchains примитивной stateless-фильтрации (подробнее о видах фильтрации см. статью о [[w:Межсетевой экран|фаерволах]]). Можно сказать, что iptables анализирует не только передаваемые данные, но и контекст их передачи, в отличие от ipchains, и поэтому может принимать более обоснованные решения о судьбе каждого конкретного пакета. Более подробно о stateful-фильтрации в netfilter/iptables см. [[w:Netfilter#Механизм определения состояний]]. В будущем, разработчики netfilter планируют заменить iptables на [[nftables]] — инструмент нового поколения, пока находящийся в ранней стадии разработки<ref>[http://www.opennet.ru/opennews/art.shtml?num=20843 Разработчики Netfilter представили замену iptables]</ref>. == Архитектура == === Основные понятия === Ключевыми понятиями iptables являются: * '''Правило''' — состоит из ''критерия'', ''действия'' и ''счетчика''. Если пакет соответствует критерию, к нему применяется действие, и он учитывается счетчиком. Критерия может и не быть — тогда неявно предполагается критерий «все пакеты». Указывать действие тоже не обязательно — в отсутствие действия правило будет работать только как счетчик. ** '''Критерий''' — логическое выражение, анализирующее свойства пакета и/или соединения и определяющее, подпадает ли данный конкретный пакет под действие текущего правила. ** '''Действие''' — описание действия, которое нужно проделать с пакетом и/или соединением в том случае, если они подпадают под критерий этого правила. О действиях более подробно будет рассказано ниже. ** '''Счетчик''' — компонент правила, обеспечивающий учет количества пакетов, которые попали под критерий данного правила. Также счетчик учитывает суммарный объем таких пакетов в байтах. * '''Цепочка''' — упорядоченная последовательность правил. Цепочки можно разделить на ''пользовательские'' и ''базовые''. ** '''Базовая цепочка''' — цепочка, создаваемая по умолчанию при инициализации таблицы. Каждый пакет, в зависимости от того, предназначен ли он самому хосту, сгенерирован им или является транзитным, должен пройти положенный ему набор базовых цепочек различных таблиц. <strike>Схема следования пакетов приведена на рисунке.</strike> Кроме того, базовая цепочка отличается от пользовательской наличием «действия по умолчанию» (default policy). Это действие применяется к тем пакетам, которые не были обработаны другими правилами этой цепочки и вызванных из нее цепочек (см. переходы). Имена базовых цепочек всегда записываются в верхнем регистре (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING). ** '''Пользовательская цепочка''' — цепочка, созданная пользователем. Может использоваться только в пределах своей таблицы. Рекомендуется не использовать для таких цепочек имена в верхнем регистре, чтобы избежать путаницы с базовыми цепочками и встроенными действиями. * '''Таблица''' — совокупность ''базовых'' и ''пользовательских'' цепочек, объединенных общим функциональным назначением. Имена таблиц (как и модулей критериев) записываются в нижнем регистре, так как в принципе не могут конфликтовать с именами пользовательских цепочек. При вызове команды iptables таблица указывается в формате <tt>-t имя_таблицы</tt>. При отсутствии явного указания, используется таблица filter. Более подробно таблицы будут рассмотрены ниже. === Принцип работы === Все пакеты пропускаются через определенные для них последовательности цепочек (см. рис.) При прохождении пакетом цепочки, к нему последовательно применяются все правила этой цепочки в порядке их следования. Под применением правила понимается: во-первых, проверка пакета на соответствие критерию, и во-вторых, если пакет этому критерию соответствует, применение к нему указанного действия. Под действием может подразумеваться как элементарная операция (встроенное действие, например, ACCEPT, MARK), так и переход в одну из пользовательских цепочек. В свою очередь, действия могут быть как терминальными, то есть прекращающими обработку пакета в рамках данной базовой цепочки (например, ACCEPT, REJECT), так и нетерминальными, то есть не прерывающими процесса обработки пакета (MARK, TOS). Если пакет прошел через всю базовую цепочку и к нему так и не было применено ни одного терминального действия, к нему применяется действие по умолчанию для данной цепочки (обязательно терминальное). Например, <syntaxhighlight lang="bash"> iptables -F # Очищаем все цепочки таблицы filter iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Ко всем пакетам, которые относятся к уже установленным # соединениям, применяем терминальное действие ACCEPT — принять пакет iptables -P INPUT DROP # В качестве действия по умолчанию для входящих пакетов устанавливаем DROP — блокирование пакета iptables -P OUTPUT ACCEPT # Разрешаем все исходящие пакеты </syntaxhighlight> Теперь цепочка INPUT таблицы filter содержит единственное правило, которое пропускает все пакеты, относящиеся к уже установленным соединениям. Ко всем остальным входящим пакетам будет применено действие по умолчанию — DROP. Цепочка же OUTPUT вообще не содержит правил, поэтому ко всем исходящим пакетам будет применяться действие по умолчанию ACCEPT. Таким образом хост, настроенный согласно этому примеру и подключенный к {{w |Интернет}}у, будет недоступен извне (все попытки установить соединение снаружи блокируются), однако с самого хоста доступ к Интернету будет свободный (исходящие пакеты разрешены, а ответы на них уже относятся к установленным соединениям). === Основные компоненты === ==== netfilter ==== <!-- Пока здесь будет англоязычный оригинал. Постараюсь в ближайшее время перевести — FIXED --> [[Файл:Netfilter-components-ru.svg|600px|thumb|Взаимосвязь основных компонентов netfilter и conntrack]] <!-- Поставил 600, потому что иначе нифига не разглядеть. С удовольствием приму ценные предложения по улучшению верстки для небольших экранных разрешений --> Компонент ядра [[Linux]], обеспечивающий фильтрацию и модификацию трафика. Собственно, именно он и является фаерволом. В состав netfilter входят следующие модули: * '''ip_tables''' — фаервол для протокола [[w:IPv4|IPv4]]. Обеспечивает фильтрацию пакетов, модификацию их заголовков и [[w:NAT|трансляцию сетевых адресов]]. * '''ip6_tables''' — фаервол для протокола [[w:IPv6|IPv6]]. Обеспечивает фильтрацию пакетов и модификацию их заголовков. * '''arp_tables''' — фаервол для протоколов [[w:ARP|ARP]] и [[w:RARP|RARP]]. Обеспечивает фильтрацию и модификацию пакетов. * '''x_tables''' — бэкенд для ip_tables, ip6_tables и arp_tables. В этом модуле определены основные операции для работы с фаерволами «таблично-цепочечной» структуры и их компонентами. * '''ebtables''' — [[w:Ethernet|Ethernet]]-фаервол (префикс eb от Ethernet Bridge). В отличие от трех перечисленных выше фаерволов, работающих с протоколами [[w:Сетевой уровень|сетевого]] и более высоких уровней, ebtables работает на канальном уровне, выполняя фильтрацию и модификацию ethernet-кадров, проходящих через [[w:Сетевой мост|сетевые мосты]], если таковые имеются на хосте. Принципы работы с ip_tables и ip6_tables практически идентичны, с тем небольшим отличием, что в ip6_tables отсутствует таблица nat и соответствующие действия (NAT уже присутствует в ip6tables). В то же время, принципы построения правил в arp_tables и ebtables несколько иные. В частности, arp_tables и ebtables имеют четыре базовых действия — ACCEPT (пропустить), DROP (заблокировать), CONTINUE (продолжить обработку в данной цепочке) и RETURN (прекратить обработку в данной цепочке, вернуть в цепочку уровнем выше). Эти действия могут использоваться отдельно, либо применяться к пакетам после выполнения какого-либо преобразующего действия (например, маркировки). Таким образом, после применения преобразования пакет может быть, скажем, немедленно пропущен фаерволом (ACCEPT), либо будет вынужден проследовать через последующие правила (CONTINUE). Этим arptables и ebtables отличаются от ip_tables и ip6_tables — в последних существует четкое разделение действий на терминальные и нетерминальные, которое нельзя изменить при составлении набора правил, а чтобы, например, пропустить пакет после некоторого нетерминального преобразования, необходимо добавлять дополнительное правило («<tt>iptables ... -j MARK ...; iptables ... -j ACCEPT</tt>» вместо «<tt>ebtables ... -j mark ... --mark-target ACCEPT</tt>»). Также, система conntrack не производит отслеживание соединений для ARP/RARP и Ethernet, поэтому возможности stateful-фильтрации в arp_tables и ebtables отсутствуют (нет критерия conntrack и таблицы raw). В данной статье рассматриваются только аспекты работы с ip_tables и ip6_tables. В их задачи входит: * Классификация пакетов на основе различных критериев. В качестве критерия могут выступать, например, [[w:IP-адрес|IP-адреса]] источника и/или назначения, состояние соединения (новое/уже установленное), [[w:Порт (TCP/IP)|порты]] источника и/или назначения (для протоколов [[w:Транспортный уровень|транспортного уровня]], имеющих порты), вспомогательные значения в заголовках пакетов (скажем, длина пакета, [[w:Type of Service|TOS]], [[w:Time to live|TTL]]) и т. п. Результаты этой классификации используются при решении других задач из данного списка. * Фильтрация входящих (INPUT), исходящих (OUTPUT) и транзитных (FORWARD) пакетов, сводящаяся либо к их пропусканию (ACCEPT), либо к блокированию (DROP или REJECT). Также поддерживаются дополнительные возможности, например, блокирование попыток сканирования портов (DELUDE и CHAOS), эффективное противодействие [[w:DoS-атака|(D)DoS-атакам]] (TARPIT). * Модификация заголовков пакетов и связанной информации. К этому классу задач можно отнести: ** Трансляцию сетевых адресов ([[w:NAT|NAT]]), включая [[w:маскарадинг|маскарадинг]] (SNAT или MASQUERADE), [[w:Трансляция порт-адрес|«проброс»]] адресов и портов (DNAT) и даже целых подсетей (NETMAP). Эта задача касается только модуля ip_tables. Модуль ip6_tables не производит трансляции адресов. ** Изменение различных вспомогательных величин в заголовках пакетов, например, [[w:Type of Service|TOS]], [[w:Time to live|TTL]], [[:en:Maximum Segment Size|TCP MSS]]. ** Установку и изменение маркировки пакетов и соединений. Впоследствии эта маркировка может быть использована системой [[w:iproute2|iproute2]] для [[w:Маршрутизация|маршрутизации]] и [[w:Шейпинг (информатика)|шейпинга]] трафика. * Учет количества обработанных пакетов и их суммарного размера при помощи счетчиков. * Занесение информации о пакетах в [[w:syslog|системный журнал]] (LOG и LOGMARK). * Передача на обработку userspace-[[w:Демон (программа)|демонам]] пакетов целиком (NFQUEUE) либо информации о них (NFLOG), что позволяет решать самый широкий круг задач по фильтрации, модификации и учету трафика. * Внутренние задачи, связанные с обеспечением работы критериев и действий netfilter. Например, сопровождение списков [[w:IP-адрес|IP-адресов]] для критериев recent и hashlimit. ==== iptables ==== Userspace-утилита, через которую [[w:Root|системный администратор]] может управлять {{w |IPv4}}-фаерволом (ip_tables). К ее задачам относятся: * Создание и удаление пользовательских цепочек. * Установка действий по умолчанию для базовых цепочек. * Добавление и удаление правил. * Установка и обнуление счетчиков пакетов и байт. * Просмотр цепочек и правил, а также значений счетчиков. * Проверка корректности задания параметров, определяющих работу критериев и действий. * Вывод справки по использованию критериев (<tt>iptables -m ''критерий'' -h</tt>) и действий (<tt>iptables -j ''действие'' -h</tt>). Также в комплект поставки вместе с iptables обычно входят вспомогательные утилиты, обеспечивающие сохранение (iptables-save) и последующее восстановление (iptables-restore) состояния фаервола, его инициализацию при запуске системы ({{w |init}}-скрипт) и т. п. Сегментом фаервола, отвечающим за фильтрацию {{w |IPv6}}-пакетов (ip6_tables), управляет утилита ip6tables. Так как обычно она поставляется вместе с iptables, имеет похожий синтаксис и выполняет схожие задачи, под термином «iptables» часто подразумевают сразу обе эти утилиты. Также в рамках данного проекта разрабатываются два набора библиотек: * '''libiptc''' — содержит функции, осуществляющие вышеперечисленные операции по управлению цепочками и правилами. Именно с этими функциями и работают утилиты iptables (библиотека libip4tc) и ip6tables (библиотека libip6tc). Приложения, использующие эти библиотеки, могут обращаться к netfilter напрямую, минуя вызов утилит iptables и ip6tables. В качестве примера такого приложения можно назвать [[Perl]]-модуль [http://search.cpan.org/~hawk/IPTables-libiptc-0.18/lib/IPTables/libiptc.pm IPTables::libiptc], предоставляющий доступ к функциям этих библиотек из Perl-{{w |скрипт}}ов. * '''libipq''' — содержит функции, позволяющие пользовательским приложениям принимать [[IP-пакет]]ы на обработку. Отправка со стороны ядра выполняется через модуль ip_queue (ip6_queue для IPv6), что соответствует действию QUEUE. В настоящее время этот механизм [http://netfilter.org/projects/libnetfilter_queue/index.html объявлен устаревшим], и вместо него рекомендуется использовать действие NFQUEUE, работа которого реализуется через модуль ядра nfnetlink_queue и библиотеку libnetfilter_queue. ==== conntrack ==== Компонент netfilter, обеспечивающий отслеживание состояния соединений и классификацию пакетов с точки зрения принадлежности к соединениям, что позволяет netfilter осуществлять полноценную stateful-фильтрацию трафика. Как и netfilter, система conntrack является частью ядра [[Linux]]. К его задачам относятся: * Отслеживание состояний отдельных соединений с тем, чтобы классифицировать каждый пакет либо как относящийся к уже установленному соединению, либо как открывающий новое соединение. При этом понятие «состояние соединения» искусственно вводится для протоколов, в которых оно изначально отсутствует ({{w |UDP}}, {{w |ICMP}}). При работе же с протоколами, поддерживающими состояния (например, {{w |TCP}}), conntrack активно использует эту возможность, тесно взаимодействуя с базовой сетевой подсистемой ядра Linux. * Отслеживание связанных соединений, например, {{w |ICMP}}-ответов на {{w |TCP}} и {{w |UDP}}-пакеты. Более сложный вариант — протоколы, использующие несколько соединений в одной сессии, например, {{w |FTP}}. Для правильной обработки таких протоколов conntrack использует специальные модули (conntrack helpers), которые анализируют трафик и «выхватывают» информацию протокола о новых соединениях (например, порт, на который оно будет открыто), что позволяет обеспечить их корректную фильтрацию, маршрутизацию, шейпинг и пропускание через NAT. Более подробно о возможностях системы conntrack и их использовании при работе с iptables/netfilter см. [[#Механизм определения состояний|чуть ниже]]. В состав conntrack входят следующие компоненты: * Главный модуль nf_conntrack. Реализует базовую функциональность отслеживания соединений, интерфейсы для работы с модулями расширений, а также механизмы отслеживания протоколов {{w |TCP}} и {{w |UDP}}. * Трекеры протоколов [[w:Протоколы сетевого уровня|сетевого уровня]]: nf_conntrack_ipv4 и nf_conntrack_ipv6. Реализуют операции, специфичные для «своих» протоколов ({{w |IPv4}} и {{w |IPv6}} соответственно), а также механизмы отслеживания соответствующих протоколов управляющих сообщений ({{w |ICMP}} и {{w |ICMPv6}} соответственно). * Трекеры протоколов [[w:Транспортный уровень|транспортного уровня]] (кроме {{w |TCP}} и {{w |UDP}}, реализованных в главном модуле): nf_conntrack_proto_sctp ({{w |SCTP}}), nf_conntrack_proto_dccp ({{w |DCCP}}), nf_conntrack_proto_gre ([[w:GRE (протокол)|GRE]]), nf_conntrack_proto_udplite ({{w |UDP Lite}}). * Вспомогательные модули (helpers), обеспечивающие отслеживание протоколов [[w:Протоколы прикладного уровня|прикладного]] и [[w:Сеансовый уровень|сеансового]] уровней: nf_conntrack_ftp, nf_conntrack_irc, nf_conntrack_pptp, nf_conntrack_netbios_ns и т. п. Требуются далеко не для всех протоколов, а только для тех, отслеживание которых требует знания специфики протокола. Например, неоднократно упоминающийся в этой статье протокол {{w |FTP}} использует в одном сеансе два соединения (управляющее соединение и соединение передачи данных), и чтобы корректно отследить соединение передачи данных, необходимо анализировать трафик управляющего соединения и выделять в нем информацию, касающуюся открытия соединения данных. * Модуль nf_nat. Реализует базовую функциональность [[w:NAT|трансляции сетевых адресов]] и [[w:Трансляция порт-адрес|портов]] с учетом информации о соединениях. Также этот модуль содержит механизмы трансляции для протоколов {{w |IPv4}}, {{w |TCP}}, {{w |UDP}} и {{w |ICMP}} ({{w |IPv6}} и {{w |ICMPv6}} не поддерживаются NAT-подсистемой conntrack). * NAT-трекеры протоколов [[w:Транспортный уровень|транспортного уровня]]: nf_nat_proto_sctp, nf_nat_proto_dccp, nf_nat_proto_gre, nf_nat_proto_udplite. * Вспомогательные модули NAT для протоколов [[w:Протоколы прикладного уровня|прикладного]] и [[w:Сеансовый уровень|сеансового]] уровней: nf_nat_ftp, nf_nat_irc, nf_nat_pptp и т. п. * Модуль взаимодействия с userspace через протокол nfnetlink (см. следующий раздел) nf_conntrack_netlink, которому соответствует userspace-библиотека libnetfilter_conntrack. * Кроме того, к conntrack можно условно отнести и модули netfilter, обеспечивающие взаимодействие этих двух подсистем: критерий conntrack (xt_conntrack), действия NOTRACK и CT (xt_NOTRACK и xt_CT), практически все действия [[#Таблица nat|таблицы nat]], а также соответствующие модули (библиотеки iptables/ip6tables): libxt_conntrack, libxt_NOTRACK, libxt_CT и т. п. Для взаимодействия с системой conntrack из userspace разработан комплект [http://conntrack-tools.netfilter.org/ conntrack-tools], содержащий две утилиты: * '''conntrack''' — инструмент, позволяющий [[w:Root|системному администратору]] наблюдать таблицы состояний соединений и взаимодействовать с ними: очищать таблицы целиком, удалять отдельные записи, маркировать соединения вручную (аналог действия CONNMARK), устанавливать [[Тайм-аут (Телекоммуникации)|тайм-ауты]] соединений. Поддерживается фильтрация вывода (например, на основании адресов и/или портов источника и/или назначения), а также вывод в различных форматах, включая {{w |XML}}. Кроме того, данная утилита позволяет отслеживать в реальном времени события системы conntrack, например, открытие новых соединений или изменение состояния существующих. * '''conntrackd''' — демон, обеспечивающий синхронизацию таблиц состояний с другими хостами, что в сочетании с возможностями демона [[keepalived]] позволяет создавать фаерволы на {{w |кластер}}ах высокой доступности (High Availability) — при выходе из строя одного из хостов кластера его соединения будут «подхвачены» другими хостами кластера и корректно обработаны с учетом состояний. Также conntrackd можно использовать просто для удаленного сбора статистики по соединениям. Взаимодействие conntrack с этими программами производится посредством интерфейса nfnetlink, который будет рассмотрен в следующем разделе. ==== nfnetlink ==== Интерфейс, позволяющий различным userspace-приложениям взаимодействовать с netfilter и conntrack. Со стороны userspace он обеспечивается набором библиотек libnfnetlink. Ключевые библиотеки из этого набора: * '''libnetfilter_conntrack''' (ранее libnfnetlink_conntrack и libctnetlink) — обеспечивает взаимодействие приложений с системой conntrack. В качестве примеров приложений, использующих эту библиотеку, можно упомянуть: ** Описанные выше программы '''conntrack''' и '''conntrackd''' из комплекта conntrack-tools. ** '''iptstate''' — в какой-то мере аналог утилиты conntrack, хотя и не имеющий таких богатых возможностей. Предназначена для непрерывного вывода таблицы состояний соединений с периодическим обновлением, в стиле широко известной утилиты {{w |top}}. Поддерживает различные виды сортировки (по адресам/портам источника/назначения, [[Тайм-аут (Телекоммуникации)|тайм-ауту]], счетчикам и т. п.). Позволяет удалять записи из таблицы состояний. Не поддерживает работу с таблицей ожидаемых (expected) соединений. * '''libnetfilter_queue''' (ранее libnfnetlink_queue) — отвечает за передачу пакетов демонам на предмет анализа. По результатам этого анализа пакет может быть заблокирован или пропущен. При пропускании пакета возможна установка или изменение его маркировки (nfmark). Идеологическим предшественником libnetfilter_queue была ныне устаревшая библиотека libipq. В качестве примеров приложений, использующих libnetfilter_queue, можно упомянуть: ** '''nufw''' — фаервол, выполняющий фильтрацию трафика на основе авторизации пользователей. Позволяет устанавливать ограничения на доступ к сетям, находящимся за фаерволом, для отдельных пользователей. Авторизация пользователей на фаерволе обеспечивается отдельным демоном nuauth. Например, в случае, если клиенты используют [[Linux]], авторизация может выполняться совершенно прозрачно, благодаря возможностям {{w |PAM}} (модуль pam_nufw) в момент входа пользователя в систему. Особенно удобны подобные системы в корпоративных сетях, где используются системы централизованного управления аккаунтами пользователей (nufw/nuauth поддерживает {{w |LDAP}} и [[winbind]]). ** '''{{w |l7-filter}}-userspace''' — демон, позволяющий определить протокол [[w:Протоколы прикладного уровня|7-го (прикладного) уровня]] [[w:Сетевая модель OSI|модели OSI]], которому принадлежит полученный пакет, на основании анализа его содержимого при помощи [[Регулярные выражения|регулярных выражений]]. Результат анализа возвращает в маркировке пакета. Полезен при фильтрации и [[w:Шейпинг (информатика)|шейпинге]] трафика протоколов, не имеющих фиксированных номеров портов для соединений данных, например, [[BitTorrent]]. Впрочем, в настоящее время существуют и альтернативные решения — {{w |P2P}}-протоколы можно выделять при помощи критерия ipp2p (из набора xtables-addons), а вспомогательные соединения в известных системе conntrack протоколах ({{w |FTP}}, {{w |IRC}}, {{w |SIP}}) можно выделять при помощи критерия helper и маркировки соединений. ** '''iplist''' — userspace-альтернатива ipset. Как и ipset, позволяет считывать большие списки {{w |IP-адрес}}ов и проверять пакеты на предмет нахождения адреса их источника/назначения в данном списке. В зависимости от результата проверки, пакет может быть пропущен или заблокирован, либо промаркирован соответствующим образом. Разумеется, ipset, работая на уровне ядра, обеспечивает более высокую скорость проверки, а также поддерживает дополнительные возможности, например, динамическое изменение списков при помощи действия SET (добавление и удаление записей), сохранение дополнительной информации (номера [[w:Порт (компьютерные сети)|портов]], {{w |MAC-адрес}}а, [[Тайм-аут (Телекоммуникации)|тайм-ауты]] записей). Несмотря на то, что в настоящий момент ipset пока что не принят в ядро, современные дистрибутивы ipset позволяет произвести сборку и установку необходимых компонентов без необходимости наложения {{w |патч}}ей на ядро и iptables, благодаря возможностям подгружаемых модулей ([[:en:LKM]]) ядра [[Linux]]. Поэтому, с учетом вышесказанного, необходимость в iplist в настоящее время сомнительна. * '''libnetfilter_log''' (ранее libnfnetlink_log) — предоставляет демонам интерфейс для получения служебной информации о пакетах на предмет регистрации и учета трафика. В настоящее время известен только один проект, использующий данную библиотеку — '''ulogd2''' ([netfilter] userspace logging daemon, версия 2). Данный проект находится пока в бета-стадии разработки. Надо заметить, что ulogd2 может получать информацию не только через libnetfilter_log (действие NFLOG), но и через классический механизм libipulog (действие ULOG), а также через libnetfilter_conntrack (данный метод позволяет получать информацию не об отдельных пакетах, а о соединениях в целом). Со стороны ядра взаимодействие обеспечивается базовым модулем nfnetlink и «специализированными» модулями nf_conntrack_netlink, nfnetlink_queue и nfnetlink_log соответственно. Кроме того, такие программы, как nfnl_osf (передает ядру список сигнатур для критерия детекции операционной системы osf) и ipset начиная с версии 5 (см. ниже) также используют для коммуникаций ядро-userspace интерфейс nfnetlink, но эти задачи являются узкоспециализированными и поэтому реализованы без использования специальных библиотек и модулей ядра. ==== ipset ==== Представляет собой набор инструментов, позволяющий работать с большими списками (sets) {{w |IP-адрес}}ов и/или [[w:Порт (компьютерные сети)|портов]]. Поддерживается возможность динамического обновления списков при прохождении пакетов через правила {{w |netfilter}}. В версии ipset 4 и более ранних поддерживалась работа только с семейством адресов {{w |IPv4}}, однако начиная с пятой версии реализована также и поддержка {{w |IPv6}}. Стоит отметить, что долгое время проект ipset существовал вне основной ветки развития [[w:Ядро Linux|ядра Linux]]. В частности, в четвертой версии ipset «ядерные» компоненты приходилось собирать отдельно, используя заголовочные файлы текущего ядра. Однако, после выхода пятой версии, в которой были учтены все предыдущие замечания, началась работа по включению ipset в основную ветку. Она [http://www.spinics.net/lists/netfilter-devel/msg17027.html завершилась успехом]: поддержка ipset присутствует в Linux начиная с 2.6.39. В ходе этих работ протокол взаимодействия ядерной и userspace-частей ipset подвергся значительной переработке, и окончательная версия [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=ipset.git;a=commit;h=d6ee5bb4e5346b84efa33858091ba4add2b26de2 получила] номер 6.0. Таким образом, в современных ядрах поддержка ipset присутствует штатно, а пользователи более старых ядер могут воспользоваться реализациями ipset версий 4 и 5, включенными в набор [http://xtables-addons.sourceforge.net/ xtables-addons]. ipset состоит из следующих элементов: * Модуль ядра ip_set, обеспечивающий базовый инструментарий работы со списками записей, который используется модулями расширений. * Модули расширений, определяющие конкретные структуры записей и методы работы с ними, например, ip_set_hash_ip (тип данных hash: ip), ip_set_bitmap_port (тип данных bitmap: port) и т. д. * Userspace-утилита ipset, позволяющая выполнять различные операции со списками и записями в них: ** Создание, удаление, переименование, вывод, очистка списков. ** Добавление и удаление записей из списков, проверка наличия записи в списке. ** Вывод справочной информации по работе со списками различного типа. * Модули расширений для утилиты ipset, соответствующие модулям расширений в ядре, например, ipset_hash_ip (тип данных hash: ip), ipset_bitmap_port (тип данных bitmap: port) и т. д. Каждый такой модуль отвечает за обеспечение {{w |интерфейс}}а между «своим» модулем ядра и конечным пользователем, в частности, проверку корректности вводимых и форматирование выводимых данных, а также вывод справочной информации по допустимым командам и параметрам. В ранних версиях ipset (до 4 включительно) такие модули выделялись в виде подгружаемых библиотек, однако в современных версиях ipset они статически включаются в основной бинарник, поэтому разделение существует лишь в исходном коде. * Модуль netfilter xt_set (критерий set и действие SET), а также соответствующие модули (библиотеки) iptables (libxt_set и libxt_SET). Критерий set позволяет проверять различные параметры пакета ([[w:IP-адрес|IP]]/{{w |MAC-адрес}}а, {{w |TCP}}/{{w |UDP}}-[[w:Порт (компьютерные сети)|порты]] источника и/или получателя) на предмет нахождения или отсутствия в списке. Действие SET позволяет добавлять или удалять записи из списка на основании указанных параметров пакета. <!-- Отметим, что, начиная с версии iptables 1.4.9 {{w |IPv4}}-специфичные модули libipt_set и libipt_SET [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=commit;h=d40f1628c3717daebc437a398a285e371b5b6f7f заменены] на более универсальные libxt_set и libxt_SET, которые могут использоваться как в iptables, так и в ip6tables. --> ipset поддерживает следующие типы данных (в скобках приведены названия согласно терминологии устаревшей версии ipset 4): * '''bitmap: ip''' (ipmap) — полный перечень {{w |IP-адрес}}ов. * '''bitmap: ip, mac''' (macipmap) — полный перечень IP-адресов, причем вместе с каждым IP-адресом может быть сохранен {{w |MAC-адрес}}. * '''bitmap: port''' (portmap) — полный перечень [[w:Порт (компьютерные сети)|портов]]. * '''hash: ip''' (iphash) — выборочный перечень IP-адресов (либо IP-подсетей с одинаковой маской). * '''hash: net''' (nethash) — выборочный перечень IP-подсетей (блоков IP-адресов). В отличие от hash: ip, в одном списке могут присутствовать подсети с различными масками. * '''hash: ip, port''' (ipporthash) — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт. В версии ipset 4 и более ранних существует ограничение: адреса в пределах одного перечня должны принадлежать одному [[w:Бесклассовая адресация|блоку /16]] (/255.255.0.0, максимум 65536 адресов). Начиная с версии ipset 5, для каждого номера порта можно также сохранять идентификатор протокола [[w:Транспортный уровень|транспортного уровня]]. * '''hash: ip, port, ip''' (ipportiphash) — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт и еще один IP-адрес. В версии ipset 4 и более ранних ограничение на «первичные» адреса (первые в тройке адрес-порт-адрес) такое же, как и для ipporthash. Начиная с версии ipset 5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня. * '''hash: ip, port, net''' (ipportnethash) — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт и IP-подсеть. В версии ipset 4 и более ранних ограничение на «первичные» адреса такое же, как и у типа ipporthash. Начиная с версии ipset 5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня. * '''list: set''' (setlist) — список списков. Может содержать списки любого перечисленного здесь типа, кроме list: set. При обращении к такому объекту из netfilter, включенные в него списки рассматриваются как один большой список. Поиск записей (критерий set) производится по всем вложенным спискам соответствующего типа. При добавлении записей (действие SET), вложенные списки поочередно проверяются (согласно порядку их перечисления) на соответствие типа и наличие свободного места, и запись добавляется в первый же подходящий. В то же время, при обращении к такому списку через утилиту ipset, он рассматривается именно как совокупность элементов-списков, что позволяет добавлять, удалять и проверять наличие именно вложенных списков, но не их элементов. * '''hash: net, iface''' — выборочный перечень IP-подсетей, причем с каждой подсетью может быть сохранено название сетевого интерфейса. Появился в версии ipset 6.7 (входит в [[w:Ядро Linux|Linux]] 3.1), ранние версии ipset не имеют подобных возможностей. Существует ограничение: нельзя сохранять более 64 имен интерфейсов с одним и тем же адресом подсети. Этот тип данных удобен при наличии в системе большого количества сетевых интерфейсов (например, сотен {{w |VLAN}}-интерфейсов). В четвертой версии дополнительно присутствовали два типа списков, упраздненные в более поздних версиях: * '''iptree''' — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранено значение [[Тайм-аут (Телекоммуникации)|тайм-аута]] в секундах. По истечении тайм-аута адрес удаляется из списка. Чтобы активировать возможность использование тайм-аутов для определенного списка, нужно при его создании задать тайм-аут по умолчанию (опция <tt>--timeout</tt>). Начиная с версии ipset 5, данный тип не поддерживается, при попытке его использования автоматически заменяется на hash: ip. Заметим, что начиная с пятой версии тайм-ауты реализованы для всех поддерживаемых типов данных. * '''iptreemap''' — гибридный перечень, позволяющий сохранять адреса, блоки и диапазоны адресов. Начиная с версии ipset 5, данный тип не поддерживается, при попытке его использования автоматически заменяется на hash: ip. Стоит отметить, что в современных версиях ipset при работе с адресами IPv4 можно указывать диапазоны адресов и подсети, которые при обращении к внутренним спискам будут автоматически преобразованы в наборы соответствующих элементов, Например, <tt>ipset create foo hash:ip; ipset add foo 192.168.0.0-192.168.0.3</tt> добавит в список <tt>foo</tt> адреса 192.168.0.0, 192.168.0.1, 192.168.0.2 и 192.168.0.3 (аналогичный эффект может быть достигнут и командой <tt>ipset add foo 192.168.0.0/3</tt>). Практически для всех типов списков, реализованных в ipset, существует общее ограничение на максимальный размер: 65536 записей. Большинство перечисленных типов данных можно разделить на две группы: полные перечни (map, bitmap) и выборочные перечни (hash, tree). Разница между этими типами состоит в следующем: если выборочный перечень сохраняет только те элементы, которые в него входят, то полный перечень представляет собой таблицу логических значений ({{w |бит}}ов) для всех элементов, которые могут входить в данный перечень, и вхождение конкретного элемента в перечень определяется значением соответствующего бита. Полный перечень всегда формируется на базе ''одного непрерывного'' диапазона значений. Таким образом, выбор необходимого вам типа данных определяется конкретными условиями задачи, прежде всего, отношением усредненного количества элементов в списке к требуемому диапазону охвата. Например, если вы собираетесь хранить в списке блэк-листы адресов, замеченных в атаках на ваш сервер, целесообразнее использовать тип hash: ip, потому что атакующие вас ботнеты, как бы они ни были велики, все равно занимают незначительную долю адресного пространства {{w |IPv4}}. К тому же, как следует из сказанного в предыдущем абзаце, тип bitmap: ip все равно не может хранить адреса, выходящие за предел одной подсети [[w:Бесклассовая адресация|префикса 16]]. Но в том случае, если вам, например, нужно задать список хостов из вашей локальной сети, имеющих доступ к каким-либо услугам (службам вашего {{w |сервер}}а, выходу в {{w |Интернет}}), и этот доступ должно иметь значительное количество хостов (а не единицы), то целесообразнее будет использовать bitmap: ip. По поводу хранения адресов подсетей ([[w:Бесклассовая адресация|блоков]] {{w |IP-адрес}}ов) можно сказать следующее. Если вам нужно хранить большое количество блоков одного размера из ограниченного диапазона (не более 65536 возможных значений), например, блоки /24 из подсети /8, вы можете использовать тип bitmap: ip, указав маску. Если же вам нужно хранить блоки одного размера из достаточно широкого диапазона, например, /24 из всего адресного пространства {{w |IPv4}}, используйте тип hash: ip, также с указанием маски. При необходимости хранить в одном списке блоки ''разного'' размера, воспользуйтесь типом hash: net. Что касается улучшений в версиях 5 и 6 по сравнению с четвертой и более ранними, то, помимо уже упомянутых (поддержка адресов {{w |IPv6}}, поддержка [[Тайм-аут (Телекоммуникации)|тайм-аутов]] для всех типов данных, возможность сохранения идентификатора протокола транспортного уровня в типах hash: ip, port, hash: ip, port, ip и hash: ip, port, net), стоит также отметить переход на использование nfnetlink (см. выше) для связи ядра и userspace, а также более простой синтаксис. Например, те действия, которые в ipset 4 выглядели бы так: <syntaxhighlight lang="bash"> ipset -N foo macipmap --network 192.168.0.0/16 # Создаем список ipset -A foo 192.168.1.1,12:34:56:78:9A:BC # Добавляем запись ipset -T foo 192.168.1.1,12:34:56:78:9A:BC # Проверяем ее наличие в списке ipset -L foo # Выводим список на экран (точнее, на stdout) ipset -F foo # Очищаем список ipset -X foo # Удаляем список </syntaxhighlight> в современных версиях ipset будут выглядеть следующим образом: <syntaxhighlight lang="text"> ipset create foo bitmap:ip,mac range 192.168.0.0/16 ipset add foo 192.168.1.1,12:34:56:78:9A:BC ipset test foo 192.168.1.1,12:34:56:78:9A:BC ipset list foo ipset flush foo ipset destroy foo </syntaxhighlight> Кроме того, современные версии ipset поддерживают работу в режиме простой [[w:Командный интерпретатор|оболочки]], принимающей команды со [[stdin]]. При этом в них обеспечивается полная обратная совместимость синтаксиса с четвертой версией, то есть синтаксис, корректно работающий для четвертой версии ipset, будет точно так же работать в пятой и шестой. ==== ipvs ==== Разработанный в рамках проекта [http://www.linuxvirtualserver.org/ Linux Virtual Server] инструментарий для балансировки входящих соединений на [[w:Транспортный уровень|транспортном уровне]], позволяющий создавать отказоустойчивые (highly available, HA) [[w:Кластер (группа компьютеров)|кластеры]] с балансировкой нагрузки. В структуру такого кластера входит один или несколько хостов-балансировщиков (front-end), а также группа хостов-обработчиков (back-end). Хост-балансировщик принимает входящие соединения и перенаправляет их на хосты-обработчики, причем выбор хоста-обработчика осуществляется по специальному алгоритму, обеспечивающему гибкое распределение нагрузки между обработчиками. В кластере также могут присутствовать дополнительные (резервные) балансировщики, которые вступают в игру в случае отказа основного балансировщика. Как правило, IPVS работает в связке с демоном [[keepalived]], который обеспечивает отказоустойчивость балансировщика (с использованием протокола [[:en:VRRP|VRRP]]) и поддержку в актуальном состоянии списка обработчиков (демон периодически проверяет работоспособность обработчиков и выводит из состава кластера неработоспособные хосты). Также допускается «ручное» управление настройками кластера — через программу [[ipvsadm]]. Как уже упоминалось выше, IPVS обеспечивает балансировку нагрузки на транспортном уровне, то есть конфигурационной единицей IPVS является ''кластерная служба''. Она характеризуется адресом ({{w |IPv4}} или {{w |IPv6}}), протоколом транспортного уровня (на данный момент IPVS поддерживает протоколы {{w |TCP}}, {{w |UDP}} и {{w |SCTP}}) и номером [[w:Порт (компьютерные сети)|порта]]. Обычно для кластерных служб выделяется отдельный адрес, который присваивается активному (на данный момент) балансировщику. В случае его отказа, адрес автоматически передается резервному балансировщику, и кластер продолжает работу. Обратите внимание, что обеспечением отказоустойчивости занимается не IPVS, а keepalived. Впрочем, использование keepalived не является строго обязательным — существуют и альтернативные подходы, например, встраивание IPVS в кластерный стек [http://linux-ha.org/ Linux-HA] (см. [[:en:Heartbeat (program)|Heartbeat]]). В том случае, если отказоустойчивость не критична (требуется только балансировка нагрузки), можно вообще обойтись без дополнительного демона, выполняя всю настройку через ipvsadm. Для перенаправления пакетов на выбранный обработчик, IPVS может использовать один из следующих методов: * '''Прямая {{w |маршрутизация}} (gatewaying)''' — применяется в том случае, если между балансировщиком и обработчиками отсутствуют {{w |маршрутизатор}}ы, то есть они находятся в одном сегменте сети. В этом случае адрес назначения в заголовке пакетов сохраняется неизменным («кластерный» адрес), подменяются лишь {{w |MAC-адрес}}а назначения при отправке [[w:Кадр (телекоммуникации)|кадров]] с этими пакетами. * '''[[w:Инкапсуляция (компьютерные сети)|Инкапсуляция]] IPIP''' — модификация предыдущего метода на тот случай, когда балансировщик и обработчики находятся в разных сегментах сети. При помощи инкапсуляции IP-в-IP создаются [[w:Туннелирование (компьютерные сети)|сетевые туннели]], которые объединяют балансировщик и обработчик в один сегмент виртуальной сети. * '''{{w |Маскарадинг}} ({{w |NAT}})''' — наиболее гибкое и универсальное решение: балансировщик подменяет адреса/порты назначения проходящих пакетов на реальные адреса/порты обработчиков ({{w |трансляция порт-адрес}}). При этом обеспечивается как простота настройки (не нужно поднимать дополнительные адреса на обработчиках и туннели между балансировщиком и обработчиком), так и гибкость (целевой порт обработчика может отличаться от порта кластерной службы, что невозможно в рамках других методов). Недостатком данного метода является несколько большее потребление системных ресурсов (трансляция адресов является довольно ресурсоемкой задачей). В настоящее время существует довольно обширная библиотека алгоритмов балансировки нагрузки между обработчиками: * '''rr (round robin)''' — классическая [[w:Round-robin (алгоритм)|кольцевая схема]], когда все обработчики получают новые соединения поочередно. * '''wrr (weighted round robin)''' — модификация кольцевой схемы на тот случай, когда одни сервера могут обрабатывать больше соединений, чем другие. Такие сервера включаются в один проход очереди по нескольку раз, и соответственно получают больше соединений. * '''lc (least-connection)''' — новое соединение передается тому серверу, который на текущий момент обрабатывает наименьшее число соединений. * '''wlc (weighted least-connection)''' — модификация предыдущего метода на случай, когда возможности серверов отличаются. При выборе нового сервера сравниваются не непосредственно количества открытых соединений, а отношения количества соединений к весовому коэффициенту (весу) обработчика (который и характеризует его возможности). * '''lblc (locality-based least-connection)''' — формирует привязку обработчиков к кластерному адресу назначения (их может быть несколько). В том случае, если для запрошенного адреса такой привязки еще нет, или привязанный обработчик сильно перегружен ­— выбирает (по алгоритму lc) и привязывает новый обработчик. * '''lblcr (locality-based least-connection with replication)''' — несколько усложненный вариант предыдущего алгоритма. К каждому кластерному адресу привязывается группа обработчиков, которая периодически обновляется (исключаются наиболее нагруженные обработчики, вместо них включаются наименее нагруженные). * '''dh (destination hashing)''' — обеспечивает жесткую, неуправляемую привязку обработчиков к кластерным адресам назначения (выбор обработчика производится исключительно на основании элементарных арифметических операций над кластерным адресом и ''никак не учитывает'' загруженности обработчиков). Может привести к перегрузкам отдельных обработчиков — в этом случае кластер просто перестает обслуживать соответствующий адрес. В такой ситуации нужно либо увеличить лимит соединений на обработчик, либо выбрать другой алгоритм. * '''sh (source hashing)''' — аналогично dh, но обработчики привязываются к адресам клиентов. Как и dh, в случае перегрузки прекращает обслуживание. Отметим, что для формирования ''временных'' привязок обработчиков к адресам клиентов целесообразнее использовать механизм устойчивых соединений (persistent connections), доступный для всех алгоритмов. * '''sed (shortest expected delay)''' — выбирает сервер с наименьшей ожидаемой задержкой ответа. Эта задержка определяется как отношение числа обрабатываемых соединений плюс единица к весу обработчика. Таким образом, этот метод по принципу близок к wlc (отличается лишь прибавлением единицы к числителю сравниваемой величины, что немного меняет влияние веса обработчика на выбор). * '''nq (never queue)''' — пытается передать новое соединение обработчику, который в данный момент не обрабатывает других соединений. Если все обработчики уже заняты, использует предыдущий алгоритм (sed). Для отслеживания соединений к кластерным службам IPVS использует собственную систему трекинга соединений, более примитивную, но менее ресурсоемкую, нежели классический conntrack. При этом поддерживается экспорт информации о кластерных соединениях в conntrack, в целях обеспечения их корректной обработки фаерволом и трансляции адресов (при трансляции адресов используются штатные средства netfilter). Однако, для корректной обработки протоколов, использующих связанные соединения (например, {{w |FTP}}), IPVS использует возможности conntrack. Синхронизация таблицы соединений между основным и дублирующими балансировщиками полностью реализована на уровне ядра (для сравнения, в conntrack эту задачу выполняет userspace-демон conntrackd). === Механизм определения состояний === Важной особенностью iptables/{{w |netfilter}} является механизм определения состояний (connection tracking, nf_[[conntrack]]) — специальная подсистема, отслеживающая состояния соединений и позволяющая использовать эту информацию при принятии решений о судьбе отдельных пакетов. Наличие этого механизма делает netfilter полноценным stateful-фаерволом. Определение состояния соединения порой бывает довольно сложной задачей. Скажем, в случае {{w |TCP}} все относительно просто — контроль состояний реализован средствами самого протокола, установлены специальные процедуры открытия и закрытия соединения. А вот в протоколе {{w |UDP}} для этого специальных процедур не предусмотрено, поэтому UDP-соединением с точки зрения [[conntrack]] является поток пакетов, следующих с интервалом, не превышающим заданный тайм-аут ({{w |sysctl}}-параметр <tt>net.netfilter.nf_conntrack_udp_timeout</tt>, по умолчанию 30 секунд), с одного и того же порта одного хоста, на один и тот же порт другого хоста. Заметим, что классификация пакетов по отношению к соединениям, реализуемая системой conntrack, во многих случаях отличается от официального описания сетевых протоколов. Например, с точки зрения критерия conntrack, TCP-пакет SYN/ACK (отвечающий на SYN) — уже часть существующего сеанса, а по определению TCP такой пакет — всего лишь элемент открытия сеанса. Существует также понятие «связанных соединений». Например, когда в ответ на {{w |UDP}}-пакет с нашего хоста удаленный хост отвечает {{w |ICMP}}-пакетом icmp-port-unreachable, формально этот ответ является отдельным соединением, так как использует совсем другой протокол. {{w |netfilter}} отслеживает подобные ситуации и присваивает таким соединениям статус «связанных» (RELATED), позволяя корректно пропускать их через фильтры фаервола. Более сложный вариант связанного соединения — соединение данных в пассивном режиме {{w |FTP}}. FTP-сервер самостоятельно выбирает порт для прослушивания из достаточно большого диапазона, и сообщает номер порта клиенту через управляющее соединение, после чего клиент подключается к этому порту и передает данные. {{w |netfilter}}, а точнее модуль conntrack_ftp, выделяет в потоке данных управляющего соединения нужный номер порта, что позволяет корректно определить новое соединение как связанное и, соответственно, корректно пропустить его через правила фильтрации. В некоторых случаях целесообразно отключить отслеживание состояния соединений. Например, если ваш сервер находится под [[w:DoS-атака|(D)DoS-атакой]] типа флуд, и вам удалось локализовать ее источники, отслеживать соединения с атакующих хостов и тратить для этого ресурсы своей системы явно не имеет смысла. В подобных случаях используется действие NOTRACK, применяемое в [[#Таблица raw|таблице raw]]. Ниже кратко перечислены возможности, предоставляемые системой отслеживания состояний: ==== Критерий состояния соединения ==== При помощи [[#conntrack 2|критерия conntrack]] вы можете классифицировать пакеты на основании их отношения к соединениям. В частности, состояние NEW позволяет выделять только пакеты, открывающие новые соединения, состояние ESTABLISHED — пакеты, принадлежащие к установленным соединениям, состоянию RELATED соответствуют пакеты, открывающие новые соединения, логически связанные с уже установленными (например, соединение данных в пассивном режиме {{w |FTP}}). Состояние INVALID означает, что принадлежность пакета к соединению установить не удалось. Например, одним простым правилом <syntaxhighlight lang="bash"> iptables -I INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT </syntaxhighlight> вы можете обеспечить корректное пропускание всех входящих пакетов, принадлежащих установленным соединениям, и сконцентрироваться только на фильтрации новых соединений. Заменив в предыдущем правиле <tt>ESTABLISHED</tt> на <tt>ESTABLISHED,RELATED</tt> и подгрузив соответствующие модули ядра, вы автоматически обеспечите корректную фильтрацию протоколов, использующих связанные соединения — {{w |FTP}}, {{w |SIP}}, {{w |IRC}}, {{w |H.323}} и других. Такое простое (с точки зрения пользователя) решение сложной (с технической точки зрения) проблемы является безусловным достоинством фаервола {{w |netfilter}} и ядра [[Linux]] в целом. Более подробно об использовании этого критерия вы можете почитать [[#conntrack 2|ниже]]. Кроме критерия conntrack, стоит упомянуть и его идеологического предшественника — [[#state|критерий state]]. Изначально для определения состояния соединения использовался именно он, то есть вместо <tt>-m conntrack --ctstate ESTABLISHED,RELATED</tt> использовалось <tt>-m state --state ESTABLISHED,RELATED</tt>. Подобные формулировки до сих пор сохраняются во многих руководствах по iptables. Однако в настоящее время критерий state считается устаревшим, и разработчики iptables [http://jengelh.medozas.de/documents/Perfect_Ruleset.pdf рекомендуют] использовать вместо него критерий conntrack. Также заметим, что критерий conntrack обладает более широкими возможностями, нежели state, и позволяет использовать дополнительную информацию о соединении, в частности, состояние самого соединения (ctstatus), факт применения к нему [[w:NAT|трансляции адресов]], тайм-аут для «повисших» соединений (ctexpire) и т. п. ==== Маркировка соединений ==== Этот прием позволяет классифицировать соединение в целом на основании информации об отдельном пакете. Выделив этот пакет, вы применяете к нему действие CONNMARK, и выбранную вами маркировку автоматически приобретают все пакеты в соединении. Впоследствии вы можете, например, модифицировать эти пакеты каким-либо образом, или использовать эту маркировку для [[w:Маршрутизация|маршрутизации]] или [[w:Шейпинг (информатика)|шейпинга]] пакетов. Таким образом, вы оперируете с соединением как с единым целым. Более того, эта маркировка автоматически копируется и на соединения, связанные с текущим. ==== [[w:NAT|Трансляция сетевых адресов]] ==== В операциях NAT, производимых с помощью iptables, отслеживание состояний используется автоматически. Вам достаточно указать критерии, под которые подпадет лишь первый пакет в соединении — и трансляция адресов будет применена ко всем пакетам в этом соединении, а также в связанных с ним соединениях. ==== Использование статистики по соединениям ==== Применяя критерий connbytes, вы можете контролировать количество байт или пакетов, переданных по каждому конкретному соединению. В простейшем случае этот механизм может использоваться, скажем, для назначения квот. Более сложный пример — шейпинг пакетов в зависимости от «весовой категории» соединения (ставить пониженный приоритет загрузкам больших файлов). Этот критерий рассмотрен ниже, в разделе [[#Лимитирующие критерии|лимитирующие критерии]]. ==== Ограничение количества соединений ==== Используя критерий connlimit, вы можете ограничивать количество одновременно открытых {{w |TCP}}-соединений с каждого хоста или подсети на ваш сервер, что позволяет обеспечить эффективную защиту от [[w:DoS-атака|DoS-атак]] или просто некорректно работающего клиентского [[w:Программное обеспечение|ПО]]. Этот критерий рассмотрен ниже, в разделе [[#Лимитирующие критерии|лимитирующие критерии]]. ==== Отслеживание информации о соединениях ==== Пользователь (точнее, [[w:Root|системный администратор]]) или его процессы могут непосредственно наблюдать таблицу контроля состояний, считывать статистику по передаче данных, а также модифицировать эту таблицу (например, удалять из нее соединения). Для этого существуют специальные утилиты, такие как [[conntrack (Программа)|conntrack]] или [[iptstate]]. Впрочем, можно читать информацию и напрямую из псевдофайлов <tt>/proc/net/nf_conntrack</tt> и <tt>/proc/net/nf_conntrack_expect</tt>. == Действия == === Переходы === Для организации перехода пакета из текущей цепочки в другую (определенную пользователем), просто используйте действие <tt>-j имя_цепочки</tt>. В случае применения в этой цепочке к пакету действия RETURN (см. ниже), пакет вернется в исходную цепочку и продолжит ее прохождение начиная со следующего правила (для базовой цепочки к пакету сразу будет применено действие по умолчанию). Также, существует довольно редко используемое действие «безвозвратного перехода» <tt>-g имя_цепочки</tt>. В таком случае, после прохождения пакетом этой цепочки либо при применении в этой цепочке к пакету действия RETURN, пакет вернется к месту последнего перехода по <tt>-j</tt>. Если таких переходов не было, к пакету сразу будет применено действие по умолчанию для базовой цепочки. Заметим, что нельзя перейти в любую встроенную цепочку из любой другой, а также в цепочку, определенную в другой таблице (так как это даже нельзя указать параметрами). Но в пользовательских можно переходить в текущую цепочку (но не желательно во избежание зацикливания). === Встроенные действия === Как уже было сказано выше, каждое встроенное действие реализует какую-либо одну операцию, например, ACCEPT пропускает пакет, MARK меняет его маркировку, MASQUERADE обеспечиват {{w |маскарадинг}} соединения. Наиболее общими действиями являются: * '''ACCEPT''', '''DROP''' и '''REJECT''' — базовые операции фильтрации. Более подробно они рассмотрены ниже, при описании таблицы filter. * '''RETURN''' — обеспечивает возврат из текущей цепочки. В частности, если из цепочки A правилом номер 3 пакет был направлен в цепочку B, то применение к нему в цепочке B действия RETURN приведет к его переходу обратно в цепочку A, и он продолжит ее прохождение со следующего правила (номер 4). Для базовой цепочки к пакету сразу будет применено действие по умолчанию. Например, предположим, что нам нужно обеспечить доступ к определенным [[w:Порт (компьютерные сети)|портам]] нашего сервера для всех хостов из подсети 10.134.0.64/26, ''кроме'' 10.134.0.67 и 10.134.0.100. <syntaxhighlight lang="bash"> iptables -F # Очищаем все цепочки таблицы filter iptables -N our_subnet # Создаем специальную цепочку для проверки пакетов из нашей подсети iptables -A our_subnet -s 10.134.0.67 -j RETURN # Запрещенный хост — выходим iptables -A our_subnet -s 10.134.0.100 -j RETURN # Запрещенный хост — выходим # Всем остальным разрешаем доступ к нужным портам iptables -A our_subnet -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT iptables -A our_subnet -p udp -m multiport --dports 53,123,137,138 -j ACCEPT iptables -A our_subnet -p icmp --icmp-type 8 -j ACCEPT # Разрешаем пакеты по уже установленным соединениям iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Все пакеты из нашей подсети отправляем на проверку iptables -A INPUT -s 10.134.0.64/26 -j our_subnet iptables -P INPUT DROP # Что не разрешено — то запрещено iptables -P OUTPUT ACCEPT # На выход — можно все </syntaxhighlight> Теперь все новые входящие пакеты, отправленные из нашей подсети 10.134.0.64/26, отправляются на проверку в цепочку <tt>our_subnet</tt>. К пакетам с «запрещенных» хостов применяется операция RETURN, и они покидают эту цепочку и впоследствии блокируются действием по умолчанию цепочки INPUT. Пакеты с остальных хостов этой подсети пропускаются в том случае, если они адресованы на порты [[w:Прокси-сервер|прокси]] (8080/tcp), {{w |SSH}} (22/tcp), {{w |SMB}} (139,445/tcp, 137,138/udp), {{w |DNS}} (53/tcp, udp), {{w |NTP}} (123/udp). Также для этих хостов разрешены {{w |ICMP}}-эхо-запросы (пинги). Все остальные пакеты (включая пакеты не из нашей подсети, пакеты с запрещенных хостов и пакеты на неразрешенные порты) блокируются действием по умолчанию DROP. Нетрудно заметить, что в нашем простом примере вместо RETURN можно было использовать и DROP. Однако, существует понятие «принципа одного запрета». При организации фильтрующих правил в рамках этого принципа, сначала следует серия разрешающих правил, исключения оформляются в виде RETURN, а все не разрешенные пакеты доходят до конца базовой цепочки и блокируются действием по умолчанию либо последним правилом. Следование этому принципу позволяет достичь гибкости в выборе и смене метода блокирования пакетов. Допустим, вы хотите сменить блокирующее действие DROP на REJECT. Нет ничего проще — просто меняете правило по умолчанию. Так же просто вводятся специфические методы блокировки для TCP, например, REJECT <tt>--reject-with tcp-reset</tt> или DELUDE — достаточно просто добавить это действие (вместе с указанием протокола <tt>-p tcp</tt>) в конец цепочки. Все не-TCP пакеты при этом будут по-прежнему блокироваться действием по умолчанию. Впрочем, изложенный принцип теряет первоначальный смысл, если в разных случаях нужно обеспечить разные способы блокирования. Рассмотрим чуть более сложный пример: допустим, наш сервер подключен к локальной сети 10.0.0.0/8. В ней есть некий «недоверенный» сегмент, скажем, 10.122.0.0/16, для которого нужно полностью заблокировать доступ к нашему серверу. Но в этом сегменте есть несколько «хороших» хостов (скажем, 10.122.72.11 и 10.122.180.91), которые блокировать не нужно. Поставленную задачу можно решить следующим образом: <syntaxhighlight lang="bash"> iptables -F # Очищаем все цепочки таблицы filter iptables -N check_untrusted # Создаем специальную цепочку для проверки пакетов из нашей подсети iptables -A check_untrusted -s 10.122.72.11 -j RETURN # Разрешенный хост — выходим iptables -A check_untrusted -s 10.122.180.91 -j RETURN # Разрешенный хост — выходим iptables -A check_untrusted -j DROP # Остальных — молча игнорируем # Разрешаем пакеты по уже установленным соединениям iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Пакеты из недоверенной подсети проверяем по списку iptables -A INPUT -s 10.122.0.0/16 -j check_untrusted # Всем остальным разрешаем доступ к нужным портам iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT iptables -A INPUT -p udp -m multiport --dports 53,123,137,138 -j ACCEPT iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT # «Хорошим» хостам, обращающимся на неправильные TCP-порты, вежливо сообщаем об отказе iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset # Для всех остальных протоколов используем стандартный REJECT с icmp-port-unreachable iptables -P INPUT REJECT iptables -P OUTPUT ACCEPT # На выход — можно все </syntaxhighlight> Заметим, что в данном примере хосты из недоверенного сегмента блокируются «молча» (DROP), в то время как при обращении «хороших» хостов на неправильные порты сервер вежливо сообщает им об отказе (REJECT). Этот принцип также является очень важным при построении фаерволов — чем меньше информации попадает к потенциальному злоумышленнику, тем лучше, поэтому на опасных направлениях целесообразно использовать «молчаливое» блокирование, в то время как явные сообщения для «своих» упрощают диагностику работы сети и поиск ошибок. : ''Примечание: следующий пример планируется к переносу в еще не написанный раздел статьи (Прочие критерии → mac)''. Например, предположим, что у нас есть объединенная через один [[w:Сетевой коммутатор|свитч]] подсеть 10.134.0.64/26, к которой наш компьютер подключен через интерфейс eth1. Тогда защиту от {{w |спуфинг}}а (подделки адресов отправителя) через проверку {{w |MAC-адрес}}а можно обеспечить следующим образом: <syntaxhighlight lang="bash"> sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик iptables -F # Очищаем все цепочки таблицы filter iptables -N check_ours_sp00f # Создаем цепочку, в которой будут проверяться MAC-адреса iptables -A check_ours_sp00f -s 10.134.0.67 -m mac --mac-source 00:1D:60:2E:ED:A5 -j RETURN iptables -A check_ours_sp00f -s 10.134.0.68 -m mac --mac-source 00:1D:60:2E:ED:CD -j RETURN iptables -A check_ours_sp00f -s 10.134.0.69 -m mac --mac-source 00:1D:60:2E:ED:D7 -j RETURN iptables -A check_ours_sp00f -s 10.134.0.70 -m mac --mac-source 00:1D:60:2E:ED:E0 -j RETURN # Аналогичным образом проверяем все адреса нашей подсети # И в конце обязательно добаляем правило для НЕпрошедших проверку iptables -A check_ours_sp00f -j DROP iptables -N check_ours # Создаем цепочку, которая будет описывать логику работы с нашей подсетью iptables -A check_ours ! -i eth1 -j DROP # С других интерфейсов пакеты от них прийти не могут iptables -A check_ours -j check_ours_sp00f # Прогоняем их через проверку на спуфинг iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Как обычно, пропускаем все, что идет по установленным соединениям iptables -A INPUT -s 10.134.0.64/26 -j check_ours # Тех, кто претендует на звание своих, прогоняем через проверку # Прошедшим проверку разрешаем пользоваться нащей проксёй и самбой, а также соединяться по ssh iptables -A INPUT -s 10.134.0.64/26 -m multiport --dports 22,8080,139,445 -j ACCEPT iptables -P INPUT DROP # Остальных блокируем iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Как обычно, пропускаем все, что идет по установленным соединениям iptables -A FORWARD -s 10.134.0.64/26 -j check_ours # Проверка iptables -A FORWARD -s 10.134.0.64/26 -j ACCEPT # Прошедшим проверку разрешаем передавать через нас транзитный трафик iptables -P FORWARD DROP # Остальных блокируем iptables -P OUTPUT ACCEPT # Исходящий трафик разрешаем </syntaxhighlight> <!--В демонстрационных целях этот пример был слегка упрощён (вместо повтора правил с критерием <tt>-s 10.134.0.64/26</tt> эти правила логичнее было бы вынести в отдельные цепочки) но, тем не менее, наглядно показывает принципы работы действия RETURN.--> Все новые входящие пакеты с обратным адресом из подсети 10.134.0.64/26 проходят двойную проверку в цепочке <tt>check_ours</tt>. Первый этап проверки — соответствие интерфейса. Ведь к нашей подсети, по условию задачи, мы подключены только интерфейсом eth1. Если пакет якобы из этой подсети придет с любого другого интерфейса, он будет заблокирован. Второй этап проверки заключается в последовательном чтении списка соответствующих [[w:IP-адрес|IP]]- и {{w |MAC-адрес}}ов (цепочка <tt>check_ours_sp00f</tt>). Каждое правило этой цепочки, кроме последнего, выделяет пакеты от одного конкретного хоста нашей подсети. К пакетам, прошедшим проверку, применяется операция RETURN, выводящая пакет из этой цепочки. Если же пакет не подошел ни по одному из этих правил, он считается не прошедшим проверки и блокируется последним правилом <tt>-j DROP</tt>. Для прошедших же проверку пакетов дальнейшая судьба зависит от того, кому они адресованы. Если они идут через наш хост в другие подсети, то они пропускаются. Если же они адресованы непосредственно нашему хосту, то пропускаются только соединения на некоторые {{w |TCP}}-[[w:Порт (компьютерные сети)|порты]] ([[w:Прокси-сервер|прокси]], {{w |SSH}}, {{w |SMB}}). * '''LOG''' — позволяет записывать информацию о пакетах в журнал ядра (см. {{w |syslog}}). Например, если в предыдущем примере перед строкой <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT </syntaxhighlight> мы добавим строку <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j LOG --log-level INFO --log-prefix "New connection from ours: " </syntaxhighlight> то для каждого нового соединения к нашему хосту из нашей подсети в системном журнале будет появляться запись примерно такого вида: Jul 16 20:10:40 interdictor kernel: New connection from ours: IN=eth0 OUT= MAC=00:15:17:4c:89:35:00:1d:60:2e:ed:a5:08:00 SRC=10.134.0.67 DST=10.134.0.65 LEN=48 TOS=0x00 PREC=0x00 TTL=112 ID=38914 DF PROTO=TCP SPT=31521 DPT=8080 WINDOW=65535 RES=0x00 SYN URGP=0 Такая запись содержит очень много полезной информации. Начинается она с даты и времени получения пакета. Затем идет имя нашего хоста (interdictor) и источник сообщения (для сообщений фаервола это всегда ядро). Потом идет заданный нами префикс (<tt>New connection from ours:</tt>), после чего следуют данные о самом пакете: входящий интерфейс (определен для цепочек PREROUTING, INPUT и FORWARD), исходящий интерфейс (определен для цепочек FORWARD, OUTPUT и POSTROUTING), далее — сцепленные вместе {{w |MAC-адрес}}а источника и назначения (сначала идет адрес назначения, в данном случае это наш интерфейс eth1 с маком 00:15:17:4C:89:35, затем адрес источника, в нашем случае это 00:1D:60:2E:ED:A5, и в конце следует значение [[:en:EtherType|EtherType]], 08:00 соответствует протоколу {{w |IPv4}}<ref>Если кратко, EtherType указывает тип протокола, инкапсулированного в {{w |Ethernet}}-[[w:Кадр (телекоммуникации)|кадр]]. При работе с iptables это значение будет всегда равно 08:00 (протокол {{w |IPv4}}), при работе с ip6tables — 86:DD ({{w |IPv6}}). Полный список EtherTypes доступен [https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml#ieee-802-numbers-1 на сайте IANA], список поддерживаемых netfilter’ом — в файле /etc/ethertypes, который в большинстве дистрибутивов находится в пакете {{w |ebtables}}.</ref>), потом {{w |IP-адрес}}а источника (10.134.0.67) и получателя (10.134.0.65, это наш хост), а затем идет различная техническая информация. Например, протокол ({{w |TCP}}), [[w:Порт (компьютерные сети)|порты]] источника и назначения (31521 и 8080 соответственно), [[w:Тип обслуживания|TOS]] и [[w:Time to live|TTL]], длина пакета (48 байт), наличие флага SYN и т. д. Указав соответствующие параметры действия LOG, можно дополнить эту информацию [[w:TCP#Номер последовательности|номером TCP-последовательности]] (опция <tt>--log-tcp-sequence</tt>), выводом включенных опций протоколов TCP (опция <tt>--log-tcp-options</tt>) и {{w |IP}} (<tt>--log-ip-options</tt>), а также идентификатором пользователя, процесс которого отправил данный пакет (<tt>--log-uid</tt>, имеет смысл только в цепочках OUTPUT и POSTROUTING). Параметр <tt>--log-prefix</tt> позволяет задать поясняющую надпись, упрощающую поиск сообщений в системных журналах. Параметр <tt>--log-level</tt> определяет уровень важности лог-сообщения, от которого зависит, в частности, в какой именно из журналов будет записано это сообщение. За более подробными сведениями обратитесь к документации по вашему [[w:Syslog|демону системного лога]]. * '''LOGMARK''' — специальная модификация действия LOG, реализованная в комплекте xtables-addons. Отличается тем, что заносит в лог информацию, специфичную для системы [[conntrack]], в частности, маркировку соединения (connmark aka ctmark), состояния соединения (ctstate и ctstatus) и т. п. Например: Jul 16 20:10:40 interdictor kernel: New connection from ours: iif=1 hook=INPUT nfmark=0x0 secmark=0x0 classify=0x0 ctdir=ORIGINAL ct=0xf5436bcc ctmark=0x0 ctstate=NEW ctstatus= <tt>iif</tt> показывает внутренний идентификатор интерфейса, через который прошел пакет (1 в данном случае соответствует eth0, 0 — lo), <tt>hook</tt> — имя цепочки, из которой было вызвано действие LOGMARK, <tt>nfmark</tt> — маркировку пакета (mark), <tt>secmark</tt> — контекст безопасности {{w |SELinux}} данного пакета (secmark), <tt>classify</tt> — класс шейпера (также известный как <tt>skb->priority</tt>, соответствует обычной для [[w:Iproute2|tc]] форме записи ''MAJOR'':''MINOR'' согласно формуле <tt>skb->priority == ''MAJOR'' << 16 | ''MINOR''</tt>), <tt>ctdir</tt> — направление передачи информации с точки зрения conntrack, <tt>ct</tt> — внутренний идентификатор соединения в системе conntrack (точнее говоря, адрес в памяти, по которому расположена структура, хранящая информацию о соединении), <tt>ctmark</tt> — маркировку соединения (connmark), <tt>ctstate</tt> — состояние соединения, <tt>ctstatus</tt> — статус соединения в системе cоnntrack. Более подробно о параметрах ctdir, ctstate и ctstatus вы можете прочитать [[#conntrack|ниже]], в описании критерия conntrack. Здесь же ограничимся замечаниями, что «<tt>ctstate=NEW ctstatus=</tt>» соответствует первому пакету в соединении, «<tt>ctstate=ESTABLISHED ctstatus=SEEN_REPLY,CONFIRMED</tt>» — второму и нескольким последующим пакетам, «<tt>ctstate=ESTABLISHED ctstatus=SEEN_REPLY,ASSURED,CONFIRMED</tt>» — пакетам в полностью установленном соединении, «<tt>ct=NULL ctmark=NULL ctstate=INVALID ctstatus=NONE</tt>» — пакету, который не удалось отнести к существующим соединениям, «<tt>ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE</tt>» — пакету, для которого была отключена трассировка conntrack (обычно это выполняется действием NOTRACK в таблице raw, см. [[#Таблица raw|ниже]]). Таким образом, в сочетании с традиционным LOG, действие LOGMARK позволяет заносить в системный журнал исчерпывающую информацию о пакетах и соединениях. Заметим, что LOGMARK принимает описанные выше опции <tt>--log-prefix</tt> и <tt>--log-level</tt>. * '''ULOG''' — позволяет передавать информацию об обработанных пакетах специальным демонам, таким, как [http://www.netfilter.org/projects/ulogd/ ulogd]. Такой подход позволяет эффективно управлять информацией о трафике, в частности, заносить ее в {{w |базы данных}}, такие как {{w |MySQL}}, {{w |PostgreSQL}} или {{w |SQLite}}. Впоследствии эти данные могут быть проанализированы и визуализированы с помощью таких средств, как [http://software.inl.fr/trac/wiki/EdenWall/NuLog NuLog]. * '''NFLOG''' — более универсальный вариант ULOG, обеспечивающий передачу информации о пакете не напрямую в netlink-[[w:Сокет (программный интерфейс)|сокет]] (как это делает ULOG), а специальной подсистеме — logging backend. Например, бэкенд nfnetlink_log обеспечивает передачу данных в netlink-сокет, то есть с ним NFLOG работает аналогично ULOG. * '''NFQUEUE''' — во многом похоже на ULOG, но передает специальному демону не информацию о пакете, а сам пакет целиком. Применяется, в частности, для организации работы {{w |l7-filter}}-userspace. Например, если демон l7-filter был запущен командой <syntaxhighlight lang="bash"> l7-filter -f /etc/l7-filter.conf -q 2 </syntaxhighlight> то передать ему на обработку все входящие и локально сгенерированные пакеты можно командами <syntaxhighlight lang="bash"> iptables -t mangle -F # На всякий случай очищаем таблицу mangle iptables -t mangle -A PREROUTING -j NFQUEUE --queue-num 2 iptables -t mangle -A OUTPUT -j NFQUEUE --queue-num 2 </syntaxhighlight> Опция <tt>--queue-num</tt> позволяет указать номер очереди пакетов. Он должен быть совпадать с номером, указанным при запуске демона l7-filter (параметр <tt>-q</tt>). * '''QUEUE''' — устаревшая версия NFQUEUE. Не имеет параметров, так как работает только с очередью номер 0. Выше были рассмотрены действия «общего назначения», то есть не привязанные по своей специфике к таблицам. Далее, при рассмотрении отдельных таблиц, будут описываться действия, специфичные для каждой таблицы. Термин «специфичные» надо понимать так: совсем не обязательно, что действие, специфичное для одной таблицы, будет в принципе недопустимо в другой, но в любом случае использование этого действия в других таблицах будет «плохим тоном» — ведь таблицы и действия четко разделены по назначению. Не стоит «забивать гвозди микроскопом». Порой эта разница бывает довольно тонкой. Например, если действие NFQUEUE передает пакеты демону {{w |l7-filter}}-userspace (который занимается маркировкой пакетов на основе анализа их содержимого), то правильнее будет разместить вызов такого действия в таблице mangle. Если же оно передает пакеты демону [[nufw]] (который обеспечивает разрешение или запрещение трафика на основе авторизации пользователя), то логичнее разместить это действие в таблице filter. Кроме того, существуют и ограничения, наложенные непосредственно в коде iptables. Например, действия таблицы nat жестко защищены от употребления за ее пределами. Другой пример: действие REDIRECT можно применять только в цепочках PREROUTING и OUTPUT таблицы nat, то есть ограничения могут быть не только на таблицы, но на отдельные цепочки. Данная статья ни в коем случае не претендует на полноту изложения, поэтому, перед тем как использовать какое-либо действие, обязательно ознакомьтесь с документацией, прилагающейся к вашей версии iptables. * '''TRACE''' - трассировка прохождения пакетов по цепочке Для включения трассировки нужно загрузить модуль ядра xt_LOG: modprobe xt_LOG echo xt_LOG > /proc/sys/net/netfilter/nf_log/2 доступно только для таблицы raw. Пример правила: iptables -I PREROUTING 1 -t raw -s 192.168.200.25 -d 1.1.1.1 -j TRACE Лог трассировки по умолчанию записывается в /var/log/syslog. Для удобства, можно раскрашивать вывод с помощью небольшого скрипта view-trace.sh === Терминальные и нетерминальные действия === * ''Терминальными'' называются действия, которые прерывают прохождение пакета через текущую базовую цепочку. То есть если к пакету в рамках некоторого правила было применено терминальное действие, он уже не проверяется на соответствие всем следующим правилам в этой цепочке (и в тех цепочках, из которых она была вызвана, если это пользовательская цепочка). Терминальными являются все действия, специфичные для таблиц filter и nat. Из приведенных выше в этом разделе — ACCEPT, DROP, REJECT, NFQUEUE, QUEUE. Например, <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "IN HTTP: " </syntaxhighlight> Второе из приведенных правил (логгирование) никогда не будет срабатывать, так как все пакеты, удовлетворяющие этому критерию (входящие TCP-пакеты на порт 80), будут пропущены по первому из этих правил, и до второго просто не дойдут. * ''Нетерминальными'', соответственно, являются действия, ''не'' прерывающие процесс прохождения пакета через цепочки. Нетерминальными являются действия, специфичные для таблицы mangle, а из перечисленных выше — LOG, ULOG и NFLOG. Например, <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "IN HTTP: " iptables -A INPUT -p tcp --dport 80 -j ACCEPT </syntaxhighlight> Теперь все входящие на TCP-порт 80 пакеты будут сначала заноситься в лог, и только потом пропускаться. Действие RETURN с точки зрения такой классификации занимает промежуточное положение — оно может прервать прохождение пакета через отдельную цепочку (или несколько цепочек, если для перехода в них использовалась опция <tt>-g</tt>, а не <tt>-j</tt>), но совсем не обязательно, чтобы это приводило к завершению обработки пакета в рамках текущей базовой цепочки. == Таблицы == [[Файл:Netfilter-diagram-rus.png|thumb|400px|Путь проверки пакета в системе netfilter]] === Таблица mangle === Данная таблица предназначена для операций по классификации и маркировке пакетов и соединений, а также модификации заголовков пакетов (поля [[w:Time to live|TTL]] и [[w:Тип обслуживания|TOS]]). ==== Цепочки ==== Таблица mangle содержит следующие цепочки: * '''PREROUTING''' — позволяет модифицировать пакет ''до'' принятия решения о маршрутизации. * '''INPUT''' — позволяет модифицировать пакет, предназначенный самому хосту. * '''FORWARD''' — цепочка, позволяющая модифицировать транзитные пакеты. * '''OUTPUT''' — позволяет модифицировать пакеты, исходящие от самого хоста. * '''POSTROUTING''' — дает возможность модифицировать все исходящие пакеты, как сгенерированные самим хостом, так и транзитные. Заметим, что все цепочки таблицы mangle пакеты проходят раньше, чем одноименные цепочки таблиц nat и filter. Это позволяет классифицировать и маркировать пакеты и соединения в цепочках этой таблицы. Впоследствии эти маркировки могут быть использованы в цепочках двух других таблиц при принятии решений о фильтрации и трансляции адресов. ==== Действия ==== Допустимыми действиями в этой таблице являются: * '''TOS''' — изменяет поле [[w:Тип обслуживания|TOS]] данного пакета. Поддерживаются опции <tt>--set-tos</tt> (установить поле TOS в заданное значение), а также <tt>--and-tos</tt>, <tt>--or-tos</tt> и <tt>--xor-tos</tt>, комбинирующие текущее значение поля TOS с заданным в правиле значением по соответствующему логическому правилу и записывающие результат как новое значения поля TOS. Кроме того, опция <tt>--set-tos</tt> поддерживает расширенный синтаксис <tt>--set-tos ''значение''/''маска''</tt>. При использовании такого синтаксиса в исходном значении TOS пакета зануляются те биты, которые установлены в маске, затем полученное число XOR’ится с указанным в параметрах значением, и полученная величина записывается в поле TOS. Используя синтаксис [[w:Си (язык программирования)|языка C]], это можно записать так: <tt>NEW_TOS = (OLD_TOS & ~''маска'') ^ ''значение''</tt>. Заметим, что в случае с {{w |IPv6}} операция отрицания маски не выполняется (то есть в исходном значении зануляются те биты, которые в маске ''не установлены''), хотя это и не отражено в документации. Также, в случае {{w |IPv4}} (iptables) в параметре <tt>--set-tos</tt> вы можете указать одно из допустимых символьных обозначений: Minimize-Delay (TOS 16, требование минимальной задержки), Maximize-Throughput (TOS 8, требование максимальной пропускной способности), Maximize-Reliability (TOS 4, максимальная надежность доставки), Minimize-Cost (TOS 2, минимальная стоимость), Normal-Service (TOS 0, специальные требования отсутствуют). В ip6tables использование этих обозначений не запрещено, однако в этом случае более корректным будет использование действия DSCP (см. ниже). Практический пример использования действия TOS представлен [[#Лимитирующие критерии|ниже]], в описании критерия connbytes. Отметим, что, в соответствии с современными соглашениями, поле TOS в заголовке IP-пакета разделяется на две части: {{w |DSCP}} (первые шесть бит кода TOS) и [[w:Explicit Congestion Notification|ECN]] (последние два бита TOS). Современные версии netfilter/iptables не поддерживают изменение значений ECN в IP-заголовках, поэтому фактически действие TOS работает только с полем DSCP, отличаясь от действия DSCP (см. чуть ниже) разве что интерфейсом (фактически, синтаксисом). * '''DSCP''' — изменяет поле {{w |DSCP}} (класс [[:en:Differentiated services|DiffServ]]) в заголовке пакета. Поддерживаются опции <tt>--set-dscp</tt> (позволяет задать значение DSCP числом) и <tt>--set-dscp-class</tt> (позволяет установить заданный класс DiffServ, например, EF или AF13). * '''TTL''' — изменяет поле [[w:Time to live|TTL]] данного пакета (работает только с {{w |IPv4}}, для {{w |IPv6}} используется действие HL). Поддерживаются опции <tt>--ttl-set</tt> (установить поле TTL в заданное значение), а также <tt>--ttl-inc</tt> и <tt>--ttl-dec</tt> (соответственно увеличить или уменьшить текущее значение поля TTL на заданное значение). Допустимые значения TTL — от 0 до 255. При достижении TTL=0 пакет уничтожается. В качестве полезного примера использования этого действия можно привести команду <syntaxhighlight lang="bash"> iptables -t mangle -I PREROUTING -j TTL --ttl-inc 1 </syntaxhighlight> делающую наш шлюз невидимым для большинства [[w:Traceroute|трассировщиков]]. Обратите внимание, что автоматически выполняемая сетевым стеком ядра операция уменьшения TTL на единицу и проверки на равенство нулю выполняется ''после'' цепочки PREROUTING, но ''до'' цепочки FORWARD. Таким образом, переместив это правило в цепочку FORWARD, вы обеспечите «невидимость» следующего за вами шлюза. Другой полезный пример — выравнивание TTL на выходе в Интернет (интерфейс eth0) <syntaxhighlight lang="bash"> iptables -t mangle -I POSTROUTING -o eth0 -j TTL --ttl-set 64 </syntaxhighlight> Некоторые домашние провайдеры, пытаясь бороться с нелегальной перепродажей канала их клиентами, блокируют доступ тем клиентам, на выходе которых замечены пакеты с разными значениями TTL, потому что этот факт косвенно указывает на наличие у клиента внутренней подсети. Предложенное правило, будучи применено на шлюзе такой подсети, делает ее детекцию по TTL крайне затруднительной. '''Будьте очень осторожны''' с правилами, которые увеличивают или, что особенно опасно, напрямую задают значение TTL, так как, при наличии определенных ошибок маршрутизации, это может привести к появлению «бессмертных» пакетов, которые будут долго циркулировать между одними и теми же узлами, захламляя канал и затрудняя работу сетевого оборудования. * '''HL''' — изменяет поле Hop Limit в заголовке {{w |IPv6}}-пакета. Является аналогом IPv4-действия TTL и поддерживает те же операции: <tt>--hl-set</tt> (установить поле HL в заданное значение), а также <tt>--hl-inc</tt> и <tt>--hl-dec</tt> (соответственно увеличить или уменьшить текущее значение поля HL на заданное значение). * '''MARK''' — устанавливает или изменяет маркировку пакета. Поддерживает опции <tt>--set-mark</tt>, <tt>--and-mark</tt>, <tt>--or-mark</tt> и <tt>--xor-mark</tt>, аналогичные опциям действия TOS. Важно понимать, что маркировка пакета не хранится в его заголовке или содержимом, и поэтому действует только в пределах одного хоста. Также нужно отличать маркировку пакета от маркировки соединения. Маркировка пакетов может применяться для их дальнейшей обработки фаерволом (критерии mark и connmark), а также для классификации трафика фильтрами [[w:Шейпинг (информатика)|шейпинговой]] подсистемы [[w:Iproute2|tc]] (лексема handle ''mark'' fw). * '''CONNMARK''' — устанавливает или изменяет маркировку соединения. Поддерживает те же опции, что и MARK, а также дополнительные опции <tt>--restore-mark</tt> (копирует маркировку соединения в маркировку пакета) и <tt>--save-mark</tt> (копирует маркировку пакета в маркировку соединения). * '''CLASSIFY''' — устанавливает [[:en:Class Based Queueing|CBQ]]-класс пакета для его последующей обработки [[w:Шейпинг (информатика)|шейпером]] (опция <tt>--set-class</tt>). * '''TCPMSS''' — устанавливает [[:en:Maximum segment size|максимальный размер TCP-сегмента]]. Бывает крайне полезной при использовании {{w |VPN}}-подключения<ref>Обычно проблемы с пониженным {{w |MTU}} в {{w |Ethernet}}-сетях возникают как раз из-за {{w |VPN}}-туннелей</ref> в том случае, если VPN-сервер блокирует {{w |ICMP}}-сообщения destination unreachable/fragmentation needed (тип 3, код 4), тем самым нарушая работу процедуры [[w:Maximum transmission unit#Технология Path MTU discovery|Path MTU discovery]]. С точки зрения клиента, эта проблема выглядит так: {{w |пинг}}и проходят нормально, но при попытке открыть какую-либо {{w |веб}}-страницу, {{w |браузер}} «подвисает». При этом с самого шлюза все работает нормально. В этом случае достаточно применить на шлюзе следующую команду <syntaxhighlight lang="bash"> iptables -t mangle -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu </syntaxhighlight> которая обеспечит автоматическую установку размера сегмента в TCP-заголовках SYN- и RST,SYN-пакетов в соответствии с минимальным из известных нашему шлюзу значений {{w |MTU}} на пути следования пакета. Например, если пакет пришел с интерфейса eth0 (MTU 1500) и уходит через интерфейс ppp0 (MTU 1492), а суммарный размер заголовков [[w:Протоколы сетевого уровня|сетевого]] и [[w:Транспортный уровень|транспортного]] уровней составляет 40 {{w |байт}} (20 байт {{w |TCP}} и 20 байт {{w |IP}}), то целесообразно установить MSS равным 1452 байтам. Помимо возможности автоматического выбора TCP MSS, вы можете задать необходимое значение и вручную, используя параметр <tt>--set-mss ''значение''</tt>. Это бывает полезным в том случае, если вам заведомо известно, что дальше на маршруте встречаются участки с еще меньшим MTU, а пограничные сервера этих участков опять же блокируют ICMP destination unreachable/fragmentation needed. * '''ECN''' — обеспечивает обнуление [[w:Explicit Congestion Notification|ECN]]-битов (флаги CWR и ECE) в TCP-заголовке (единственная опция <tt>--ecn-tcp-remove</tt>). Может использоваться только в {{w |IPv4}}-модуле (iptables, но не ip6tables) для {{w |TCP}}-пакетов (<tt>-p tcp</tt>). Данное действие предназначено для защиты пакетов от ECN blackholes (маршрутизаторов, которые некорректно обрабатывают пакеты с установленными в TCP-заголовке ECN-битами) — рекомендуется применять это действие ко всем пакетам, уходящим на такие маршрутизаторы. Обратите внимание, что данное действие никак не влияет на ECN-биты в {{w |IP}}-заголовках (последние два бита поля [[w:Тип обслуживания|TOS]]). Кроме того, данное действие поддерживает три потенциально опасные опции, не отраженные в документации: <tt>--ecn-tcp-cwr</tt> (установка значения бита CWR в TCP-заголовке, 0 или 1), <tt>--ecn-tcp-ece</tt> (установка значения бита ECE в TCP-заголовке, 0 или 1) и <tt>--ecn-ip-ect</tt> (установка значения ECT codepoint в IPv4-заголовке, от 0 до 3). Использование этих опций настолько опасно, что они не отражены даже во встроенной справке iptables (<tt>iptables -j ECN -h</tt>) — их можно увидеть, только изучив [https://git.netfilter.org/iptables/tree/extensions/libipt_ECN.c исходный код]. Без крайней необходимости применять их не рекомендуется. * '''TCPOPTSTRIP''' — выполняет удаление заданных TCP-опций из заголовка TCP-пакета (единственный параметр <tt>--strip-options ''значение''[,''значение''[,...]]</tt>). Удаляемые опции могут быть указаны через их номера (согласно [http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml списку на сайте IANA]) или в виде символьных обозначений (список обозначений, поддерживаемых в вашей версии iptables можно посмотреть, выполнив команду <tt>iptables -j TCPOPTSTRIP -h</tt>). Разумеется, данное действие допустимо только для протокола TCP (<tt>-p tcp</tt>). Например, <syntaxhighlight lang="bash"> iptables -t mangle -A POSTROUTING -p tcp -j TCPOPTSTRIP --strip-options timestamp </syntaxhighlight> обеспечит удаление штампов времени ({{RFC|1323}}). С одной стороны, такое правило будет препятствовать удаленному злоумышленнику определить {{w |аптайм}} нашего хоста, а также тех хостов, маршрут от которых до злоумышленника проходит через наш хост. С другой стороны, блокирование штампов времени может негативно сказаться на быстродействии сети, особенно если вы используете подключения на скорости [[w:Fast Ethernet|100 МБит]] и выше. Заметим также, что если вам нужно управлять использованием именно штампов времени для TCP IPv4-пакетов, исходящих от вашего хоста, вы можете воспользоваться {{w |sysctl}}-параметром net.ipv4.tcp_timestamps (1 — штампы включены, 0 — выключены). * '''TPROXY''' — реализует механизм полностью прозрачного [[w:Прокси-сервер|проксирования]]. Такой подход отличается от традиционно используемого «прозрачного» проксирования (действие REDIRECT [[#Таблица nat|таблицы nat]], см. ниже) тем, что заголовок пакета никак не модифицируется, в том числе не заменяется {{w |IP-адрес}} назначения (при традиционном прозрачном проксировании он заменяется на адрес проксирующего хоста). Кроме того, полностью прозрачное проксирование является прозрачным с точки зрения обеих общающихся сторон. Например, при проксировании обращений некоторой подсети клиентов к серверам из другой подсети, можно сделать так, чтобы не только клиенты считали, что обращаются напрямую к серверам, но и сервера «видели» настоящие исходные адреса клиентов и могли бы устанавливать с ними обратные соединения (например, в случае активного режима {{w |FTP}}). При традиционном же «прозрачном» проксировании, сервера могут видеть только адрес прокси-сервера. TPROXY позволяет перенаправить транзитный пакет на локальный [[w:Сокет (программный интерфейс)|сокет]] типа AF_INET (iptables) или AF_INET6 (ip6tables), заданный портом, а также может промаркировать пакет таким образом, чтобы система марушрутизации ({{w |iproute2}}) не позволила пакету покинуть наш хост. Разумеется, поддержка полностью прозрачного проксирования должна быть реализована и в самом {{w |прокси-сервер}}е. В частности, прозрачное проксирование {{w |IPv4}} {{w |HTTP}} [http://wiki.squid-cache.org/Features/Tproxy4 поддерживается] прокси-сервером {{w |Squid}} начиная с версии 3.1. В качестве примера можно привести простейший случай конфигурации iptables и iproute2 для обеспечения полностью прозрачного проксирования {{w |IPv4}} {{w |HTTP}}. <syntaxhighlight lang="bash"> # Добавляем принудительную локальную маршрутизацию для всех адресов в таблицу 120 ip route add local 0.0.0.0/0 dev lo table 120 # Все пакеты, имеющие соответствующую маркировку, направляем в эту таблицу ip rule add fwmark 120 table 120 # Выполняем проксирование для новых соединений iptables -t mangle -I PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 120 --on-port 3129 # Перехватываем, маркируем и пропускаем пакеты, принадлежащие проксируемым соединениям iptables -t mangle -N proxypackets iptables -t mangle -A proxypackets -j MARK --set-mark 120 iptables -t mangle -A proxypackets -j ACCEPT # Такие пакеты можно выделять с помощью критерия socket iptables -t mangle -I PREROUTING -m socket -j proxypackets </syntaxhighlight> Таким образом, пакеты, перехваченные TPROXY-правилом, маркируются и направляются на локальный сокет (порт 3129), который должен прослушиваться специально сконфигурированным прокси-сервером (в случае Squid, в файл конфигурации <tt>squid.conf</tt> нужно добавить строку <tt>http_port 3129 tproxy</tt>). Все пакеты, принадлежащие уже проксируемым соединениям, перехватываются правилом с критерием socket (этот критерий позволяет определить, существует ли на нашем хосте сокет, связанный с данным пакетом), маркируются и немедленно пропускаются. Отметим, что последнее правило будет обрабатываться раньше, чем правило с TPROXY, так как параметр <tt>-I</tt> обеспечивает вставку правил ''в начало'' цепочки, и при последовательном добавлении нескольких правил с этим параметром, порядок добавленных правил будет обратным порядку их ввода. === Таблица nat === Предназначена для операций stateful-преобразования [[w:IP-адрес|сетевых адресов]] и [[w:Порт (компьютерные сети)|портов]] обрабатываемых пакетов. ==== Цепочки ==== Таблица nat содержит следующие цепочки: * '''PREROUTING''' — в эту цепочку пакеты попадают ''до'' принятия решения о маршрутизации. По сути, термин «решение о маршрутизации» подразумевает деление трафика на входящий (предназначенный самому хосту) и транзитный (идущий через этот хост на другие хосты). Именно на данном этапе нужно проводить операции проброса (DNAT, REDIRECT, NETMAP). * '''OUTPUT''' — через эту цепочку проходят пакеты, сгенерированные процессами самого хоста. На данном этапе при необходимости можно повторить операции проброса, так локально сгенерированные пакеты ''не'' проходят цепочку PREROUTING и ''не'' обрабатываются ее правилами. См. пример для действия DNAT ниже. * '''POSTROUTING''' — через эту цепочку проходят все исходящие пакеты, поэтому именно в ней целесообразно проводить операции {{w |маскарадинг}}а (SNAT и MASQUERADE). ==== Действия ==== Допустимыми действиями в таблице nat являются: * '''MASQUERADE''' — подменяет адрес источника для исходящих пакетов адресом того интерфейса, с которого они исходят, то есть осуществляет {{w |маскарадинг}}. Такая операция позволяет, например, предоставлять доступ в {{w |Интернет}} целым [[w:Локальная вычислительная сеть|локальным сетям]] через один [[w:Сетевой шлюз|шлюз]]. Допустим, у нас есть локальная сеть 192.168.1.0/255.255.255.0 с несколькими компьютерами, имеющими адреса 192.168.1.2, 192.168.1.3 и т. д. Адрес 192.168.1.1 имеет внутренний (подключенный к локальной сети) сетевой интерфейс шлюза, назовем этот интерфейс eth1. Другой его интерфейс, назовем его eth0, подключен к сети Интернет и имеет адрес, допустим, 208.77.188.166. Тогда, чтобы обеспечить выход хостов из этой локальной сети в Интернет, на шлюзе достаточно выполнить следующие команды <syntaxhighlight lang="bash"> sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик iptables -F FORWARD # На всякий случай очистим цепочку FORWARD # Разрешаем проходить пакетам по уже установленным соединениям iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем исходящие соединения из локальной сети к интернет-хостам iptables -A FORWARD -m conntrack --ctstate NEW -i eth1 -s 192.168.1.0/24 -j ACCEPT iptables -P FORWARD DROP # Весь остальной транзитный трафик — запрещаем. iptables -t nat -F POSTROUTING # На всякий случай очистим цепочку POSTROUTING таблицы nat # Маскарадим весь трафик, идущий через eth0 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE </syntaxhighlight> Теперь, если один из хостов локальной сети, например, 192.168.1.2, попытается связаться с одним из интернет-хостов, например, 199.204.44.194 (kernel.org), при проходе его пакетов через шлюз, их исходный адрес будет подменяться на внешний адрес шлюза, то есть 208.77.188.166. С точки зрения удаленного хоста (kernel.org), это будет выглядеть, как будто с ним связывается непосредственно сам шлюз. Когда же удаленный хост начнет ответную передачу данных, он будет адресовать их именно шлюзу, то есть 208.77.188.166. Однако, на шлюзе адрес назначения этих пакетов будет подменяться на 192.168.1.2, после чего пакеты будут передаваться настоящему получателю. Для такого обратного преобразования никаких дополнительных правил указывать не нужно — это будет делать все та же операция MASQUERADE. Простота трансляции сетевых адресов является одним из важнейших достоинств stateful-фильтрации. Если же такой трансляции не производить, удаленный хост просто не сможет ответить на адрес 192.168.1.2, так как адресные пространства локальных сетей изолировано от адресного пространства Интернета. В мире могут существовать миллионы локальных сетей 192.168.1.0/255.255.255.0, и в каждой может быть свой хост 192.168.1.2. Эти сети могут и не быть связаны с Интернетом. Но если они с ним связаны — то только благодаря механизмам трансляции сетевых адресов. * '''SNAT''' (Source Network Address Translation) — работает аналогично MASQUERADE, однако позволяет указать адрес «внешнего» интерфейса (опция <tt>--to-source</tt>). Такой подход позволяет экономить процессорное время шлюза, так как в случае с MASQUERADE для каждого пакета адрес внешнего интерфейса определяется заново при каждом новом коннекте (например к сайту на другом хосту). Таким образом, если в предыдущем примере внешний адрес шлюза 208.77.188.166 является статическим (то есть никогда не меняется), команду <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE </syntaxhighlight> целесообразно заменить на <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.166 </syntaxhighlight> Однако, в случае, если внешний адрес шлюза динамический, то есть меняется в начале каждой новой сессии, правильнее будет использовать именно MASQUERADE. Дополнительно, если на внешнем интерфейсе шлюза «висит» несколько статических адресов, например, 208.77.188.166, 208.77.188.167 и 208.77.188.168, можно использовать балансировку между этими адресами: <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.166-208.77.188.168 </syntaxhighlight> Теперь для каждого нового соединения адрес для подмены будет выбираться случайным образом. * '''DNAT''' (Destination Network Address Translation) — подменяет адрес назначения для входящих пакетов, позволяя «пробрасывать» адреса или отдельные порты внутрь локальной сети. Возвращаясь к предыдущему примеру, предположим, что нам нужно «пробросить» внешний адрес шлюза 208.77.188.166 на хост 192.168.1.2, то есть все, кто будет обращаться по внешнему адресу шлюза 208.77.188.166, должны попадать на хост 192.168.1.2. Это достигается следующими командами: <syntaxhighlight lang="bash"> # Разрешаем шлюзу передавать транзитный трафик sysctl net.ipv4.ip_forward=1 iptables -t nat -F PREROUTING # На всякий случай очистим цепочку PREROUTING таблицы nat # Пробрасываем 208.77.188.166 на 192.168.1.2 iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2 iptables -F FORWARD # На всякий случай очистим цепочку FORWARD # Разрешаем проходить пакетам по уже установленным соединениям iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем входящие соединения к 192.168.1.2 iptables -A FORWARD -m conntrack --ctstate NEW -d 192.168.1.2 -j ACCEPT iptables -P FORWARD DROP # Весь остальной транзитный трафик — запрещаем. </syntaxhighlight> В лучших традициях stateful-фаерволинга, подменяются не только адреса назначения для входящих пакетов (208.77.188.166 -> 192.168.1.2), но и адреса источника для исходящих пакетов (192.168.1.2 -> 208.77.188.166), поэтому для интернет-хостов создается полное впечатление, что они общаются именно с 208.77.188.166. Однако, при всей своей простоте и наглядности, этот пример имеет два недостатка. Во-первых, из нашей локальной сети 192.168.1.0/24 адрес 208.77.188.166 может быть недоступен, так как 192.168.1.2, увидев, что запрос исходит из его сети, может отправить ответ непосредственно отправителю (например, 192.168.1.3), минуя сам шлюз. Отправитель же будет ждать ответа от 208.77.188.166, и просто проигнорирует ответ от 192.168.1.2. Впрочем, эта проблема легко исправляется добавлением SNAT’а для пробрасываемых пакетов: <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -d 192.168.1.2 -s 192.168.1.0/24 -j SNAT --to-source 192.168.1.1 </syntaxhighlight> Теперь, с точки зрения 192.168.1.2, к нему будет обращаться только сам шлюз (192.168.1.1), поэтому ответ также пойдет через шлюз, где будет корректно оттранслирован. Такое решение тоже имеет недостаток — подмена исходного адреса пакета приводит к тому, что компьютер, на который мы пробрасываем соединение, не может определить реального инициатора соединения. Чтобы уменьшить «вредность» этого правила, в него добавлена опция «-s 192.168.1.0/24», которая ограничивает применение этого правила только пакетами из локальной сети. Таким образом, соединения из локальной сети будут выглядеть как соединения, инициированные шлюзом, а соединения из внешней сети будут иметь свои оригинальные адреса. Вторым недостатком предложенного примера является некорректная обработка запросов с самого шлюза. Ведь пакеты, генерируемые локальными процессами, не проходят цепочку PREROUTING. Поэтому правило DNAT нужно также добавить и в цепочку OUTPUT таблицы nat: <syntaxhighlight lang="bash"> iptables -t nat -A OUTPUT -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2 </syntaxhighlight> Разумеется, исходящие соединения к 192.168.1.2 и ответы на них должны быть разрешены соответственно в цепочках OUTPUT и INPUT таблицы filter. Самый простой способ сделать это — <syntaxhighlight lang="bash"> iptables -F INPUT # Очищаем цепочку INPUT # Разрешаем входящие пакеты по уже установленным соединениям iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -P INPUT DROP # Все остальные входящие пакеты — запрещаем iptables -F OUTPUT # Очищаем цепочку OUTPUT iptables -P OUTPUT ACCEPT # Разрешаем исходящие пакеты безо всяких ограничений </syntaxhighlight> Кроме того, при помощи действия DNAT можно пробрасывать не только сразу весь IP-адрес, но и отдельные {{w |TCP}}- или {{w |UDP}}-[[w:Порт (компьютерные сети)|порты]]. Например, если в предыдущем примере мы в каждое из правил <syntaxhighlight lang="bash"> iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2 iptables -t nat -A POSTROUTING -d 192.168.1.2 -s 192.168.1.0/24 -j SNAT --to-source 192.168.1.1 iptables -t nat -A OUTPUT -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2 </syntaxhighlight> добавим <syntaxhighlight lang="bash"> -p tcp --dport 80 </syntaxhighlight> то мы «пробросим» не сам адрес 208.77.188.166, а только его {{w |TCP}}-[[w:Порт (компьютерные сети)|порт]] 80 ({{w |HTTP}}). Обращения на все остальные {{w |TCP}}- и {{w |UDP}}-порты, а также {{w |ICMP}}-пакеты, поступившие на адрес 208.77.188.166, будут обрабатываться шлюзом, и лишь входящие TCP-соединения на порт 80 будут передаваться на 192.168.1.2. Как и SNAT, DNAT поддерживает указание диапазонов адресов для подмены. Таким образом можно, например, балансировать нагрузку между несколькими серверами. * '''REDIRECT''' — подменяет номер порта в TCP- или UDP-пакете, а также подменяет адрес назначения на свой собственный. Например, <syntaxhighlight lang="bash"> iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080 </syntaxhighlight> позволяет «завернуть» все исходящие из локальной сети TCP-соединения на порт 80, на TCP-порт 8080 шлюза. Если этот порт обслуживается специально настроенным {{w |прокси-сервер}}ом, то можно организовать «прозрачное проксирование» — клиенты из локальной сети даже не будут подозревать, что их запросы идут через прокси-сервер. Разумеется, входящие соединения из локалки на TCP-порт 8080 должны быть разрешены в таблице filter. Другой полезный пример: <syntaxhighlight lang="bash"> iptables -t nat -A PREROUTING -i eth0 -s 213.180.0.0/16 \ -p tcp --dport 80 -j REDIRECT --to-port 8000 </syntaxhighlight> «заворачивает» все входящие из Интернета, а точнее подсети 213.180.0.0/255.255.0.0 TCP-соединения на порт 80, переадресуя их на порт 8000 того же сервера (где, например, может работать специальный веб-сервер). Как обычно, входящие соединения на TCP-порт 8000 должны быть разрешены в таблице filter. * '''SAME''' — в зависимости от цепочки (PREROUTING или POSTROUTING) может работать как DNAT или SNAT. Однако, при указании (в параметре <tt>--to-ip</tt>) одного или нескольких диапазонов IP-адресов, определяет для каждого нового соединения подставляемый адрес не случайно, а базируясь на IP-адресе клиента. Таким образом, адрес для подмены остается постоянным для одного и того же клиента при повторных соединениях (что ''не'' выполняется для обычных DNAT/SNAT). В некоторых случаях это бывает важным. Примечание: в соответствии с iptables-extensions’s man page действие SAME убрано и заменено на опцию --persistent для действий '''DNAT'''/'''SNAT'''. * '''NETMAP''' — позволяет «пробросить» целую сеть. Например, для шлюза, стоящего между сетями 192.168.1.0/24 и 192.168.2.0/24 можно организовать следующий проброс: <syntaxhighlight lang="bash"> iptables -t nat -A PREROUTING -s 192.168.1.0/24 -d 192.168.3.0/24 -j NETMAP --to 192.168.2.2/24 </syntaxhighlight> Теперь, при обращении, например, хоста 192.168.1.3 на IP-адрес 192.168.3.2 он будет попадать на 192.168.2.2 (при условии, что такой транзитный трафик разрешен на шлюзе в цепочке FORWARD таблицы filter, а также на хостах сети 192.168.1.0/24 наш шлюз [[w:Маршрутизация|прописан]] в качестве шлюза для подсети 192.168.3.0/24). : ''Примечание: следующее действие планируется к переносу в еще не написанный раздел статьи (Устаревшие критерии и действия)''. * '''MIRROR''' — довольно интересная игрушка. Меняет местами адрес источника и назначения и высылает пакет обратно. Создано исключительно для демонстрационных целей. Однако, может, например, применяться для защиты от сканирования портов — в результате атакующий сканирует свои собственные порты. Однако наличие двух встречных MIRROR’ов на двух хостах может повлечь бесконечное блуждание одних и тех же пакетов, забивающее канал. Поэтому применяйте это действие с осторожностью. === Таблица filter === Предназначена для фильтрации трафика, то есть разрешения и запрещения пакетов и соединений. ==== Цепочки ==== Таблица filter содержит следующие цепочки: * '''INPUT''' — эта цепочка обрабатывает трафик, поступающий непосредственно самому хосту. * '''FORWARD''' — позволяет фильтровать транзитный трафик. * '''OUTPUT''' — эта цепочка позволяет фильтровать трафик, исходящий от самого хоста. ==== Действия ==== Допустимыми действиями в таблице filter являются: * '''ACCEPT''' — пропуск пакета. Пакет покидает текущую базовую цепочку и следует дальше по потоковой диаграмме (см. рис.). * '''REJECT''' — заблокировать пакет и сообщить его источнику об отказе. По умолчанию об отказе сообщается отправкой ответного {{w |ICMP}}-пакета «icmp-port-unreachable». Однако, это действие поддерживает опцию <tt>--reject-with</tt>, позволяющую указать формулировку сообщения об отказе (возможные значения: <tt>icmp-net-unreachable</tt>, <tt>icmp-host-unreachable</tt>, <tt>icmp-proto-unreachable</tt>, <tt>icmp-net-prohibited</tt>, <tt>icmp-host-prohibited</tt>). Для протокола {{w |TCP}} поддерживается отказ в форме отправки RST-пакета (<tt>--reject-with tcp-reset</tt>). * '''DROP''' — заблокировать пакет, не сообщая источнику об отказе. Более предпочтительна при фильтрации трафика на интерфейсах, подключенных к интернету, так как понижает информативность сканирования портов хоста злоумышленниками. Также определенный интерес представляют действия, предоставляемые модулями [http://xtables-addons.sourceforge.net/ xtables-addons] (в настоящее время этот проект уже [http://packages.debian.org/squeeze/xtables-addons-common включен] в {{w |Debian}} testing). Некоторые из них: * '''STEAL''' — аналогично DROP, но в случае использования в цепочке OUTPUT при блокировании исходящего пакета не сообщает об ошибке приложению, пытавшемуся отправить этот пакет. * '''TARPIT''' — «подвесить» {{w |TCP}}-соединение. Используется лишь в самых крайних случаях, например, при борьбе с {{w |DoS-атака}}ми. Отвечает на входящее соединение, после чего уменьшает размер фрейма до нуля, блокируя возможность передачи данных. Соединение будет «висеть» в таком состоянии пока не истечет тайм-аут на атакующей стороне (обычно 20—30 минут). При этом на такое соединение расходуются системные ресурсы атакующей стороны (процессорное время и оперативная память), что может быть весьма ощутимо при значительном количестве соединений. В случае правильного использования действия TARPIT ресурсы атакуемой стороны практически не расходуются. Под правильным применением понимается предотвращение обработки таких соединений подсистемой [[conntrack]], так как в противном случае будут расходоваться системные ресурсы самого атакуемого хоста. Например, перед добавлением правила блокирования порта <syntaxhighlight lang="bash"> iptables -I INPUT -p tcp --dport 25 -j TARPIT </syntaxhighlight> обязательно добавляйте в таблицу raw соответствующее правило <syntaxhighlight lang="bash"> iptables -t raw -I PREROUTING -p tcp --dport 25 -j NOTRACK </syntaxhighlight> предотвращающее обработку блокируемых соединений подсистемой conntrack. * '''DELUDE''' — создать видимость открытого TCP-порта. На SYN-пакеты отвечает пакетами SYN/ACK, на все прочие пакеты отвечает RST. Очень полезно для введения в заблуждение злоумышленника, сканирующего порты вашего хоста. * '''CHAOS''' — для каждого нового TCP-соединения случайно выбрать одно из двух действий. Первое из них — REJECT, второе, в зависимости от выбранной опции, либо TARPIT (<tt>--tarpit</tt>), либо DELUDE (<tt>--delude</tt>). В частности, при использовании действия <tt>CHAOS --delude</tt> для всех неиспользуемых портов, сканирующий ваши порты злоумышленник получит совершенно неверную информацию о состоянии ваших портов. В случае с <tt>CHAOS --tarpit</tt> ситуация усугубится еще и «подвисающими» соединениями. Особо заметим, что все действия, перечисленные в качестве допустимых в таблице filter, можно применять в любой из цепочек любой из таблиц (конечно, с разумными ограничениями — например, не стоит ставить действия TARPIT, CHAOS и DELUDE для собственных исходящих пакетов). Однако эти действия предназначены именно для фильтрации, и применение их за пределами таблицы filter является дурным тоном. Как и, например, применение действий, специфичных для таблицы mangle, в таблицах filter и nat. === Таблица security === Предназначена для изменения маркировки безопасности (меток {{w |SELinux}}) пакетов и соединений. ==== Цепочки ==== Аналогичны цепочкам таблицы filter: * '''INPUT''' — эта цепочка обрабатывает трафик, поступающий непосредственно самому хосту. * '''FORWARD''' — через эту цепочку проходит транзитный трафик. * '''OUTPUT''' — эта цепочка позволяет обрабатывать трафик, исходящий от самого хоста. Так как эта таблица появилась относительно недавно, ее редко можно увидеть на схемах следования пакетов через цепочки и таблицы {{w |netfilter}}'а. Поэтому стоит отметить, что все цепочки таблицы security пакеты проходят непосредственно после одноименных цепочек таблицы filter. ==== Действия ==== Данная таблица добавлена в ядро [[w:Ядро Linux|Linux]] в версии 2.6.27. Ранее операции с метками безопасности выполнялись в таблице mangle, и в целях обратной совместимости все действия, разрешенные для таблицы security, можно использовать и в таблице mangle. * '''SECMARK''' — устанавливает для пакета контекст безопасности {{w |SELinux}} (единственная допустимая опция <tt>--selctx</tt>). * '''CONNSECMARK''' — позволяет скопировать контекст безопасности SELinux с отдельного пакета на соединение в целом (опция <tt>--save</tt>) и наоборот (опция <tt>--restore</tt>). === Таблица raw === Предназначена для выполнения действий с пакетами до их обработки системой [[conntrack]]. Обратите внимание, что в данной таблице не будут срабатывать критерии, которым для корректной работы необходим conntrack (это критерии conntrack, connmark, connlimit, connbytes). ==== Цепочки ==== * '''PREROUTING''' — в эту цепочку входящие пакеты попадают раньше, чем в любую другую из цепочек iptables, и ''до'' обработки их системой conntrack. * '''OUTPUT''' — аналогично для пакетов, сгенерированных самим хостом. ==== Действия ==== <!-- В таблице raw целесообразно применять действие '''NOTRACK''', позволяющее предотвратить обработку пакетов системой conntrack. Разумеется, применять ее стоит не ко всем пакетам подряд, а только к тем, для которых такая обработка не нужна и даже вредна. Например, к пакетам, к которым впоследствии применяется действие TARPIT (см. выше). --> * '''NOTRACK''' — позволяет предотвратить обработку пакетов системой conntrack. Разумеется, применять его стоит не ко всем пакетам подряд, а только к тем, для которых такая обработка не нужна и даже вредна. Например, к пакетам, к которым впоследствии применяется действие TARPIT (см. выше). * '''CT''' — более функциональный инструмент, добавленный в версии [[w:Ядро Linux|Linux]] 2.6.34. Позволяет задать различные настройки [[conntrack]], в соответствии с которыми будет обрабатываться соединение, открытое данным пакетом. В частности, можно: :* Отключить отслеживание соединения (опция <tt>--notrack</tt>). Таким образом, функциональность действия CT включает и функциональность NOTRACK, так что, возможно, действие NOTRACK будет объявлено устаревшим. :* Задать вспомогательный модуль (conntrack helper) для данного соединения. Если раньше указать нестандартные порты для такого модуля можно было только в параметрах его загрузки (<tt>/etc/modprobe.conf</tt> или <tt>/etc/modprobe.d/netfilter.conf</tt>, например, <tt>options nf_conntrack_ftp ports=2121</tt>), то теперь это можно сделать и через правила netfilter: <syntaxhighlight lang="bash"> iptables -t raw -I PREROUTING -p tcp --dport 2121 -j CT --helper ftp </syntaxhighlight> :* Ограничить список событий conntrack, которые будут генерироваться для данного соединения. Например, правило <syntaxhighlight lang="bash"> iptables -t raw -I PREROUTING -p tcp --dport 8000 -j CT --ctevents new,destroy </syntaxhighlight> : будет предписывать для всех соединений на {{w |TCP}}-[[w:Порт (компьютерные сети)|порт]] 8000 генерировать только события «открытие соединения» (NEW) и «завершение соединения» (DESTROY), игнорируя все прочие события. Полный список возможных событий: new, related, destroy, reply, assured, protoinfo, helper, mark, natseqinfo, secmark. :* Задать ''зону conntrack'' для данного пакета (параметр <tt>--zone</tt>). Механизм зон conntrack позволяет корректно отслеживать, фильтровать и {{w |NAT}}'ить соединения даже в том случае, если хост подключен к нескольким сетям, использующим одинаковые пространства имен, через различные интерфейсы (например, интерфейсы eth0 и eth1 подключены к двум разным сетям, но обе эти сети используют пространство 192.168.0.0/24). Традиционно, для идентификации соединений conntrack использует кортежи (tuples) — набор значений в который входят адреса и порты (в случае ICMP — типы и коды ICMP) источника и назначения при передаче данных в прямом и обратном направлении. Очевидно, что при наличии нескольких подсетей с одинаковыми адресными пространствами, возможно возникновение путаницы, когда сразу нескольким соединениям ставится в соответствие одна и та же запись в таблице соединений. Чтобы избежать такой ситуации, в кортеж был добавлен идентификатор зоны conntrack — целое число, которое можно устанавливать через специальное правило в таблице raw в зависимости от входящего/исходящего интерфейса (как уже говорилось выше, цепочки таблицы raw пакеты проходят еще до обработки их conntrack’ом). Например, <syntaxhighlight lang="bash"> iptables -t raw -I PREROUTING -i eth1 -j CT --zone 1 iptables -t raw -I OUTPUT -o eth1 -j CT --zone 1 </syntaxhighlight> : Таким образом, пакеты, входящие или исходящие через интерфейс eth1, будут получать идентификатор зоны 1, в то время как пакеты интерфейса eth0 будут по-прежнему использовать зону по умолчанию (идентификатор 0), и путаницы не произойдет. : Кроме того, идентификатор зоны можно задать для каждого интерфейса через {{w |sysfs}}, минуя iptables (псевдофайл <tt>/sys/class/net/имя_интерфейса/nf_ct_zone</tt>): <syntaxhighlight lang="bash"> echo 1 > /sys/class/net/eth1/nf_ct_zone </syntaxhighlight> : Однако, стоит заметить, что iptables/netfilter позволяют реализовать более гибкую логику управления идентификатором зоны, опирающуюся на различные параметры пакетов, и поэтом данный параметр действия CT может быть полезен при решении различных сложных задач управления трафиком при использовании зон conntrack. * '''RAWDNAT''' — позволяет выполнять [[w:NAT|«проброс»]] адресов и портов «сырым» методом — без использования системы conntrack, то есть без учета состояний соединений. Это действие реализовано в рамках проекта xtables-addons. Применять его можно только в таблице raw. Имеет единственную опцию <tt>--to-destination ''адрес''[/''маска'']</tt>, по смыслу аналогичную опции <tt>--to</tt> действия NETMAP, то есть при указании маски заменяются только те биты в адресе, которые соответствуют единичным битам маски. Биты адреса, соответствующие нулевым битам маски, остаются неизменными. При отсутствии маски изменяется весь адрес. : Отметим, что в отличие от действий [[#Таблица nat|таблицы nat]], которые работают только с соединениями в целом, операции «сырого» преобразования адресов работают только с отдельными пакетами, никак не учитывая контекст их передачи. Вышесказанное можно проиллюстрировать, скажем, таким простым примером: для элементарной операции «проброса» внешнего адреса на другой адрес при использовании обычных операций NAT достаточно одного правила<ref>На самом деле, для «чистого» проброса адреса, даже при использовании stateful NAT, необходимо обычно два или три правила, в частности, для проброса соединений с самого сервера в цепочке OUTPUT. Более подробно это описано при рассмотрении операции DNAT [[#Таблица nat|таблицы nat]], и здесь, с целью упрощения понимания примера, эти аспекты опущены</ref> <syntaxhighlight lang="bash"> iptables -t nat -A PREROUTING -i eth0 -d 212.201.100.135 -j DNAT --to-destination 199.181.132.250 </syntaxhighlight> : в то время как для той же операции при использовании «сырых» преобразований необходимо минимум два правила <syntaxhighlight lang="bash"> iptables -t raw -A PREROUTING -i eth0 -d 212.201.100.135 -j RAWDNAT --to-destination 199.181.132.250 iptables -t rawpost -A POSTROUTING -o eth0 -s 199.181.132.250 -j RAWSNAT --to-source 212.201.100.135 </syntaxhighlight> : Как уже говорилось выше, при использовании обычной операции DNAT в ответных пакетах, приходящих с пробрасываемого адреса (199.181.132.250), производится автоматическая (без необходимости писать для этого отдельные правила) подмена исходного адреса на изначальный (212.201.100.135), и обращающиеся по адресу 212.201.100.135 хосты даже не подозревают, что общаются с кем-то другим. В случае же «сырого» преобразования такая автоматическая обработка невозможна, так как она требует возможности проверять пакеты на принадлежность соединению. С другой стороны, операции «сырого» преобразования являются более гибким инструментом, а также могут работать даже с UNTRACKED и INVALID-пакетами. === Таблица rawpost === Данная таблица предназначена для выполнения операций «сырого» преобразования адресов (без использования информации о соединениях), которые не могут быть реализованы в рамках таблицы raw, а именно, для операции «сырой» подмены исходного адреса ({{w |маскарадинг}}а). Как и в таблице raw, в rawpost отсутствует возможность обращения к [[conntrack]], поэтому критерии, использующие эту подсистему (conntrack, connmark, connlimit, connbytes), в этой таблице работать не будут. Данная таблица реализована в рамках проекта xtables-addons и отсутствует в стандартном комплекте iptables/netfilter. ==== Цепочки ==== * '''POSTROUTING''' — обрабатывает весь исходящий трафик. ==== Действия ==== В таблице rawpost можно использовать действие '''RAWSNAT''', выполняющее операцию «сырой» подмены исходного адреса. Имеет единственную опцию <tt>--to-source ''адрес''[/''маска'']</tt>, позволяющую задать новый исходный адрес для обрабатываемых пакетов. Как обычно, при наличии маски, в обрабатываемых адресах изменяются только те биты, которые в маске установлены в единицу, при отсутствии маски адрес изменяется целиком. Например, если по правилу <syntaxhighlight lang="bash"> iptables -t rawpost -A POSTROUTING -o eth0 -s 10.125.0.0/16 -d 172.18.1.100 -j RAWSNAT --to-source 192.168.0.20/16 </syntaxhighlight> будет обработан пакет с исходным адресом 10.125.32.28, то этот адрес будет заменен на 192.168.32.28. Если же при задании правила маску /16 в параметре <tt>--to-source</tt> опустить, адрес будет заменен на 192.168.0.20. Но так лучше не делать, потому что мы выполняем трансляцию для всех пакетов из подсети 10.125.0.0/16, и без отслеживания соединений не сможем отличить, какие пакеты следует вернуть 10.125.32.28, а какие — другим хостам из этой подсети. Сама же операция «возвращения» пакетов требует отдельного RAWDNAT-правила: <syntaxhighlight lang="bash"> iptables -t raw -A PREROUTING -i eth0 -s 172.18.1.100 -d 192.168.0.0/16 -j RAWDNAT --to-destination 10.125.0.0/16 </syntaxhighlight> которое выполняет обратную подмену, заменяя адреса назначения в пакетах-ответах. Таким образом, хост 172.18.1.100 будет считать, что к нему обращаются хосты из подести 10.125.0.0/16, а вовсе не из 192.168.0.0/16. Для сравнения, с использованием stateful-преобразования достаточно одного правила <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -o eth0 -s 10.125.0.0/16 -d 172.18.1.100 -j NETMAP --to 192.168.0.0/16 </syntaxhighlight> которое будет обеспечивать все необходимые преобразования адресов. Заметим, что для корректной работы обеих описанных конфигураций требуется, чтобы хост 172.18.1.100, а также маршрутизаторы на пути от нашего хоста к нему, считали наш хост шлюзом для сети 192.168.0.0/16. == Критерии == Напоминаем, критерий — это логическое выражение, определяющее, соответствует ли пакет или соединение данному конкретному правилу. В одном правиле можно указать несколько критериев. Для того, чтобы пакет был обработан правилом, должны выполняться ''все'' критерии, то есть критерии неявно объединяются логическим AND. Также многие критерии и параметры критериев можно инвертировать, поставив перед ними восклицательный знак. В описании синтаксиса таких критериев присутствует пометка «<tt>[!]</tt>». Инверсия меняет смысл критерия или его параметра на ровно противоположный. Например, критерию <tt>-s 127.0.0.1</tt> соответствуют все пакеты, имеющие обратный адрес 127.0.0.1, а критерию <tt>! -s 127.0.0.1</tt> — все пакеты, ''кроме'' имеющих обратный адрес 127.0.0.1. В ранних версиях iptables восклицательный знак можно было ставить между названием критерия и значением, например, <tt>-s ! 127.0.0.1</tt>, однако последние версии iptables (в частности, 1.4.3.2 и выше), уже не поддерживают этот синтаксис, выдавая следующую ошибку: Using intrapositioned negation (`--option ! this`) is deprecated in favor of extrapositioned (`! --option this`). Далее мы кратко рассмотрим наиболее важные и интересные критерии. === Универсальные критерии === Под этим термином понимаются критерии, применимые ко все пакетам и соединениям, независимо от протокола транспортного уровня, и не требующие подключения внешних модулей (<tt>-m</tt>). * <tt>[!] '''-p'''</tt>, <tt>--protocol ''протокол''</tt> Позволяет указать протокол транспортного уровня. Наиболее часто употребляются <tt>[[tcp]]</tt>, <tt>[[udp]]</tt>, <tt>[[icmp]]</tt> и <tt>all</tt>. Протокол также можно указать с помощью номера или названия согласно перечню, приведенному в <tt>/etc/protocols</tt>. Значение «любой протокол» можно указать с помощью слова <tt>all</tt> или числа 0. Если протокол не указан, подразумевается «любой протокол». При указании протокола становится возможным использовать специфичные для него критерии. Например, для {{w |TCP}} и {{w |UDP}} доступны критерии <tt>--sport</tt> и <tt>--dport</tt>, для {{w |ICMP}} — <tt>--icmp-type</tt>. Подробнее эти критерии будут рассмотрены ниже. * <tt>[!] '''-s'''</tt>, <tt>--src</tt>, <tt>--source ''адрес''[/''маска''][,''адрес''[/''маска'']...]</tt> Определяет адрес отправителя. В качестве адреса может выступать {{w |IP-адрес}} (возможно с [[w:Маска подсети|маской]]), имя хоста из /etc/hosts, или {{w |доменное имя}} (в последних двух случаях перед добавлением правила в цепочку имя [[w:DNS|резольвится]] в IP-адрес). Маска подсети может быть указана в классическом формате (например, 255.255.0.0) либо в формате {{w |CIDR}} (например, 16)<ref>Заметим, что для расчета масок подсетей и диапазонов адресов существует очень удобная утилита [[ipcalc]].</ref>. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -i eth0 -s 192.168.0.0/16 -j DROP </syntaxhighlight> (где eth0 — интерфейс, подключенный к интернету), позволяет заблокировать простейший вид {{w |спуфинг}}а — из интернета ''не могут'' приходить пакеты с обратным адресом, принадлежащим к диапазону, зарезервированному для локальных сетей. Начиная с версии iptables 1.4.6, в одном параметре <tt>-s</tt> можно указывать более одного адреса, разделяя адреса запятой. При этом для каждого адреса будет добавлено ''отдельное'' правило. Например, запись <syntaxhighlight lang="bash"> iptables -A INPUT -i eth0 -s 192.168.0.0/16,172.16.0.0/12,10.0.0.0/8 -j DROP </syntaxhighlight> эквивалентна записи <syntaxhighlight lang="bash"> iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP </syntaxhighlight> При добавлении через команду <tt>-A</tt> (вставка в конец цепочки) порядок добавляемых правил будет соответствовать порядку перечисления адресов в исходной команде, при использовании команды <tt>-I</tt> (вставка в начало цепочки либо после заданного правила) порядок будет обратным исходному. Настойчиво не рекомендуется использовать доменные имена, для разрешения (резольва) которых требуются {{w |DNS}}-запросы, так как на этапе конфигурирования фаервола DNS может работать некорректно. Также, заметим, имена резольвятся всего один раз — при добавлении правила в цепочку. Впоследствии соответствующий этому имени IP-адрес может измениться, но на уже записанные правила это никак не повлияет (в них останется старый адрес). Если указать доменное имя, которое резольвится в несколько {{w |IP-адрес}}ов, то для каждого адреса будет добавлено отдельное правило (как и в случае перечисления нескольких адресов, см. выше). * <tt>[!] '''-d'''</tt>, <tt>--dst</tt>, <tt>--destination ''адрес''[/''маска''][,''адрес''[/''маска'']...]</tt> Определяет адрес получателя. Синтаксис аналогичен <tt>-s</tt>. Заметим, что, если использовать возможность указания нескольких адресов (перечислив их явно или указав доменное имя, резольвящееся на несколько адресов) ''одновременно'' в параметрах <tt>-s</tt> и <tt>-d</tt>, то на каждое возможное сочетание адресов будет добавлено свое правило. Например, запись <syntaxhighlight lang="bash"> iptables -A FORWARD -s 192.168.1.1,192.168.1.2 -d 192.168.1.3,192.168.1.4 -j REJECT </syntaxhighlight> эквивалентна <syntaxhighlight lang="bash"> iptables -A FORWARD -s 192.168.1.1 -d 192.168.1.3 -j REJECT iptables -A FORWARD -s 192.168.1.1 -d 192.168.1.4 -j REJECT iptables -A FORWARD -s 192.168.1.2 -d 192.168.1.3 -j REJECT iptables -A FORWARD -s 192.168.1.2 -d 192.168.1.4 -j REJECT </syntaxhighlight> * <tt>[!] '''-i'''</tt>, <tt>--in-interface ''имя_интерфейса''</tt> Определяет входящий сетевой интерфейс. Если указанное имя интерфейса заканчивается знаком «+» (например, <tt>tun+</tt>), то критерию соответствуют все интерфейсы, чьи названия начинаются на указанное имя (для нашего примера tun0, tun1, …). Данный критерий можно использовать в цепочках PREROUTING, INPUT и FORWARD. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -i lo -j ACCEPT </syntaxhighlight> позволит принимать весь трафик, входящий через интерфейс [[w:Loopback|обратной петли]]. * <tt>[!] '''-o'''</tt>, <tt>--out-interface ''имя_интерфейса''</tt> Определяет исходящий сетевой интерфейс. Синтаксис аналогичен <tt>-i</tt>. Критерий можно использовать в цепочках FORWARD, OUTPUT и POSTROUTING. Вспоминая один из наших примеров, <syntaxhighlight lang="bash"> iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE </syntaxhighlight> будет [[w:Маскарадинг|маскарадить]] весь трафик, исходящий через интерфейс eth0. === Критерии, специфичные для протоколов === ==== Протоколы [[w:Транспортный уровень|транспортного уровня]] ==== ===== {{w |TCP}} ===== * <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt> Позволяет указать исходящий порт (или их диапазон). Например, <syntaxhighlight lang="bash"> iptables -I INPUT -m conntrack --ctstate NEW -p tcp --sport 0:1023 -j DROP </syntaxhighlight> заблокирует все исходящие соединения с [[w:Список портов TCP и UDP|привилегированных]] портов (''привилегированными'' в TCP/UDP считаются порты с 0 по 1023 включительно, так как для их использования нужны привилегии [[w:Root|суперпользователя]], и обычно такие порты используются [[w:Демон (программа)|демонами]] только в режиме прослушивания). * <tt>[!] '''--dport'''</tt>, <tt>--destination-port ''порт''[:''порт'']</tt> Позволяет указать порт назначения (или их диапазон). Синтаксис аналогичен <tt>--sport</tt>. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -p tcp --dport 80 -j ACCEPT </syntaxhighlight> разрешит все входящие пакеты на 80 порт ({{w |HTTP}}). * <tt>[!] '''--tcp-flags''' ''маска'' ''установленные_флаги''</tt> Позволяет указать список установленных и снятых [[w:TCP#Флаги (управляющие биты)|TCP-флагов]]. В ''маске'' перечисляются (через запятую, без пробелов) все проверяемые флаги, далее, после пробела, перечисляются (также через запятую) те из них, которые должны быть установлены. Все остальные перечисленные в маске флаги должны быть сняты. Возможные флаги: SYN ACK FIN RST URG PSH. Также можно использовать псевдофлаги ALL и NONE, обозначающие «все флаги» и «ни одного флага» соответственно. Пример: <syntaxhighlight lang="bash"> iptables -I INPUT -p tcp --tcp-flags SYN,RST,ACK,FIN SYN -j LOG --log-level DEBUG --log-prefix "TCP SYN: " </syntaxhighlight> будет заносить в лог все входящие TCP SYN-пакеты. У обычного SYN-пакета всегда установлен флаг SYN и сняты флаги RST, ACK и FIN. Другой пример: <syntaxhighlight lang="bash"> iptables -I INPUT -m conntrack --ctstate NEW,INVALID -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT --reject-with tcp-reset </syntaxhighlight> будет препятствовать {{w |спуфинг}}у от нашего имени. Ведь если мы получаем пакет с установленными флагами SYN и ACK (такой комбинацией флагов обладает только ответ на SYN-пакет) по еще не открытому соединению, это означает, что кто-то послал другому хосту SYN-пакет от нашего имени, и ответ пришел к нам. Однако добавление такого правила в конфигурацию фаервола ''не рекомендуется'', поскольку стандартом также предусмотрено использование случайного начального номера последовательности для каждого нового TCP-соединения, как раз для предотвращения возможности спуфинг-атаки. Шансов угадать начальный номер у злоумышленника практически нет, тогда как наш ответ RST-пакетом на такой пакет может серьезно нарушить работоспособность некоторых систем защиты от DoS-атак, полагающихся на метод, называемый out-of-sequence ACK. В случае добавления этого правила в конфигурацию фаервола, системы защиты будут считать, что, раз уж мы отвечаем RST на out-of-sequence ACK, вы действительно пытались установить соединение с ресурсом, и пропустят все последующие поддельные пакеты злоумышленника, отправленные от вашего имени. В результате вы заметно облегчите злоумышленнику осуществление DoS-атаки от вашего имени, и при расследовании этого эпизода следы приведут к вам. * <tt>[!] '''--syn'''</tt> Позволяет отлавливать TCP SYN-пакеты (сокращение для <tt>--tcp-flags SYN,RST,ACK,FIN SYN</tt>). Так что приведенный выше пример про логгирование SYN-пакетов можно записать в виде <syntaxhighlight lang="bash"> iptables -I INPUT -p tcp --syn -j LOG --log-level DEBUG --log-prefix "TCP SYN: " </syntaxhighlight> Более интересный пример: <syntaxhighlight lang="bash"> iptables -I INPUT -m conntrack --ctstate NEW -p tcp ! --syn -j DROP </syntaxhighlight> будет блокировать все попытки открыть входящее TCP-соединение ''не'' SYN-пакетом. Попытка установить соединение таким образом может быть либо ошибкой, либо атакой. * <tt>[!] '''--tcp-option''' ''номер''</tt> Позволяет проверить, установлена ли в заголовке TCP-пакета соответствующая опция. Полный список опций с их номерами представлен [http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml на сайте IANA]. ===== {{w |UDP}} ===== * <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt> Позволяет указать исходящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP. * <tt>[!] '''--dport'''</tt>, <tt>--destination-port ''порт''[:''порт'']</tt> Позволяет указать входящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP. ===== {{w |SCTP}} ===== * <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt> Позволяет указать исходящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP. * <tt>[!] '''--dport'''</tt>, <tt>--destination-port ''порт''[:''порт'']</tt> Позволяет указать входящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP. * <tt>[!] '''--chunk-types''' {all|any|only} ''тип_секции''[:''флаги''][,''тип_секции''[:''флаги'']...]</tt> Позволяет анализировать набор [[:en:SCTP packet structure|секций (chunks)]], входящих в состав SCTP-пакета. Возможные типы секций: DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK. Также, для секций, имеющих флаги (DATA, ABORT и SHUTDOWN_COMPLETE) можно проверить состояние флагов, указав соответствующие буквы после названия секции (для DATA — U, B и E, для ABORT и SHUTDOWN_COMPLETE — T). Литера в верхнем регистре предполагает установленный флаг, в нижнем — снятый. Ключевое слово в начале позволяет определить логику работы: в случае <tt>all</tt> должны присутствовать ''все'' перечисленные секции, для <tt>any</tt> — хотя бы одна из них, для <tt>only</tt> — пакет должен состоять только из перечисленных секций. Примеры: <syntaxhighlight lang="bash"> iptables -I INPUT -p sctp --chunk-types only DATA,INIT -j DROP </syntaxhighlight> заблокирует все входящие SCTP-пакеты, состоящие только из секций DATA и INIT, а <syntaxhighlight lang="bash"> iptables -I INPUT -p sctp --chunk-types any DATA:Be -j ACCEPT </syntaxhighlight> разрешит входящие SCTP-пакеты, содержащие секцию DATA с установленным флагом B и снятым флагом E, то есть первый фрагмент фрагментированной DATA-секции. ===== {{w |DCCP}} ===== * <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt> Позволяет указать исходящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP. * <tt>[!] '''--dport'''</tt>, <tt>--destination-port ''порт''[:''порт'']</tt> Позволяет указать входящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP. * <tt>[!] '''--dccp-types''' ''маска''</tt> Позволяет указать тип DCCP-пакета. В ''маске'' через запятую перечисляются DCCP-типы (допустимые названия: REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID). Пакет считается удовлетворяющим критерию, если имеет один из типов, перечисленных в маске. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -p dccp --dccp-types RESET,INVALID -j LOG --log-level DEBUG --log-prefix "DCCP RESET or INVALID: " </syntaxhighlight> занесет в лог все входящие RESET и INVALID DCCP-пакеты. ===== {{w |UDP Lite}} ===== Поддержка специфических опций протокола UDPLite (а именно, проверки портов источника и/или назначения) в netfilter реализована не вполне очевидным образом: через критерий multiport (см. раздел [[#Вспомогательные критерии|вспомогательные критерии]]). Если для обычного {{w |UDP}} соответствие номера порта проверялось выражением вида <tt>-p udp --dport ''номер_порта''</tt> (или <tt>-p udp --sport ''номер_порта''</tt>), то в случае UDPLite аналогичное выражение будет выглядеть как <tt>-p udplite -m multiport --dports ''номер_порта''</tt> (или <tt>-p udplite -m multiport --sports ''номер_порта''</tt>). Все опции критерия multiport для UDPLite поддерживаются в полном объеме. ==== {{w |IPv4}} ==== Ниже перечислены критерии, которые реализованы только для протокола IPv4 и, соответственно, могут быть вызваны только через iptables, но не через ip6tables. * <tt>[!] '''-f'''</tt>, <tt>--fragment</tt> Проверка фрагментации: критерию соответствуют только фрагменты пакета, начиная со второго фрагмента. Пример: <syntaxhighlight lang="bash"> iptables -I INPUT -p icmp -f -j DROP </syntaxhighlight> блокирует фрагменты {{w |ICMP}}-пакетов. Так как, в силу функционального назначения протокола, ICMP-пакеты должны быть очень небольшими и нормально укладываться в {{w |MTU}}, наличие их фрагментов обычно свидетельствует об ошибке или попытке атаки. У второго и последующего фрагментов нет заголовка транспортного уровня, поэтому бессмысленно пытаться использовать для них критерии номеров [[w:Порт (компьютерные сети)|TCP/UDP-портов]] или типа ICMP. * '''addrtype''' — позволяет проверить тип адреса источника и/или назначения с точки зрения подсистемы маршрутизации сетевого стека ядра. Допустимые типы адресов: UNSPEC (адрес 0.0.0.0), [[w:Unicast|UNICAST]], LOCAL (адрес принадлежит нашему хосту), [[w:Broadcast|BROADCAST]], [[w:Anycast|ANYCAST]], [[w:Мультивещание|MULTICAST]], [[:en:Black hole (networking)|BLACKHOLE]], UNREACHABLE, PROHIBIT, THROW, NAT, XRESOLVE. Подробнее о большинстве перечисленных типов адресов и их использовании в [[w:Ядро Linux|Linux]] (точнее, в подсистеме {{w |iproute2}}) можно почитать [http://linux-ip.net/html/routing-tables.html здесь]. Данный критерий поддерживает следующие параметры: <tt>[!] --src-type ''тип''[,''тип''...]</tt> — проверка, принадлежит ли исходный адрес пакета одному из перечисленных типов. <tt>[!] --dst-type ''тип''[,''тип''...]</tt> — проверка, принадлежит ли адрес назначения пакета одному из перечисленных типов. <tt>--limit-iface-in</tt> — ограничивает проверку типа адреса только записями для интерфейса, через который пакет вошел на хост. Допускается использовать этот параметр только в цепочках PREROUTING, INPUT и FORWARD. <tt>--limit-iface-out</tt> — ограничивает проверку типа адреса только записями для интерфейса, через который пакет вышел с хоста. Допускается использовать этот параметр только в цепочках POSTROUTING, OUTPUT и FORWARD. Критерии <tt>--limit-iface-in</tt> и <tt>--limit-iface-out</tt> нельзя указывать одновременно. В качестве практического примера использования данного критерия можно привести простейшую защиту от {{w |спуфинг}}а: <syntaxhighlight lang="bash"> iptables -I INPUT -m addrtype --src-type LOCAL ! -i lo -j DROP </syntaxhighlight> Это правило заблокирует пакеты, которые пришли с внешних интерфейсов, но при этом в качестве обратного адреса у них указан один из адресов, принадлежащих нашему хосту (например, {{w |127.0.0.1}}). * '''ecn''' — позволяет проверять значения битов [[w:Explicit Congestion Notification|ECN]] в заголовках {{w |TCP}} и {{w |IPv4}}. Допустимые параметры: <tt>[!] --ecn-tcp-cwr</tt> — проверка флага ECN CWR (Congestion Window Received) в TCP-заголовке пакета. <tt>[!] --ecn-tcp-ece</tt> — проверка флага ECN ECE (ECN Echo) в TCP-заголовке пакета. <tt>[!] --ecn-ip-ect ''значение''</tt> — проверка значения, сформированного ECN-битами поля [[w:Тип обслуживания|TOS]] (последние два бита). Возможные значения от 0 до 3. * '''realm''' — проверка области маршрутизации (realm) пакета. Имеет единственный параметр <tt>[!] --realm ''значение''[/''маска'']</tt>, позволяющий указать численный идентификатор области. Если указана маска, то значение realm каждого проверяемого пакета сначала объединяется с маской при помощи [[w:Битовые операции#Побитовое И (AND)|побитового AND]], а затем сравнивается со значением, указанным в правиле. Также вместо числа можно указать символьное название области согласно обозначениям в файле <tt>/etc/iproute2/rt_realms</tt> (в этом случае маску использовать нельзя). * '''ttl''' — обеспечивает проверку поля [[w:Time to live|TTL]] в заголовке пакета. Позволяет установить, является ли значение TTL проверяемого пакета большим (<tt>--ttl-gt</tt>), меньшим (<tt>--ttl-lt</tt>), равным или не равным (<tt>[!] --ttl-eq</tt>) указанному значению. ===== {{w |ICMP}} ===== ICMP является протоколом контрольных сообщений IPv4. Несмотря на то, что ICMP формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (<tt>-p</tt>), а не для вспомогательного критерия (<tt>-m</tt>), де-факто этот протокол неотделим от IPv4, и поэтому соответствующий критерий может использоваться только в iptables, но не в ip6tables. Критерий этого протокола имеет единственный параметр <tt>[!] '''--icmp-type''' ''тип''</tt> — обеспечивает проверку [[w:ICMP#Типы ICMP пакетов (полный список)|типа]] ICMP-пакета. Список возможных типов выводится по команде <tt>iptables -p icmp -h</tt>. Также можно указать стандартные числовые тип и, при необходимости, код. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -p icmp --icmp-type echo-request -j ACCEPT </syntaxhighlight> как и аналогичное <syntaxhighlight lang="bash"> iptables -I INPUT -p icmp --icmp-type 8 -j ACCEPT </syntaxhighlight> пропустят все входящие ICMP-эхо-запросы (пинги). ==== {{w |IPv6}} ==== Ниже перечислены критерии, которые реализованы только для протокола IPv6 и, соответственно, могут быть вызваны только через ip6tables, но не через iptables. Особо отметим, что критерии для некоторых подзаголовков IPv6 (dst, frag, hbh, rt) корректно вызываются ''только'' с использованием синтаксиса для расширенных критериев (ключ <tt>-m</tt>), хотя имеют номера протоколов в <tt>/etc/protocols</tt> и, формально, могут быть вызваны с использованием синтаксиса для протоколов (ключ <tt>-p</tt>) что, однако, является неверным. В таких случаях ip6tables выдает предупреждение вида <syntaxhighlight lang="text"> Warning: never matched protocol: ipv6-frag. use extension match instead. </syntaxhighlight> гласящее, что в такое правило никогда не будет срабатывать. Если вы видите подобное предупреждение, удалите правило, которое его вызвало, и перепишите это правило с использованием корректного синтаксиса (<tt>-m</tt>). С другими же критериями, которые представляют более или менее самостоятельные протоколы ({{w |ICMPv6}}, [[MH]], {{w |IPSec}} [[:en:IPSec#Authentication Header|AH]] и [[:en:IPSec#Encapsulating Security Payload|ESP]]), все ровно наоборот, и для них корректным будет использование именно синтаксиса протокола (ключ <tt>-p</tt>), а не расширенного критерия. Во избежание путаницы, такие критерии вынесены в отдельные подзаголовки, по аналогии с протоколами транспортного уровня (выше). * '''dst''' — проверят опции назначения (подзаголовок 60 Destination Options). Имеет две опции: <tt>[!] --dst-len ''значение''</tt> — проверяет длину подзаголовка; <tt>[!] --dst-opts ''код''[:''длина''][,''код''[:''длина'']...]</tt> — позволяет проверить вхождение в данный подзаголовок конкретных опций. Также можно проверить длину каждой из них. Можно указать до 16 опций (представленных числовыми кодами), разделяя их запятой. * '''eui64''' — сравнивает младшие 64 бита исходного IPv6-адреса с битами исходного {{w |MAC-адрес}}а, преобразованными согласно правилам автоконфигурирования IPv6-адресов на основании MAC-адресов. Таким образом, позволяет проверить, является ли IPv6-адрес отправителя пакета автоматически сконфигурированным (работает, если отправитель находится в одном [[w:Широковещательный домен|широковещательном домене]] с нашим хостом, так как в противном случае сохранность MAC-адреса отправителя не может быть гарантирована). * '''frag''' — позволяет проверять параметры фрагментации (подзаголовок 44 Fragment). Допустимые опции: <tt>[!] --fragid ''мин''[:''макс'']</tt> — сверяет величину идентификатора фрагмента. Если указано одно значение, проверяется равенство, если указан диапазон — проверяется вхождение значения в этот диапазон (включая границы). <tt>--fragres</tt> — проверяет, заполнены ли нулями зарезервированные поля заголовка (биты 29-30). <tt>--fragfirst</tt> — проверяет, является ли данный фрагмент первым в последовательности. <tt>--fraglast</tt>/<tt>--fragmore</tt> — проверяют M-флаг, показывающий, является ли данный фрагмент последним в последовательности (в этом случае <tt>--fraglast</tt> дает истину, а <tt>--fragmore</tt> ложь), или после него должны быть еще фрагменты (соответственно, наоборот). Эти две опции являются взаимоисключающими. Также в документации можно найти упоминание параметра <tt>--fraglen </tt>, который якобы проверяет длину подзаголовка Fragment. Однако, согласно текущим соглашениям, длина этого подзаголовка фиксирована и равна 8 {{w |байт}}ам, а названная опция ни на что не влияет. * '''hbh''' — проверяет опции Hop-by-Hop (подзаголовок 0 Hop-by-Hop). Синтаксис аналогичен параметру dst. * '''hl''' — обеспечивает проверку поля Hop Limit в IPv6-заголовке. Позволяет установить, является ли значение HL проверяемого пакета большим (<tt>--hl-gt</tt>), меньшим (<tt>--hl-lt</tt>), равным или не равным (<tt>[!] --hl-eq</tt>) указанному значению. * '''ipv6header''' — позволяет проверить наличие вспомогательных подзаголовков IPv6. Допустимыми типами заголовков являются: hop (hop-by-hop 0), dst (ipv6-opts 60), route (ipv6-route 43), frag (ipv6-frag 44), auth (ah 50), esp (esp 59). В скобках указаны «длинные» названия и числовые идентификаторы протокола. Используя опцию <tt>[!] --header ''тип''[,''тип''...]</tt> вы можете указывать любые из этих обозначений — короткие названия, длинные названия или числовые идентификаторы. Отметим, что пакет будет соответствовать критерию в том случае, если будет содержать ''только'' перечисленные подзаголовки. Изменить это поведение можно, указав опцию <tt>--soft</tt> — в этом случае достаточно, чтобы пакет содержал хотя бы один из перечисленных подзаголовков. * '''rt''' — позволяет проверять параметры маршрутизации пакета (подзаголовок 43 Routing). Допустимые параметры: <tt>[!] --rt-type ''тип''</tt> — тип маршрутизации (0, 1 или 2); <tt>[!] --rt-segsleft ''мин''[:''макс'']</tt> — проверка значения поля Segment Left (показывает, сколько еще узлов должен пройти данный пакет, прежде чем достигнет цели); <tt>[!] --rt-len ''значение''</tt> — проверка длины всего подзаголовка. Следующие три параметра работают для типа 0 (<tt>--rt-type 0</tt>): <tt>--rt-0-res</tt> — проверять зарезервированные поля; <tt>--rt-0-addrs ''адрес''[,''адрес''...]</tt> — проверяет адреса, перечисленные в подзаголовке. Можно указать не более 16 адресов, разделяя их запятыми. Пакет считается удовлетворяющим критерию, если подзаголовок содержит все адреса, которые были перечислены в правиле, в том же порядке; <tt>--rt-0-not-strict</tt> — делает условие проверки по предыдущем параметру не таким жестким: достаточно, чтобы хотя бы один из перечисленных адресов совпадал с соответствующим адресом в подзаголовке, при соблюдении порядка перечисления. ===== {{w |ICMPv6}} ===== ICMPv6 является протоколом контрольных сообщений IPv6. Несмотря на то, что ICMPv6 формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (<tt>-p</tt>), а не для вспомогательного критерия (<tt>-m</tt>), де-факто этот протокол неотделим от IPv6, и поэтому соответствующий критерий может использоваться только в ip6tables, но не в iptables. Критерий этого протокола имеет единственный параметр <tt>[!] '''--icmpv6-type''' ''тип''</tt> по смыслу и синтаксису аналогичный параметру <tt>--icmp-type</tt> критерия icmp (см. предыдущий раздел). Например, <syntaxhighlight lang="bash"> ip6tables -I INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT </syntaxhighlight> как и аналогичное <syntaxhighlight lang="bash"> ip6tables -I INPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT </syntaxhighlight> пропустит входящие ICMPv6-эхо-запросы (пинги). Как и в случае icmp, вы можете получить список допустимых типов сообщений, введя <syntaxhighlight lang="bash"> ip6tables -p icmpv6 -h </syntaxhighlight> ===== [[MH]] ===== Критерий mh позволяет определять пакеты с подзаголовком IPv6 Mobility Header ({{RFC|3775}}). Как и в случае с ICMPv6, вызов данного критерия должен выполняться в соответствии с синтаксисом для протокола (через ключ <tt>-p</tt>). Имеет единственную опцию <tt>[!] '''--mh-type''' ''мин''[:''макс'']</tt> позволяющую указать точное значение типа или диапазон допустимых значений. Перечень поддерживаемых типов MH можно получить, введя команду <syntaxhighlight lang="bash"> ip6tables -p mh -h </syntaxhighlight> Также к данному критерию допустимо обращение по названию ipv6-mh (<tt>-p ipv6-mh</tt>). ==== {{w |IPsec}} ==== netfilter «знает» два протокола из семейства IPsec: [[:en:IPSec#Authentication Header|Authentication Header]] (<tt>-p ah</tt>) и [[:en:IPSec#Encapsulating Security Payload|Encapsulating Security Payload]] (<tt>-p esp</tt>). ===== AH ===== Для протокола AH поддерживается единственная опция * <tt>'''--ahspi''' ''значение''[:''значение'']</tt> — позволяет указать значение (или диапазон значений) [[:en:Security Parameter Index|SPI (Security Parameter Index)]]. ===== ESP ===== Протокол ESP имеет аналогичную по смыслу опцию * <tt>'''--espspi''' ''значение''[:''значение'']</tt> В большинстве конфигураций IPsec-пакеты просто пропускаются фаерволом (пусть с ними разбирается IPsec-подсистема): <syntaxhighlight lang="bash"> iptables -I INPUT -p ah -j ACCEPT iptables -I INPUT -p esp -j ACCEPT </syntaxhighlight> === Критерии состояния соединения === ==== conntrack ==== Основной критерий, используемый для контроля состояния соединения. Он предоставляет эффективный набор инструментов, позволяющий использовать информацию системы [[conntrack]] о состоянии соединения. Затронутую тему весьма проблематично осветить в двух словах и привести по ней простые примеры, не выходя за краткий формат, принятый для нашей статьи. Поэтому ограничимся мы подробным рассмотрением лишь наиболее важного параметра данного критерия — ctstate. Для прочих параметров мы лишь кратко опишем синтаксис и назначение. За более подробной информацией обратитесь к документации, прилагаемой к вашему дистрибутиву. Итак, * <tt>[!] '''--ctstate''' ''маска''</tt> ''Маска'' содержит перечисление через запятую список возможных состояний соединения. Пакет считается удовлетворяющим критерию, если соединение, по которому он проходит, находится в одном из перечисленных состояний. Возможные состояния: :* '''NEW''' — соединение не открыто, то есть пакет является первым в соединении. Полезные примеры использования этого состояния приведены выше, в частности, при описании [[#TCP|TCP-специфичных критериев]]. :* '''ESTABLISHED''' — пакет относится к уже установленному соединению. Обычно такие пакеты принимаются без дополнительной фильтрации, как и в случае с RELATED. :* '''RELATED''' — пакет открывает новое соединение, логически связанное с уже установленными, например, открытие канала данных в пассивном режиме {{w |FTP}}. Например: <syntaxhighlight lang="bash"> modprobe nf_conntrack_ftp # Подгружаем модуль для распознавания связанных FTP-соединений # В старых системах этот модуль может называться ip_conntrack_ftp iptables -F # Очищаем все цепочки таблицы filter # Ко всем пакетам, которые относятся к уже установленным соединениям, применяем терминальное действие ACCEPT — пропустить iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 21 -j ACCEPT # Разрешаем открывать соединения на 21 TCP-порт. iptables -P INPUT DROP # В качестве действия по умолчанию устанавливаем DROP — блокирование пакета iptables -P OUTPUT ACCEPT # Разрешаем все исходящие пакеты </syntaxhighlight> Этот набор команд обеспечит функционирование на хосте FTP-сервера с поддержкой как активного, так и пассивного режимов. В пассивном режиме FTP клиент сначала устанавливает управляющее соединение на TCP-порт 21 сервера. Когда возникнет необходимость передачи данных, клиент даст серверу команду PASV. Сервер выберет высокий порт и подключится к нему в режиме прослушивания, отправив номер порта клиенту по управляющему соединению. Система [[conntrack]], при наличии подгруженного модуля ядра nf_conntrack_ftp, зафиксирует это сообщение и выделит номер порта. Когда клиент откроет соединение данных на этот высокий порт, система conntrack присвоит первому пакету статус RELATED, в результате чего пакет пройдет по нашему правилу и будет принят. Остальные пакеты в этом соединении будут иметь уже статус ESTABLISHED и тоже будут приняты. Возможность корректно обрабатывать пассивный режим FTP, как это было описано выше, из всех [[unix]]-фаерволов доступна только в iptables. В других фаерволах для решения данной проблемы используются различные «костыли». Например, в {{w |pf}} управляющие FTP-соединения [http://www.openbsd.org/faq/pf/ftp.html#client пропускаются] через специальную программу [http://www.openbsd.org/cgi-bin/man.cgi?query=ftp-proxy&sektion=8 ftp-proxy], которая анализирует трафик подобно conntrack и «на лету» добавляет правила для соединений данных. Однако даже подобные «костыли» существуют далеко не для всех протоколов. Поэтому можно утверждать, что в данном аспекте iptables находится вне конкуренции. С обработкой активного режима таких проблем не возникает, так как сервер сам устанавливает соединение данных с порта 20, поэтому первый пакет пропускается согласно правилу по умолчанию цепочки OUTPUT. Правда, проблемы могут возникнуть на стороне фаервола клиента, но это уже не относится к компетенции сервера. :* '''INVALID''' — пакет по смыслу должен принадлежать уже установленному соединению (например, ICMP-сообщение port-unreachable), однако такое соединение в системе не зарегистрировано. Обычно к таким пакетам применяют действие DROP: <syntaxhighlight lang="bash"> iptables -I INPUT -m conntrack --ctstate INVALID -j DROP </syntaxhighlight> :* '''UNTRACKED''' — отслеживание состояния соединения для данного пакета было отключено. Обычно оно отключается с помощью действия NOTRACK в таблице raw. :* '''DNAT''' — показывает, что к данному соединению применена операция подмены адреса назначения (об операциях преобразования адресов см. [[#Таблица nat|выше]]). :* '''SNAT''' — показывает, что к данному соединению применена операция подмены адреса источника (об операциях преобразования адресов см. [[#Таблица nat|выше]]). Остальные параметры критерия conntrack, как уже говорилось, мы опишем лишь конспективно. * <tt>[!] '''--ctstatus''' ''маска''</tt> Применяется для определения статуса соединения в системе conntrack. Возможные статусы: :* '''EXPECTED''' — данное соединение ожидалось системой conntrack по результатам анализа других соединений. Например, после того, как клиент и сервер через управляющее {{w |FTP}}-соединение согласуют номер порта для соединения данных в пассивном режиме, система [[conntrack]] на сервере будет ожидать входящее соединение на этот порт. :* '''CONFIRMED''' — подтвержденное соединение. Такой статус присваивается соединению после того, как инициатор начал передачу пакетов. :* '''SEEN_REPLY''' — соединение, по которому поступил ответ, то есть имеет место передача данных в обоих направлениях (поддержка данного состояния появилась сравнительно недавно). :* '''ASSURED''' — соединение можно считать полностью установленным. Этот статус присваивается соединению после передачи определенного количества данных. Присвоение данного статуса приводит к увеличению conntrack-тайм-аута для данного соединения (эти тайм-ауты используются для определения и удаления «повисших» и оборванных соединений). :* '''NONE''' — нет статуса. Соединение не соответствует ни одному из перечисленных критериев. * <tt>[!] '''--ctproto''' ''протокол''</tt> Протокол [[w:Транспортный уровень|транспортного уровня]], определенный системой conntrack. Синтаксис аналогичен стандартному критерию <tt>-p</tt>. * <tt>[!] '''--ctdir''' {ORIGINAL|REPLY}</tt> Позволяет указать направление прохождения пакетов (ORIGINAL — от инициатора к отвечающему, REPLY — наоборот). Если не указывать эту опцию, под критерий будут подпадать пакеты, идущие в обоих направлениях. * <tt>[!] '''--ctorigsrc''' ''адрес''[/''маска'']</tt>, <tt>[!] '''--ctorigdst''' ''адрес''[/''маска'']</tt>, <tt>[!] '''--ctreplsrc''' ''адрес''[/''маска'']</tt>, <tt>[!] '''--ctrepldst''' ''адрес''[/''маска'']</tt> Позволяет определять адреса источника (src) и назначения (dst) при передаче данных от инициатора к отвечающему (orig) и наоборот (repl). Синтаксис аналогичен описанному выше стандартному критерию <tt>-s</tt>. Обычно адрес-порт источника при передаче в прямом направлении совпадают с адресом-портом назначения при передаче в обратном направлении, и наоборот, адрес-порт источника при передаче в обратном направлении совпадает с адресом-портом назначения при передаче в прямом направлении. То есть, если клиент 192.168.1.2 обращается к серверу 192.168.1.1, то с точки зрения системы conntrack ситуация выглядит следующим образом: : → В прямом направлении (от инициатора к отвечающему): :: — Адрес источника (ctorigsrc): 192.168.1.2 (адрес клиента) :: — Адрес назначения (ctorigdst): 192.168.1.1 (адрес сервера) : ← В обратном направлении (от отвечающего к инициатору): :: — Адрес источника (ctreplsrc): 192.168.1.1 (адрес сервера) :: — Адрес назначения (ctrepldst): 192.168.1.2 (адрес клиента) Однако для соединений, к которым применена трансляция адресов или портов, это может не выполняться. Например, рассмотрим ситуацию, когда клиент из нашей подсети (192.168.1.2) обращается к некоторому серверу в интернете (204.152.191.37) через наш сервер (внешний адрес нашего сервера 208.77.188.166, внутренний 192.168.1.1). Для корректной работы такой схемы нужно обеспечить на нашем сервере подмену исходного адреса (SNAT), например, <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.166 </syntaxhighlight> Тогда, с точки зрения системы conntrack нашего сервера, : → В прямом направлении (от инициатора к отвечающему): :: — Адрес источника (ctorigsrc): 192.168.1.2 (внутренний адрес клиента) :: — Адрес назначения (ctorigdst): 204.152.191.37 (адрес интернет-сервера) : ← В обратном направлении (от отвечающего к инициатору): :: — Адрес источника (ctreplsrc): 204.152.191.37 (адрес интернет-севера) :: — Адрес назначения (ctrepldst): 208.77.188.166 (внешний адрес нашего сервера) В том случае, если адрес-порт источника при передаче в прямом направлении отличаются от адреса-порта назначения при передаче в обратном направлении, соединению будет присвоен статус SNAT. Аналогично, если один из внешних адресов нашего сервера «проброшен» на внутренний сервер, например, так <syntaxhighlight lang="bash"> iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2 </syntaxhighlight> то при обращении на этот адрес клиента извне (допустим, все тот же 204.152.191.37), получим : → В прямом направлении (от инициатора к отвечающему): :: — Адрес источника (ctorigsrc): 204.152.191.37 (адрес клиента) :: — Адрес назначения (ctorigdst): 208.77.188.166 (наш внешний адрес) : ← В обратном направлении (от отвечающего к инициатору): :: — Адрес источника (ctreplsrc): 192.168.1.2 (адрес внутреннего сервера) :: — Адрес назначения (ctrepldst): 204.152.191.37 (адрес клиента) В том случае, если адрес-порт назначения при передаче в прямом направлении отличаются от адреса-порта источника при передаче в обратном направлении, соединению будет присвоен статус DNAT. * <tt>[!] '''--ctorigsrcport''' ''порт''</tt>, <tt>[!] '''--ctorigdstport''' ''порт''</tt>, <tt>[!] '''--ctreplsrcport''' ''порт''</tt>, <tt>[!] '''--ctrepldstport''' ''порт''</tt> Позволяет определять порты источника (src) и назначения (dst) при передаче данных от инициатора к отвечающему (orig) и наоборот (repl) для протоколов транспортного уровня, имеющих порты (TCP, UDP, SCTP, DCCP). Ситуация с портами в принципе аналогична описанной выше ситуации с адресами, поэтому рассматривать ее отдельно мы не будем. * <tt>[!] '''--ctexpire''' ''мин_время''[:''макс_время'']</tt> Позволяет указать в качестве критерия оставшееся по тайм-ауту время в секундах для данного соединения. Система conntrack присваивает каждому соединению тайм-аут (счетчик обратного отсчета времени). Когда этот счетчик доходит до нуля, система conntrack удаляет информацию о соединении из своих таблиц. Тайм-аут устанавливается в значение по умолчанию каждый раз, когда по соединению передаются данные. Таким образом, активно используемые соединения никогда не будут сброшены. Заметим, что значения тайм-аута по умолчанию для разных протоколов, и даже для одного протокола на разных стадиях установки соединения, могут различаться. Например, для протокола {{w |TCP}} вводятся отдельные значения тайм-аутов для состояний SYN_SENT, SYN_RECV, ESTABLISHED (не путать TCP-состояние ESTABLISHED с conntrack-состоянием ESTABLISHED), FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. Для {{w |UDP}} существуют два тайм-аута: для соединений, не получивших статуса ASSURED (conntrack_udp_timeout) и для соединений, по которым передано достаточное количество данных в обе стороны для получения этого статуса (conntrack_udp_timeout_stream). Для {{w |ICMP}} тайм-аут только один. ==== state ==== Идеологический предшественник критерия conntrack. Имеет единственный параметр <tt>--state</tt>, аналогичный параметру <tt>--ctstate</tt> критерия conntrack (но, в отличие от него, не поддерживающий состояния DNAT и SNAT). Долгое время был основным критерием определения состояния, и до сих пор фигурирует во многих руководствах и примерах. Однако в настоящее время разработчики iptables рекомендуют использовать вместо него критерий conntrack. Возможно, что критерий state вообще будет удален из будущих версий iptables/netfilter. === Дополнительные критерии === Дополнительные критерии iptables подгружаются при помощи параметра <tt>-m</tt> (<tt>--match</tt>). Далее можно указать дополнительные параметры, специфичные для данного конкретного критерия. Если дополнительных критериев несколько, не смешивайте их параметры — указывайте нужные параметры каждого критерия непосредственно после его вызова через <tt>-m</tt>. Перед некоторыми дополнительными параметрами критерия может стоять восклицательный знак. В соответствии с принятыми в iptables соглашениями, это означает логическую инверсию параметра, то есть его смысл меняется на противоположный. Но такая возможность предусмотрена отнюдь не для всех параметров. Заметим, что перечисленные выше критерии состояния и критерии, специфичные для протоколов, по сути также являются параметрами соответствующих дополнительных критериев (например, при указании <tt>-p tcp</tt> подразумевается еще и <tt>-m tcp</tt>). Однако в силу ряда причин более логичным и понятным было их отделение от остальных дополнительных критериев. Обратите внимание, что ''все'' параметры вышеперечисленных критериев допускают логическое отрицание (например, <tt>-m conntrack ! --ctstate NEW</tt>). Справочную информацию по любому из дополнительных критериев можно получить, используя команду <syntaxhighlight lang="bash"> iptables -m название_критерия -h </syntaxhighlight> ==== Вспомогательные критерии ==== К этой группе можно отнести критерии, расширяющие возможности других критериев. * '''multiport''' — позволяет указать несколько (до 15) портов и/или их диапазонов (для протоколов {{w |TCP}}, {{w |UDP}}, {{w |SCTP}}, {{w |DCCP}} и {{w |UDP Lite}}). Поддерживает следующие параметры <tt>[!] --sports</tt>, <tt>--source-ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]</tt> — улучшенная версия критерия <tt>--sport</tt>, описанного выше. Позволяет перечислить (без пробелов, через запятую) до 15 портов или их диапазонов. <tt>[!] --dports</tt>, <tt>--destination-ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]</tt> — улучшенная версия критерия <tt>--dport</tt>, описанного выше. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -p tcp -m multiport --dports 80,8000:8008 -j ACCEPT </syntaxhighlight> позволит принимать TCP-пакеты, приходящие на порты 80 и с 8000 по 8008. <tt>[!] --ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]</tt> — пакет будет подпадать под этот критерий, если его исходный порт ''или'' порт назначения присутствует в указанном списке. * '''iprange''' — позволяет указать диапазон {{w |IP-адрес}}ов, не являющийся подсетью. Поддерживает следующие параметры: <tt>[!] --src-range ''адрес''[-''адрес'']</tt> — позволяет указать диапазон исходных адресов. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -m iprange --src-range 192.168.0.8-192.168.0.25 -j DROP </syntaxhighlight> заблокирует все пакеты, исходный адрес которых лежит в диапазоне с 192.168.0.8 по 192.168.0.25 включительно. <tt>[!] --dst-range ''адрес''[-''адрес'']</tt> — позволяет указать диапазон адресов назначения. ==== Критерии маркировки ==== * '''mark''' — позволяет выделять пакеты с заданной маркировкой (nfmark). Имеет единственную опцию <tt>[!] --mark ''значение''[/''маска'']</tt> — указывает значение маркировки. Простейший пример: <syntaxhighlight lang="bash"> -m mark --mark 15 </syntaxhighlight> будет выделять пакеты с маркировкой 15. Если указана маска, то перед сравнением с заданным значением маркировка каждого пакета комбинируется с этой маской посредством логической операции [[w:Конъюнкция|AND]], то есть проверяется условие <tt>x & ''маска'' == ''значение''</tt> (где x — маркировка текущего пакета). Такой подход позволит сравнивать значения отдельных {{w |бит}}. Например, критерию <syntaxhighlight lang="bash"> -m mark --mark 64/64 </syntaxhighlight> будет отлавливать пакеты, в маркировке которых установлен 7-й бит (<math>2^6=64</math>, при этом первый бит соответствует <math>2^0</math>). В частности, 64…127, 192…255, 320…383 и т. д. Еще один пример — <syntaxhighlight lang="bash"> -m mark --mark 2/3 </syntaxhighlight> будет определять пакеты, в маркировке которых установлен второй бит, но снят первый. Такие числа будут нацело делиться на два, но не делиться на четыре — 2, 6, 10, 14, … * '''connmark''' — полностью аналогичен mark, но проверяет не маркировку пакета (nfmark), а маркировку соединения (ctmark). Также имеет параметр <tt>--mark</tt> с аналогичным синтаксисом. В качестве практического примера использования меток пакетов и соединений рассмотрим улучшение работы {{w |l7-filter}}-userspace. Userspace-вариант {{w |l7-filter}} является [[w:Демон (программа)|демоном]], взаимодействующим с {{w |netfilter}} через подсистему nfnetlink_queue — действие NFQUEUE в терминологии iptables. При помощи этого действия определенные пакеты можно направить на анализ демону l7-filter. По результатам анализа демон выставит маркировку пакетов: 1 — пакет принадлежит новому соединению, тип которого пока не идентифицирован; 2 — пакет принадлежит соединению, тип которого идентифицировать так и не удалось. Другие значения соответствуют установленным типам соединений (соответствие задается в конфигурационном файле демона) [http://l7-filter.sourceforge.net/HOWTO-userspace#Does]. Задача l7-filter — определить тип протокола [[w:Протоколы прикладного уровня|прикладного уровня]] (см. {{w |модель OSI}}) для данного пакета/соединения. Решается эта задача путем анализа содержимого пакета с применением [[Регулярные выражения|регулярных выражений]], позволяющих определить типовые лексемы, характерные для различных протоколов (например, «<tt>220 ftp server ready</tt>» для {{w |FTP}} или «<tt>HTTP/1.1 200 OK</tt>» для {{w |HTTP}}). Пакет, в котором встречаются такие лексемы, может быть однозначно классифицирован. В принципе, это дает достаточное основание классифицировать соединение в целом. Однако, в этом поведение kernel и userspace версий l7-filter существенно различается. Как описывается в [http://l7-filter.sourceforge.net/technicaldetails документации], версия l7-filter-kernel ''хранит'' данные о соединениях и ''использует'' их для классификации пакетов, принадлежащих к соединениям, тип которых уже установлен. В то же время, аналогичное утверждение в отношении l7-filter-userspace в документации отсутствует. И, как показывает практика, userspace-версия ''не использует'' информацию о соединениях. Возможно, это обусловлено техническими ограничениями nfnetlink_queue как средства взаимодействия l7-filter с системой netfilter. Описанный недостаток значительно снижает эффективность l7-filter — ведь однозначно классифицированы могут быть всего несколько пакетов из каждого соединения, а всего в соединении могут быть миллионы и миллиарды пакетов. Соответственно, применение l7-filter по своему основному назначению — классификация трафика для последующего [[w:Шейпинг (информатика)|шейпинга]] — не оправдывает себя. Итак, рассмотрим, как, используя возможности netfilter, можно исправить этот недостаток. Идея решения проста: после обработки пакетов демоном l7-filter, нужно добавить операции по переносу маркировки пакета на соединение (чтобы классифицировать соединение в целом) и с соединения на пакеты (чтобы пометить уже ''все'' пакеты в соединении для дальнейшей обработки шейпером, так как шейпер воспринимает только метки пакетов). Таким образом, классификация одного пакета в соединении влечет классификацию всех последующих пакетов. Для начала, запустим демон l7-filter-userspace. Небольшое замечание: в его конфигурационном файле (назовем его, например, <tt>l7-filter.conf</tt>) будем помечать протоколы метками в диапазоне от 16 до 31 включительно (почему — станет понятно из дальнейших пояснений). <syntaxhighlight lang="bash"> l7-filter -f /etc/l7-filter.conf -q 2 -m 0x1f </syntaxhighlight> Параметр <tt>-f</tt> указывает путь к конфигурационному файлу, <tt>-q</tt> — номер очереди, <tt>-m</tt> — задает биты маркировки, модифицируемые демоном l7-filter (в нашем случае — с первого по пятый, что соответствует диапазону значений маркировки от 0 до 31). Далее, добавим правила, направляющие весь входящий и исходящий трафик (кроме локального) на анализ демону l7-filter: <syntaxhighlight lang="bash"> iptables -t mangle -F # На всякий случай очищаем таблицу mangle # Направляем на анализ входящий трафик, включая транзитный iptables -t mangle -A PREROUTING ! -i lo -j NFQUEUE --queue-num 2 # Направляем на анализ исходящий трафик, кроме транзитного iptables -t mangle -A OUTPUT ! -o lo -j NFQUEUE --queue-num 2 </syntaxhighlight> Добавлять второе из этих правил в цепочку POSTROUTING не стоило — ведь в нее попадает как трафик, исходящий от самого хоста, так и транзитный трафик, который уже был обработан ранее, в цепочке PREROUTING. Посмотрев на диаграмму выше, вы можете убедиться, что приведенные правила обрабатывают весь трафик, как принадлежащий самому хосту, так и транзитный, за исключением локального. Локальный трафик (идущий через интерфейс [[w:Loopback|lo]]), бессмысленно шейпить, а значит, не стоит и классифицировать. Теперь добавим правила, обеспечивающие копирование маркировки пакетов в маркировку соединений и обратно: <syntaxhighlight lang="bash"> # Для входящего трафика (кроме транзитного) # Копируем маркировку пакетов в маркировку соединений iptables -t mangle -A INPUT -m mark --mark 0x10/0xfffffff0 -j CONNMARK --save-mark # И наоборот iptables -t mangle -A INPUT -m connmark --mark 0x10/0xfffffff0 -j CONNMARK --restore-mark # Аналогично для исходящего трафика (включая транзитный) iptables -t mangle -A POSTROUTING -m mark --mark 0x10/0xfffffff0 -j CONNMARK --save-mark iptables -t mangle -A POSTROUTING -m connmark --mark 0x10/0xfffffff0 -j CONNMARK --restore-mark </syntaxhighlight> Поясним два момента. Во-первых, добавление этих правил в цепочки PREROUTING и OUTPUT, сразу после правил, передающих трафик демону l7-filter, не имеет смысла — после обработки пакетов демон [http://l7-filter.sourceforge.net/HOWTO-userspace#Does применяет] к ним действие ACCEPT, прекращающее обработку пакета в рамках исходных цепочек. Поэтому мы добавляем эти правила в цепочки, идущие «ниже по течению». Как вы можете заметить по диаграмме выше, такая комбинация правил также обеспечивает обработку всего трафика. Второй момент, который стоит пояснить — маски специального вида. По сути, они позволяют проверить, лежит ли маркировка пакета в диапазоне от 16 до 31. Такая защита позволяет избежать обработки маркировок 0 (такую маркировку имеет локальный трафик, так как он не проходит процедуру анализа), 1 и 2 (эти значения маркировки, как уже было замечено выше, означают, что тип пакета не определен), а также 32 и выше (эти значения мы оставляем для других задач). Как показывает [http://www.linux.org.ru/jump-message.jsp?msgid=3790164&cid=3791754 практика], даже в самом примитивном случае (детекция протокола {{w |HTTP}}, сервер — {{w |nginx}} 0.6.32, клиент — [http://www.hping.org/wbox/ wbox] 4), эффективность детекции возрастает — без использования маркировки соединений регистрируются лишь 2 исходящих пакета (l7-filter работает на сервере), с использованием — 3 исходящих и 2 входящих. Детальное исследование показывает, что детекции избегают лишь первые четыре пакета в соединении — 2 SYN-пакета и 2 пакета с данными. Это цифры, характерные для тестовой задачи — при передаче больших объемов данных количество детектированных пакетов будет значительно больше, в то время как количество не определенных пакетов сохранит тот же порядок. Более того, предложенный метод решает задачу, не решенную даже в реализации l7-filter-kernel — маркировка связанных соединений. Согласно документации iptables, маркировка соединений автоматически копируется с исходных соединений на связанные с ними (например, с управляющего {{w |FTP}}-соединения на соединение данных). : ''Примечание: следующий пример планируется к переносу в еще не написанный раздел статьи (Прочие критерии → statistic)''. В качестве практического примера использования меток пакетов и соединений можно рассмотреть задачу [[w:Случайная величина|стохастической]] балансировки соединений между несколькими [[аплинк]]ами. Допустим, у нас есть три провайдера, подключенных к интерфейсам eth0, eth1 и eth2 (это могут быть и {{w |VLAN}}-порты одного интерфейса, суть от этого не меняется, только названия), и их шлюзы имеются соответственно {{w |IP-адрес}}а 208.77.188.1, 208.77.189.1, 208.77.190.1. Для начала, создадим для каждого провайдера свою таблицу маршрутизации <syntaxhighlight lang="bash"> echo -e "\n110\tstatic\n111\tprov1\n112\tprov2\n113\tprov3" >> /etc/iproute2/rt_tables </syntaxhighlight> Этот код добавит в конец файла <tt>/etc/iproute2/rt_tables</tt> строки 110 static 111 prov1 112 prov2 113 prov3 устанавливающие соответствие между внутренними номерами таблиц маршрутизации и их символьными именами. Используемые здесь имена prov1, prov2 и prov3, разумеется, условны. Таблица static — особая, ее мы рассмотрим чуть ниже. Обратите внимание, что это действие выполняется только один раз — не надо повторять его при каждой загрузке системы! Далее, сделаем каждого провайдера шлюзом по умолчанию в «своей» таблице: <syntaxhighlight lang="bash"> ip route add default via 208.77.188.1 dev eth0 table prov1 ip route add default via 208.77.189.1 dev eth1 table prov2 ip route add default via 208.77.190.1 dev eth2 table prov3 </syntaxhighlight> Добавим для каждой таблицы правило, отправляющее в нее пакеты с соответствующей маркировкой: <syntaxhighlight lang="bash"> ip rule add fwmark 1 table prov1 ip rule add fwmark 2 table prov2 ip rule add fwmark 3 table prov3 # Но прежде всего пакеты должны пройти таблицу static ip rule add table static prio 1 </syntaxhighlight> Таблица static предназначена для обслуживания статических маршрутов. В частности, в нее мы занесем подсети провайдеров (предположим, что все они [[w:Бесклассовая адресация|класса 1C]]), а также наши внутренние локальные сети (если таковые есть): <syntaxhighlight lang="bash"> # Провайдеры ip route add 208.77.188.0/24 dev eth0 table static ip route add 208.77.189.0/24 dev eth1 table static ip route add 208.77.190.0/24 dev eth2 table static # Две наших локалки ip route add 192.168.1.0/24 dev eth3 table static ip route add 192.168.2.0/24 dev eth4 table static # Сбрасываем кеш маршрутов ip route flush cache </syntaxhighlight> Таким образом, если нашему хосту нужно будет обратиться в подсеть провайдера prov2 (208.77.189.0/24), то маршрут пойдет сразу через интерфейс eth1. Также в этой таблице присутствуют маршруты для наших внутренних локальных сетей — с ними тоже все просто. По сути дела, таблица static обычно содержит те же маршруты, что и таблица main (главная таблица маршрутизации), за исключением маршрута по умолчанию — таких маршрутов у нас несколько и каждый из них размещается в отдельной таблице, выбор между которыми осуществляется на основании назначенной iptables/netfilter маркировки. Заметим, что ни в таблицу static, ни в какие-либо другие таблицы не нужно вносить {{w |loopback}}-маршруты, например «127.0.0.1/8 dev lo», так как все эти маршруты фигурируют в автоматически создаваемой таблице local, которую любой пакет проходит в первую очередь (нетрудно убедиться в этом, посмотрев вывод команды «ip rule show»). Далее, отключим статическую антиспуфинговую фильтрацию: <syntaxhighlight lang="bash"> sysctl net.ipv4.conf.all.rp_filter=0 </syntaxhighlight> Reverse path filtering — штука, конечно, удобная и полезная но, к сожалению, совершенно не совместимая с динамической маршрутизацией. Если вы планируете использовать этот компьютер не только как [[w:Сетевой шлюз|шлюз]], и но и как интернет-{{w |сервер}} (то есть предоставлять доступ к нему извне), необходимо выполнить привязку входящих соединений к их интерфейсам — в противном случае могут возникнуть проблемы, если обращение извне придет через одного провайдера, а сервер ответит через другого. <syntaxhighlight lang="bash"> iptables -t mangle -N bind_connect # Создаем отдельную цепочку (для простоты управления) # Следите за правильным соответствием значений меток и интерфейсов! iptables -t mangle -A bind_connect -i eth0 -j CONNMARK --set-mark 1 iptables -t mangle -A bind_connect -i eth1 -j CONNMARK --set-mark 2 iptables -t mangle -A bind_connect -i eth2 -j CONNMARK --set-mark 3 # Пропускаем через эту процедуру все новые соединения к нашему серверу iptables -t mangle -I INPUT -m conntrack --ctstate NEW -j bind_connect </syntaxhighlight> Теперь, в сочетании с операцией <tt>-j CONNMARK --restore-mark</tt>, которой мы подвергнем исходящий с нашего сервера трафик (см. ниже), эта процедура обеспечит корректную обработку входящих соединений. (Отметим, что, если бы нам не нужно было бы балансировать исходящие соединения, мы могли бы обойтись вообще без помощи iptables/netfilter, выполнив привязку входящих соединений через правила вида <tt>ip rule add from 208.77.188.100 table prov1</tt> и т. п. — ответные пакеты всегда уходят с того же адреса, на который пришел запрос, так что в качестве критерия для выбора шлюза можно использовать исходный адрес.) Ввиду того, что выбор исходящего адреса для каждого нового соединения осуществляется на основании правил статической маршрутизации (таблица main), могут возникнуть ошибки. Например, если в маршруте по умолчанию (default) в таблице main указан интерфейс eth0, то все исходящие от нас во внешнюю сеть (интернет) соединения будут иметь в качестве исходного адреса первый адрес интерфейса eth0, и ответные пакеты пойдут именно на этот интерфейс. Чтобы избежать возникновения таких ситуаций, добавим {{w |маскарадинг}} для всех исходящих соединений (предполагается, что у всех провайдеров наши внешние адреса имеют вид 208.77.x.100): <syntaxhighlight lang="bash"> iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.100 iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 208.77.189.100 iptables -t nat -A POSTROUTING -o eth2 -j SNAT --to-source 208.77.190.100 </syntaxhighlight> А теперь — самое интересное. Используя описанный ниже критерий statistic, мы будем случайно распределять метки между пакетами. <syntaxhighlight lang="bash"> iptables -t mangle -N select_prov # Создаем для этого специальную цепочку iptables -t mangle -A select_prov -j CONNMARK --set-mark 1 # Ставим всем соединениям маркировку 1 iptables -t mangle -A select_prov -m statistic --mode random --probability 0.34 -j RETURN # С вероятностью 34% выходим из этой цепочки iptables -t mangle -A select_prov -j CONNMARK --set-mark 2 # Ставим всем оставшимся соединениям маркировку 2 iptables -t mangle -A select_prov -m statistic --mode random --probability 0.5 -j RETURN # С вероятностью 50% выходим из этой цепочки iptables -t mangle -A select_prov -j CONNMARK --set-mark 3 # Всем, кто дошел досюда, ставим маркировку 3 </syntaxhighlight> Первое правило в этой цепочке пройдут все пакеты, вошедшие в нее. После этого, 34 % (примерно треть из них) покинет цепочку согласно второму правилу. Далее, оставшиеся пакеты (66 % от первоначального количества) получат маркировку 2. После этого половина из них (то есть 33 % от начального) покинут цепочку с этой маркировкой. Оставшаяся половина (тоже 33 % от начального количества) получат маркировку 3. После этого, создадим вспомогательную цепочку, осуществляющую маркировку соединений и пакетов: <syntaxhighlight lang="bash"> iptables -t mangle -N sort_connect iptables -t mangle -A sort_connect -o lo -j RETURN # Локальным соединениям балансировка не нужна # Аналогично выгоняем пакеты, выходящие через интерфейсы внутренней локалки, если она есть iptables -t mangle -A sort_connect -o eth3 -j RETURN iptables -t mangle -A sort_connect -o eth4 -j RETURN iptables -t mangle -A sort_connect -m conntrack --ctstate NEW -j select_prov # Все новые пакеты прогоняем через процедуру случайного выбора iptables -t mangle -A sort_connect -j CONNMARK --restore-mark # Копируем маркировку соединений на пакеты </syntaxhighlight> Через цепочку <tt>select_prov</tt> мы прогоняем только новые пакеты, то есть первые пакеты каждого соединения. После этой процедуры соединение уже имеет маркировку. К сожалению, на данный момент роутинговая подсистема ядра [[w:Ядро Linux|Linux]] не умеет маршрутизировать пакеты на основании маркировки соединения — только на основании маркировки пакетов. Поэтому действием <tt>CONNMARK --restore-mark</tt> мы копируем маркировку соединений в маркировку пакетов. Осталось только добавить вызов этой цепочки в таблицу mangle: <syntaxhighlight lang="bash"> iptables -t mangle -I OUTPUT -j sort_connect </syntaxhighlight> Теперь все ваши исходящие соединения будут балансироваться согласно описанным правилам. Аналогичную функциональность можно реализовать и для транзитных соединений. Для этого достаточно добавить вызов <tt>sort_connect</tt> в цепочку FORWARD таблицы mangle: <syntaxhighlight lang="bash"> iptables -t mangle -I FORWARD -j sort_connect </syntaxhighlight> Разумеется, при этом должна быть разрешена передача транзитного трафика, как в таблице filter, так и на уровне sysctl. Как это делается — см. выше. Заметим, что кроме алгоритма случайной балансировки, критерий statistic позволяет реализовать балансировку в режим [[w:Round-robin (алгоритм)|round robin]]. Для этого поменяем цепочку <tt>select_prov</tt> следующим образом: <syntaxhighlight lang="bash"> iptables -t mangle -F select_prov # Очищаем ее iptables -t mangle -A select_prov -j CONNMARK --set-mark 1 # Ставим всем соединениям маркировку 1 iptables -t mangle -A select_prov -m statistic --mode nth --every 3 -j RETURN # Первый из трех пакетов - выходим iptables -t mangle -A select_prov -j CONNMARK --set-mark 2 # Ставим всем оставшимся соединениям маркировку 2 iptables -t mangle -A select_prov -m statistic --mode nth --every 2 -j RETURN # Один из оставшихся двух - выходим iptables -t mangle -A select_prov -j CONNMARK --set-mark 3 # Последний </syntaxhighlight> Подробнее о принципах работы критерия statistic см. ниже. В завершение нашего обсуждения стоит заметить, что в некоторых случаях для балансировки соединений достаточно единственной команды <syntaxhighlight lang="bash"> ip route add default scope global nexthop via 208.77.188.1 dev eth0 weight 1 nexthop via 208.77.189.1 dev eth1 weight 1 # И т.д. </syntaxhighlight> Стоит обратить особое внимание на тот факт, что данный метод балансирует ''пакеты'', а не соединения. Например, в том случае, если вы хотите организовать выход в интернет из локальной сети через нескольких провайдеров, не имея единого внешнего адреса, этот метод может работать некорректно — часть пакетов пройдет через одного провайдера и после операции {{w |NAT}} получит один исходный адрес, часть пойдет через другого и соответственно получит другой адрес, и в результате удаленные хосты не смогут правильно обрабатывать соединения, исходящие из вашей сети. Однако, в большинстве случаев этот негативный эффект нивелируется другим фактором — кэшированием маршрутов. При прохождении через такое правило серии пакетов, адресованных некоторому хосту, действительно случайным выбор будет только для первого из них, после чего выбранный маршрут будет закэширован, и остальные пакеты к этому хосту будут маршрутизироваться через тот же шлюз. С одной стороны, подобный эффект позволяет соединениям корректно функционировать, с другой стороны — балансировка оказывается не такой уж и случайной. К тому же, после очистки кэша маршрутов (например, посредством ввода команды <tt>ip route flush cached</tt>), работа существующих на этот момент соединений может быть нарушена. В качестве наиболее безопасного и целесообразного применения описанного метода можно привести задачу балансировки транзитного трафика в сетях без NAT (условия «прямой видимости» между балансирующим маршрутизатором и точкой схождения потоков трафика). В том случае, если доступ к шлюзам осуществляется через один сетевой интерфейс, этим методом можно балансировать и соединения, исходящие от самого хоста. Также заметим, что описанные в этом примере методы балансировки не учитывают загруженность каналов. Для этого рекомендуется использовать критерий rateest и действие RATEEST совместно с уже знакомым нам CONNMARK. ==== Лимитирующие критерии ==== К этой группе относятся критерии, позволяющие ограничивать количество пакетов, соединений, и переданных байт. * '''limit''' — позволяет ограничить количество пакетов в единицу времени. Параметры: <tt>--limit ''количество''[/second|/minute|/hour|/day]</tt> — задает ограничение на количество пакетов в секунду (second), минуту (minute), час (hour) или сутки (day). Пакеты в пределах этого количества считаются удовлетворяющими критерию, сверх этого количества — не удовлетворяющими. <tt>--limit-burst ''количество''</tt> — задает длину очереди, то есть максимальную пропускную способность. Критерий -limit использует модель «дырявого ведра», и --limit-burst задает «объем ведра», а --limit — «скорость вытекания». Каждому такому критерию соответствует своя очередь, длина которой задается параметром --limit-burst. Если в очереди есть пакеты, то со скоростью, заданной в --limit, они покидают очередь и считаются удовлетворяющими критерию. Если же вся очередь занята, то новые пакеты в ней не регистрируются и считаются ''не'' удовлетворяющими критерию. Например, <syntaxhighlight lang="bash"> iptables -I INPUT -m limit --limit 3/min --limit-burst 5 -j LOG --log-level debug --log-prefix "INPUT packet: " </syntaxhighlight> предполагает очередь на пять пакетов, которая «продвигается» со скоростью 3 пакета в минуту. При непрерывном поступлении входящих пакетов, очередь всегда будет заполнена, и в лог будут заноситься в среднем по три пакета в минуту. Однако, если входящих пакетов долго не будет, то очередь успеет очиститься, и при поступлении пяти и менее новых пакетов, они пойдут в лог подряд. В любом случае, скорость попадания пакетов в лог остается неизменной. Типичная ошибка новичков — использовать limit для ограничения TCP-трафика, например, так: <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -m limit --limit 10000/sec --limit-burst 10000 -j ACCEPT iptables -P INPUT DROP </syntaxhighlight> Это пример попытки защитить {{w |web-сервер}} от [[w:DoS-атака|DDoS-атаки]], ограничив количество пакетов в единицу времени. Однако, это правило не помешает без особого труда завалить сервер запросами (считая, что на один запрос требуется два входящих пакета — SYN-пакет и пакеты данных, содержащий, например, только GET /, согласно спецификации HTTP 0.9). При этом могут возникнуть помехи для легальных пользователей, например, загружающих на сервер большой файл методом POST. Более корректным решением будет ограничивать не скорость входящего потока данных, а скорость открытия новых соединений: <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m limit --limit 32/sec --limit-burst 32 -j ACCEPT iptables -P INPUT DROP </syntaxhighlight> Теперь мы ограничиваем количество не всех пакетов, а только новых, то есть мы разрешаем открывать не более 32 новых соединений в секунду. Впрочем, число 32 приведено здесь только для примера. Конкретное значение скорости для вашей задачи рекомендуем определять самостоятельно. * '''hashlimit''' — позволяет применять ограничения, аналогичные критерию limit, к группам хостов, подсетей или портов, используя всего одно правило. При этом для каждого хоста, подсети или порта создается отдельная очередь. Можно задвать, например, такие критерии: «1000 пакетов в секунду с каждого хоста из подсети 192.168.0.0/16» <syntaxhighlight lang="bash"> -s 192.168.0.0/16 -m hashlimit --hashlimit-upto 1000/sec --hashlimit-mode srcip </syntaxhighlight> «100 пакетов в секунду с каждого TCP-порта хоста 192.168.1.1» <syntaxhighlight lang="bash"> -s 192.168.1.1 -m hashlimit --hashlimit-upto 100/sec --hashlimit-mode srcport </syntaxhighlight> «10000 пакетов в минуту с каждой подсети префикса 28 (маска 255.255.255.240) из диапазона 10.0.0.0/8» <syntaxhighlight lang="bash"> -s 10.0.0.0/8 -m hashlimit --hashlimit-upto 10000/min --hashlimit-mode srcip --hashlimit-srcmask 28 </syntaxhighlight> Обратите внимание, что в ''каждом'' из этих правил нужно обязательно указать имя таблицы очередей (haslimit-name, см. ниже), однако, в целях простоты изложения, в некоторых примерах этот параметр опущен. Рассмотрим основные параметры этого критерия более подробно: <tt>--hashlimit-mode {srcip|srcport|dstip|dstport}[,...]</tt> — задает список контролируемых параметров: адреса (ip) и порты (port) источника (src) и назначения (dst). Например, если указать параметр <syntaxhighlight lang="bash"> --hashlimit-mode srcip,dstip </syntaxhighlight> то будет создаваться отдельная очередь для каждой пары «адрес источника — адрес назначения», то есть ограничение будет вводиться на количество пакетов, передаваемых с каждого хоста на другой хост (разумеется, если эти пакеты идут через наш сервер). Или, например, <syntaxhighlight lang="bash"> --hashlimit-mode srcip,srcport </syntaxhighlight> будет создавать отдельную очередь для каждого исходного порта каждого хоста. <tt>--hashlimit-upto ''количество''[/second|/minute|/hour|/day]</tt> — этот параметр задает скорость движения очереди (аналог <tt>--limit</tt>). Если пакеты поступают с такой же или меньшей скоростью, они считаются подпадающими под критерий. Обратите внимание, что этот параметр ''не'' поддерживает логической инверсии (отрицания) через восклицательный знак (см. ниже). <tt>--hashlimit-above ''количество''[/second|/minute|/hour|/day]</tt> — этот параметр таке задает скорость движения очереди, но смысл его противоположный — если пакеты поступают с ''большей'' скоростью, они считаются подпадающими под критерий. <tt>--hashlimit-burst ''количество''</tt> — задает длину каждой очереди. Аналогичен <tt>--limit-burst</tt>. <tt>--hashlimit-srcmask ''префикс''</tt> — задает размер подсети исходных адресов, для которой вводится своя очередь. Имеет смысл, только если в haslimit-mode указан режим srcip. Как уже говорилось выше, <syntaxhighlight lang="bash"> -m hashlimit --hashlimit-mode srcip --hashlimit-srcmask 28 </syntaxhighlight> будет заводить отдельную очередь для каждой подсети с маской 255.255.255.240 (подробнее про префиксы и маски см. {{w |CIDR}}). По умолчанию 32 (своя очередь для каждого отдельного хоста). Если указать 0, то контроль по параметру srcip теряет смысл. <tt>--hashlimit-dstmask ''префикс''</tt> — задает размер подсети исходных адресов, для которой вводится своя очередь. Имеет смысл, только если в haslimit-mode указан режим dstip. Принцип использования аналогичен hashlimit-srcmask. <tt>--hashlimit-name ''имя''</tt> — позволяет использовать несколько независимых таблиц очередей (hashes), распознаваемых по имени. Обязательный параметр. Например, <syntaxhighlight lang="bash"> iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Пропускаем все, что идет по уже установленным соединениям # Вводим ограничения для новых подключений по FTP iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 21 -m hashlimit --hashlimit-upto 5/min --hashlimit-mode srcip --hashlimit-name ftphash -j ACCEPT # Вводим ограничения для новых подключений по rsync. iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 873 -m hashlimit --hashlimit-upto 5/min --hashlimit-mode srcip --hashlimit-name rsynchash -j ACCEPT iptables -P INPUT DROP # Всех остальных не пускаем </syntaxhighlight> Теперь очереди ограничений для подключения к службам {{w |FTP}} и {{w |rsync}} для нашего сервера будут вводиться независимо, то есть если какой-либо хост превысит предел подключений по FTP, то это никак не повлияет на подключения по rsync. Заметим, что в данном конкретном случае аналогичную функциональность можно реализовать, даже не используя разные хеши: <syntaxhighlight lang="bash"> iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Пропускаем все, что идет по уже установленным соединениям # Вводим ограничения для новых подключений по FTP и rsync iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dports 21,873 -m hashlimit --hashlimit-upto 5/min --hashlimit-mode srcip,dstport --hashlimit-name ftprsynchash -j ACCEPT iptables -P INPUT DROP # Всех остальных не пускаем </syntaxhighlight> Впрочем, выбирая между этими двумя реализациями, стоит учитывать, что размер каждого хеша ограничен. Не забывайте указывать имя таблицы очередей при каждом использовании критерия hashlimit. Если вы не планируете совместно использовать одни и те же таблицы в нескольких правилах, эти имена должны различаться. Доступ к таблицам очередей возможен через procfs (файл <tt>/proc/net/ipt_hashlimit/имя_таблицы</tt>). Подробнее о формате этого файла можно почитать [http://www.opennet.ru/base/net/iptables_tbf.txt.html здесь], однако учтите, что большая часть сведений, приведенных в указанной статье, устарела. Критерий haslimit также имеет ряд параметров, не описанных здесь (максимальный размер таблицы, время жизни записи в таблице, интервал [[w:Сборка мусора (программирование)|«сбора мусора»]], и т. п.). За подробными сведениями обратитесь к документации. * '''connlimit''' — позволяет ограничивать количество одновременно открытых соединений с каждого IP-адреса (или подсети). Параметры: <tt>[!] --connlimit-above количество</tt> — минимальное количество соединений. Все пакеты, проходящие по соединениям, установленным сверх заданного количества, считаются удовлетворяющими критерию. Например, <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 3 -j DROP iptables -A INPUT -p tcp --dport 80 -j ACCEPT </syntaxhighlight> разрешит не более трех одновременных соединений к нашему веб-серверу с одного IP-адреса. Аналогичного эффекта можно добиться командами <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -m connlimit ! --connlimit-above 3 -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j DROP </syntaxhighlight> <tt>--connlimit-mask</tt> — маска подсети, для которой устанавливается общее ограничение на количество соединений. Например, <syntaxhighlight lang="bash"> iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 5 --connlimit-mask 24 -j DROP iptables -A INPUT -p tcp --dport 80 -j ACCEPT </syntaxhighlight> разрешит не более пяти одновременных соединений на порт 80 с каждой подсети [[w:Бесклассовая адресация|класса 1C]]. Не надо путать connlimit с hashlimit — hashlimit позволяет ограничить ''скорость'' поступления пакетов с хостов или подсетей (в сочетании с <tt>-m conntrack --ctstate NEW</tt> — скорость открытия новых соединений), а connlimit — ''количество'' одновременно открытых соединений. * '''connbytes''' — позволяет ограничивать количество переданных байт или пакетов. Параметры: <tt>[!] --connbytes ''мин'':[''макс'']</tt> — собственно задает количество пакетов или байт. Можно указать просто минимальное количество или диапазон. <tt>--connbytes-dir {original|reply|both}</tt> — задает направление движения пакетов. Проверяются только пакеты, движущиеся от инициатора соединения к отвечающему (original), наоборот (reply) или в обоих направлениях (both). <tt>--connbytes-mode {packets|bytes|avgpkt}</tt> — задает собственно учитываемую величину: количество пакетов (packets), количество байт (bytes) или средний размер пакета (avgpkt). Пример: <syntaxhighlight lang="bash"> # Для соединений, по которым передано более 500 КБ, ставим минимальный приоритет TOS (требование максимальной полосы) iptables -t mangle -I INPUT -m connbytes --connbytes 512000: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Maximize-Throughput iptables -t mangle -I OUTPUT -m connbytes --connbytes 512000: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Maximize-Throughput # Для соединений, по которым передано менее 50 КБ, ставим максимальный приоритет TOS (требование минимальной задержки) iptables -t mangle -I INPUT -m connbytes ! --connbytes 51200: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Minimize-Delay iptables -t mangle -I OUTPUT -m connbytes ! --connbytes 51200: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Minimize-Delay </syntaxhighlight> Таким образом, все пакеты, принадлежащие «легким» соединениям, будут маркироваться как наиболее приоритетные, а пакеты, проходящие по «тяжеловесным» соединениям — как наименее приоритетные. Такой подход позволит рационально распределять канал между различными задачами, например, просмотром веб-страниц («легкие» соединения) и скачиванием файлов («тяжелые» соединения). Конечно, при таком подходе даже «тяжелые» соединения будут занимать канал с наивысшим приоритетом, пока не превысят ограничение. Но даже на медленных соединениях (128 Кбит/с) для этого достаточно всего четырех секунд (если эта закачка в данный момент единственная). После превышения лимита 50 Кбайт соединение получит средний приоритет ([[w:Тип обслуживания|TOS]] не установлен), а еще через некоторое время соединение превысит второй лимит — 500 Кбайт, и получит минимальный приоритет. В то же время, «легкие» соединения в большинстве случаев не превышают даже первого лимита, и поэтому целиком проходят с повышенным приоритетом. * '''quota''' — позволяет задать квоту в байтах для данного конкретного правила. Имеет единственный параметр <tt>--quota количество_байт</tt> — собственно задает квоту. Для каждого правила, содержащего такой критерий, создается счетчик, который уменьшается с каждым прошедшим по этому правилу пакетом на количество байт, равное размеру этого пакета. Когда значение счетчика доходит до нуля, правило перестает срабатывать. Чтобы восстановить счетчик, удалите правило и добавьте его снова. Например: <syntaxhighlight lang="bash"> sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик iptables -F FORWARD # Очищаем цепочку FORWARD iptables -A FORWARD -m quota --quota 1073741824 -j ACCEPT iptables -P FORWARD DROP </syntaxhighlight> разрешает хосту передавать не более одного гигабайта транзитного трафика (учитывается трафик в обоих направлениях). * '''quota2''' — критерий из уже упоминавшегося набора xtables-addons. Является результатом развития идей, заложенных в критерии quota. Позволяет создавать именованные счетчики квот (для совместного использования одного счетчика в нескольких правилах), считать не только байты, но и пакеты, а также создавать отдельные правила для пакетов, превышающих квоту (логическая инверсия параметра <tt>--quota</tt>). Поддерживаются следующие параметры: <tt>--name ''имя''</tt> — задает имя счетчика. Текущее значение счетчика содержится в файле <tt>/proc/net/xt_quota/''имя''</tt>. Его можно вывести на экран <syntaxhighlight lang="bash"> cat /proc/net/xt_quota/имя </syntaxhighlight> или задать вручную <syntaxhighlight lang="bash"> echo значение > /proc/net/xt_quota/имя </syntaxhighlight> Для осуществления этих действий, как и для работы с iptables, нужны полномочия [[w:Root|суперпользователя]]. <tt>[!] --quota ''количество''</tt> — проверяет текущее значение счетчика и уменьшает его на размер текущего пакета. Этот же параметр задает начальное значение счетчика (если счетчик с таким именем уже существует, он не сбрасывается). Пакет считается подпадающим под критерий, если счетчик еще не дошел до нуля (при указании логической инверсии — наоборот). Если немного усложнить наш предыдущий пример, <syntaxhighlight lang="bash"> sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик iptables -F FORWARD # Очищаем цепочку FORWARD # Устанавливаем квоту для первой подсети iptables -A FORWARD -s 192.168.1.0/24 -m quota2 --name first --quota 1073741824 -j ACCEPT # Для тех, кто идет из первой подсети сверх квоты - блокируем и сообщаем об отказе. # Кстати, счетчик first уже создан, поэтому теперь в параметре quota можно писать любое число. Но мы все-таки напишем 1 Гб. iptables -A FORWARD -s 192.168.1.0/24 -m quota2 --name first ! --quota 1073741824 -j REJECT # Устанавливаем квоту для второй подсети iptables -A FORWARD -s 192.168.2.0/24 -m quota2 --name second --quota 536870912 -j ACCEPT iptables -P FORWARD DROP </syntaxhighlight> Теперь для подсети 192.168.1.0/24 установлена квота в 1 Гб, и при превышении этой квоты пакеты блокируются, причем их отправителям хост отвечает пакетами icmp-port-unreachable, уведомляя их, что передача данных заблокирована. Для подсети 192.168.2.0/24 устанавливается квота 512 Мб, и при ее превышении никаких сообщений не посылается (пакеты блокируются «молча»). Так же молча блокируются транзитные пакеты из всех остальных подсетей. <tt>--packets</tt> — при указании этого параметра счетчик учитывает количество пакетов, а не их суммарный размер. <tt>--grow</tt> — ''увеличивает'' счетчик, вместо того, чтобы уменьшать его. Критерий с этим параметром всегда возвращает истину. Позволяет создавать счетчики «приходно-расходного типа». Например, <syntaxhighlight lang="bash"> -A INPUT -p tcp --dport 6881 -m quota2 --name bt --grow -A OUTPUT -p tcp --sport 6881 -m quota2 --name bt </syntaxhighlight> позволяет в любой момент определять разность сумм входящих (на TCP-порт [[BitTorrent|6881]]) и исходящих (с этого же порта) байт через файл <tt>/proc/net/xt_quota/bt</tt>. Вот [http://jengelh.medozas.de/2009/0717-bandwidth-monitoring.php еще один пример] использования этого критерия для сбора статистики по трафику. Обратите внимание, что при указании параметра grow критерий quota2 ''всегда'' будет возвращать истину. Действие для такого правила обычно назначать не имеет смысла — правило изменяет только счетчик квоты, а не сам пакет. * '''length''' — позволяет использовать в качестве критерия размер пакета. Проверятся размер пакета протокола транспортного уровня ({{w |TCP}}, {{w |UDP}}, {{w |SCTP}}, {{w |DCCP}} и т. д.) или, иначе говоря, размер пакета протокола сетевого уровня ({{w |IP}}, {{w |IPv6}}) за вычетом размера заголовков сетевого уровня. Данный критерий имеет единственный параметр <tt>[!] --length ''размер''[:''макс_размер'']</tt>, который может употребляться в нескольких формах: : <tt>--length ''размер''</tt> — пакет проверяется на точное соответствие заданному размеру, : <tt>--length ''мин_размер'':</tt> — размер пакета должен быть больше или равен заданной величине, : <tt>--length :''макс_размер''</tt> — размер пакета должен быть меньше или равен заданной величине, : <tt>--length ''мин_размер'':''макс_размер''</tt> — размер пакета должен попадать в указанный диапазон (включая границы). Смысл всех приведенных форм может быть заменен на противоположный, как обычно, указанием перед данным параметром восклицательного знака. Все размеры задаются в байтах. В качестве практического примера использования данного критерия можно рассмотреть установку высокого приоритета [[w:Тип обслуживания|TOS]] (требование минимальной задержки) для небольших транзитных пакетов (размер до 512 байт): <syntaxhighlight lang="bash"> iptables -t mangle -I INPUT -m length --length :512 -j TOS --set-tos Minimize-Delay </syntaxhighlight> * '''length2''' — расширение критерия length, доступное в наборе xtables-addons. Отличается от классического length возможностью проверять размеры пакетов на различных уровнях [[w:Сетевая модель OSI|модели OSI]]. Принимает следующие опции: <tt>--layer3</tt> — проверка размера пакета сетевого уровня (например, IPv4-пакета). <tt>--layer4</tt> — проверка размера пакета транспортного уровня (например, TCP-пакета). <tt>--layer5</tt> — проверка размера полезной нагрузки транспортного уровня (например, содержимого TCP-пакета, ''не'' учитывая размер заголовков TCP). Работает корректно только для некоторых протоколов транспортного уровня, на момент написания этих строк (конец 2009) поддерживаются: {{w |TCP}}, {{w |UDP}}, [[UDPLite]] ([[:en:UDPLite|en]]), {{w |ICMP}}, {{w |ICMPv6}} ([[:en:ICMPv6|en]]), {{w |DCCP}}, {{w |SCTP}}, {{w |IPSec}} (AH и ESP). Для {{w |SCTP}}-пакета в этот размер включаются все [[:en:SCTP packet structure|секции (chunks)]] вместе с их заголовками. <tt>--layer7</tt> — для SCTP проверяется суммарный размер DATA-секций в пакете (то есть его полезная нагрузка), для остальных протоколов аналогично <tt>--layer5</tt>. По умолчанию используется <tt>--layer3</tt>, однако во избежание недоразумений рекомендуется явно указывать одну из перечисленных опций. Если этого не делать, при вводе соответствующей команды появится сообщение iptables: length match: Defaulting to --layer3. Consider specifying it explicitly. Это ''не'' является ошибкой (только предупреждением о возможной неоднозначности). Заданное вами правило должно добавиться успешно. <tt>[!] --length ''размер''[:''макс_размер'']</tt> — собственно, задает нужные значения размера. В отличие от аналогичного параметра в классическом критерии length, его синтаксические формы несколько беднее. Допускаются два варианта записи: : <tt>--length ''размер''</tt> — пакет проверяется на точное соответствие заданному размеру, : <tt>--length ''мин_размер'':''макс_размер''</tt> — размер пакета должен быть попадать в указанный диапазон (включая границы). Впрочем, недостающие варианты легко выразить через имеющиеся: для имитации <tt>--length :''макс_размер''</tt> используйте <tt>--length 0:''макс_размер''</tt>, а вместо <tt>--length ''мин_размер'':</tt> применяйте <tt>--length ''мин_размер'':65535</tt>. Будьте внимательны: в отличие от length, length2 не проверяет взаимное соответствие границ диапазона (<tt>''мин_размер'' <= ''макс_размер''</tt>), и если вы зададите их неправильно (<tt>''мин_размер'' > ''макс_размер''</tt>), ваше правило просто никогда не будет срабатывать. <!-- По крайней мере в xtables-addons 1.21 этот баг присутствует. --> '''Подводя краткий итог по разделу «Лимитирующие критерии»''', хотелось бы заметить, что перечисленные в этом разделе критерии предназначены главным образом для ограничения доступа и защиты от различных атак. Не стоит пытаться ограничивать с их помощью трафик. Для ограничения и приоритизации трафика в [[Linux]] рекомендуется использовать стандартный [[w:Шейпинг (информатика)|шейпер]] ядра, управляемый при помощи утилиты [[w:Iproute2|tc]]. <!-- Если же вам нужно ограничить именно трафик, а не отдельные пакеты или соединения, то рекомендуем использовать для этого [[w:Шейпинг (информатика)|шейпер]]. Управление шейпером ядра Linux производится при помощи утилиты [[w:Iproute2|tc]]. Впрочем, этот шейпер позволяет эффективно управлять лишь исходящим трафиком.--> ==== Критерий recent ==== recent — это специальный критерий, позволяющий запоминать проходящие через него пакеты, а затем использовать полученную информацию для принятия решений. Ввиду его уникальности, широких возможностей и, как следствие, некоторых трудностей в понимании новичками принципов его использования, рассказ о нем был вынесен в отдельный подраздел. Если быть точным, recent запоминает не сами пакеты, а их количество, время поступления, адрес источника (в последних версиях iptables также может запоминать и адрес назначения), а также, при необходимости, [[w:Time to live|TTL]]. В начале кратко рассмотрим его опции: <tt>[!] --set</tt> — запомнить адрес источника/назначения пакета (внести его во внутренний список). Если такая запись уже присутствует в списке — обновить время последнего доступа для нее. Обратите внимание, что критерию recent с опцией <tt>--set</tt> удовлетворяют ''все'' пакеты. Чтобы ему не удовлетворял ни один пакет — используйте логическую инверсию (<tt>! --set</tt>). <tt>[!] --rcheck</tt> — позволяет проверить, присутствует ли адрес источника/назначения пакета во внутреннем списке. Критерий recent с этой опцией вернет истину, если адрес в списке присутствует. <tt>[!] --update</tt> — работает аналогично <tt>--rcheck</tt>, но еще и обновляет время последнего доступа для данной записи. <tt>[!] --remove</tt> — работает аналогично <tt>--rcheck</tt>, но еще и удаляет найденную запись из списка. Если запись не найдена, пакет считается ''не'' соответствующим критерию. <tt>--seconds ''число''</tt> — дополнительная опция в режимах <tt>--rcheck</tt> и <tt>--update</tt>. Пакет считается соответствующим критерию, только если последний доступ к записи был не позднее, чем ''число'' секунд назад. <tt>--hitcount ''число''</tt> — дополнительная опция в режимах <tt>--rcheck</tt> и <tt>--update</tt>. Пакет считается удовлетворяющим критерию, если было не менее ''число'' обращений к данной записи. Обычно используется вместе с <tt>--seconds</tt> — тогда критерий имеет смысл «не менее n обращений за последние m секунд». Заметим, что, хотя в официальной документации для параметров <tt>--seconds</tt> и <tt>--hitcount</tt> указывается возможность отрицания (указания перед ними восклицательного знака), на самом деле такое отрицание никак не обрабатывается в коде и не меняет смысла параметров, так что указывать его бессмысленно. Эта ошибка в документации исправлена в версии iptables 1.4.7. <tt>--rttl</tt> — дополнительно к адресу источника/назначения, заносить в список и проверять еще и [[w:Time to live|TTL]] пакета. <tt>--rsource</tt> — эта опция появилась в последних версиях iptables, с тех пор, как критерий recent начал поддерживать запоминание адресов не только источника, но и назначения. Позволяет явно указать, что в список вносится именно адрес источника пакета. Однако в целях обратной совместимости этот режим используется по умолчанию, и поэтому указывать данную опцию не обязательно. <tt>--rdest</tt> — эта опция появилась в последних версиях iptables. Позволяет явно указать, что в список вносится именно адрес назначения пакета. <tt>--name ''имя''</tt> — позволяет указать имя списка при использовании нескольких списков. По умолчанию используется список DEFAULT. Каждый список представлен псевдофайлом <tt>/proc/net/xt_recent/''имя''</tt> (на старых ядрах критерий recent реализован только для {{w |IPv4}}, но не для {{w |IPv6}}, поэтому вместо <tt>xt_recent</tt> будет <tt>ipt_recent</tt>). В частности, вы можете: <syntaxhighlight lang="bash"> cat /proc/net/xt_recent/имя # вывести список на экран echo +адрес > /proc/net/xt_recent/имя # добавить адрес в список echo -адрес > /proc/net/xt_recent/имя # удалить адрес из списка echo / > /proc/net/xt_recent/имя # очистить список </syntaxhighlight> Теперь давайте рассмотрим несколько примеров. * Блокирование {{w |bruteforce}}-атак (подбор пароля вслепую) на {{w |SSH}} и аналогичные сервисы. <syntaxhighlight lang="bash"> iptables -N ssh_brute_check # Создаем цепочку для проверки попыток соединений на защищаемый порт # Если за последние 10 минут (600 секунд) с одного адреса было 3 или более новых соединений — блокируем этот адрес iptables -A ssh_brute_check -m conntrack --ctstate NEW -m recent --update --seconds 600 --hitcount 3 -j DROP # В противном случае — разрешаем, и при этом заносим в список iptables -A ssh_brute_check -m recent --set -j ACCEPT iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям # Все попытки открыть новое соединение по SSH направляем на проверку iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_brute_check # Здесь можно разрешать те порты, для которых такая проверка не нужна. Например, HTTP iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 80 -j ACCEPT iptables -P INPUT DROP # Что не разрешено — то запрещено </syntaxhighlight> Теперь все попытки открыть новое SSH-соединение проверяются, и с одного {{w |IP-адрес}}а можно открывать не более 2 соединений за 10 минут. Обратите внимание, что за одно соединение злоумышленник может проверить несколько паролей — число попыток аутентификации до обрыва соединения задает параметр MaxAuthTries в файле <tt>/etc/ssh/sshd_config</tt>. По умолчанию это число равно 6, так что в нашем примере злоумышленник сможет проверять не более 12 паролей за 10 минут. Впрочем, данный пример весьма тривиален, и сходную функциональность можно получить и при помощи критерия hashlimit: <syntaxhighlight lang="bash"> iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -m hashlimit --hashlimit-mode srcip --hashlimit-upto 5/hour --hashlimit-name ssh -j ACCEPT </syntaxhighlight> разрешит не более 5 новых соединений в час. Данная реализация имеет недостаток по сравнению с recent — вы не можете произвольно задавать временной период. * Защита от сканирования портов (заметим, что кроме критерия recent для этой задачи можно также использовать критерии psd и lscan из комплекта xtables-addons). <syntaxhighlight lang="bash"> iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям # Если за последний час было 10 или более запросов на нерабочие порты — блокируем iptables -A INPUT -m recent --rcheck --seconds 3600 --hitcount 10 --rttl -j RETURN # Если за последнюю минуту было 2 или более запросов на нерабочие порты — блокируем iptables -A INPUT -m recent --rcheck --seconds 60 --hitcount 2 --rttl -j RETURN # Разрешаем рабочие порты iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 21,25,53,80,110 -j ACCEPT iptables -A INPUT -m conntrack --ctstate NEW -p udp -m multiport --dport 53,123 -j ACCEPT # Всех, кто ломится в нерабочие порты — регистрируем iptables -A INPUT -m recent --set iptables -P INPUT DROP # Что не разрешено — то запрещено </syntaxhighlight> Все пакеты, попадающие на нерабочие порты сервера, регистрируются. После нескольких таких попыток за заданный интервал времени адрес их источника блокируется. Проверка TTL добавлена для защиты от блокировки легитимных клиентов после спуфинга злоумышленником от их имени. Хотя, с другой стороны, эта мера позволяет ему обойти защиту от сканирования, выставляя своим пакетам различный TTL. Так что вопрос о нужности этой проверки в вашем конкретном случае вам придется решать самостоятельно. Другой пример использования критерия recent для детекции и блокирования сканирования портов: <syntaxhighlight lang="bash"> # Создаем цепочку для проверки и блокирования портсканов iptables -N portscan_check # Блокируем тех, кто был уличен в портскане в течение последних суток iptables -A portscan_check -m recent --name portscan --rcheck --seconds 86400 -j DROP # По прошествии суток можно удалять их из списка iptables -A portscan_check -m recent --name portscan --remove # Ну а сейчас — собственно процедура определения портскана iptables -A portscan_check -p tcp --dport 139 -m recent --name portscan --set -j DROP # Пускаем на проверку всех, кто пришел к нам из интернета (интерфейс eth0) iptables -I INPUT -i eth0 -j portscan_check </syntaxhighlight> В данном случае сканированием портов считается обращение на порт 139/tcp ({{w |SMB}}). Впрочем, вы можете задать другой порт или, используя критерий multiport, даже список портов. В отличие от предыдущего примера, здесь производится автоматическая очистка списка {{w |IP-адрес}}ов: по прошествии суток с момента блокировки, первое же обращение с заблокированного адреса на наш сервер приводит к удалению этого адреса из нашего recent-списка. Однако, если это обращение вновь является попыткой сканирования портов, то есть направлено на порт 139/tcp, адрес тут же блокируется вновь. Именно поэтому процедура блокировки расположена «ниже по течению», чем процедура удаления адреса из списка. Для предыдущего примера реализация очистки списка адресов достигается следующим образом: <syntaxhighlight lang="bash"> # Создаем цепочку для проверки на необходимость удаления iptables -N recent_remove # Последнее обращение на неиспользуемые порты было менее суток назад # поэтому оставим-ка пока этот адресок в черном списке iptables -A recent_remove -m recent --rcheck --seconds 86400 -j RETURN # Если адрес в есть в списке — удаляем его оттуда iptables -A recent_remove -m recent --remove # Вставляем эту проверку вторым правилом (сразу после проверки ctstate) iptables -I INPUT 2 -j recent_remove </syntaxhighlight> Проводя аналогию с ныне почившим проектом [http://www.opennet.ru/docs/RUS/portsentry/portsentry-security.html.gz PortSentry], первый наш пример соответствует режиму PortSentry «Advanced Stealth Scan Detection», а второй — «Enhanced Stealth Scan Detection». (Правда, заметим, что в режиме Advanced Stealth Scan Detection блокировка производится после ''первого'' попадания пакета на нерабочий порт — для достижения такого же эффекта в нашем примере достаточно выкинуть проверки на seconds и hitcount из блокирующих правил.) Однако, использование iptables/recent имеет значительное преимущество перед примитивными userspace-системами наподобие PortSentry — возможность интеграции с системой [[conntrack]], что позволяет избежать ошибочной блокировки, например, при использовании высоких портов для {{w |NAT}}. * Открытие порта «по стуку». Port knocking — метод защиты портов, при котором доступ к определенному порту с отдельно взятого IP-адреса открывается после серии пакетов на заданную последовательность портов с заданными интервалами. <!-- Обычно эта задача решается демоном [[knockd]]. Также сходной функциональностью обладает критерий [http://www.netfilter.org/projects/patch-o-matic/pom-external.html#pom-external-pknock pknock] из [http://www.netfilter.org/projects/patch-o-matic/pom-external.htm patch-o-matic-ng], однако он, к сожалению, потерял разработчика и прекратил развиваться.--> Обычно эта задача решается при помощи демона [[knockd]] либо критерия pknock из комплекта xtables-addons. Несколько самых простых вариантов такой защиты можно организовать и средствами критерия recent. Самое простое — открывать порт ssh (22) после стука в заданный высокий порт: <syntaxhighlight lang="bash"> iptables -N ssh_knock # Создаем цепочку для проверки попыток соединений на защищаемый порт # Если за последние 60 секунд было 2 и более стука — блокируем, на всякий случай iptables -A ssh_knock -m recent --rcheck --seconds 60 --hitcount 2 -j RETURN # Если за последние 10 секунд стук в нужный порт был — разрешить соединение iptables -A ssh_knock -m recent --rcheck --seconds 10 -j ACCEPT iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям # Все попытки открыть новое соединение по SSH направляем на проверку iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_knock # Здесь мы добавляем правило для регистрации стука iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 27520 -m recent --set # Опять же на всякий случай — при стуке в соседние порты закрываем SSH iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 27519,27521 -m recent --remove iptables -P INPUT DROP # Что не разрешено — то запрещено </syntaxhighlight> Даже в таком простом примере присутствуют жесткие меры защиты: защищаемый порт (22) открывается на 10 секунд после стука в заданный порт (27520), при этом более одного стука в этот порт в течение минуты считается ошибкой. Также стук в соседние с заданным порты сразу закрывает защищаемый порт. Это делается в целях защиты от подбора стука. Если вам не интересны такие параноидальные меры безопасности, то обратите внимание на этот простой пример: <syntaxhighlight lang="bash"> iptables -N ssh_knock # Создаем цепочку для проверки # Если за последние 10 минут было 5 и более попыток соединения — блокируем iptables -A ssh_knock -m recent --name ssh --update --seconds 600 --hitcount 5 -j RETURN # Регистрируем iptables -A ssh_knock -m recent --name ssh --set # Если за последние 5 секунд было менее двух попыток — блокируем iptables -A ssh_knock -m recent --name ssh ! --rcheck --seconds 5 --hitcount 2 -j RETURN # Все остальное — разрешаем iptables -A ssh_knock -j ACCEPT iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям # Все попытки открыть новое соединение по SSH направляем на проверку iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_knock iptables -P INPUT DROP # Что не разрешено — то запрещено </syntaxhighlight> Идея метода проста: защищаемый порт открывается со второй попытки, то есть стук идет непосредственно в него. Вторую попытку нужно сделать в течение 5 секунд после первой. При этом 5 и более попыток за десять минут блокируются (во избежание брутфорса). Также можно организовать защиту через стук в серию портов: <syntaxhighlight lang="bash"> iptables -N reset_knock # Цепочка для сброса процесса стука iptables -A reset_knock -m recent --name PHASE1 --remove iptables -A reset_knock -m recent --name PHASE2 --remove iptables -A reset_knock -m recent --name PHASE3 --remove iptables -A reset_knock -m recent --name PHASE4 --remove iptables -N in_phase_2 # Создаем цепочку для фазы 2 iptables -A in_phase_2 -m recent --name PHASE1 --remove # Удаляем запись из списка первой фазы iptables -A in_phase_2 -m recent --name PHASE2 --set # Добавляем ее в список второй фазы iptables -N in_phase_3 # Создаем цепочку для фазы 3 iptables -A in_phase_3 -m recent --name PHASE2 --remove # Удаляем запись из списка второй фазы iptables -A in_phase_3 -m recent --name PHASE3 --set # Добавляем ее в список третьей фазы iptables -N in_phase_4 # Создаем цепочку для фазы 4 iptables -A in_phase_4 -m recent --name PHASE3 --remove # Удаляем запись из списка третьей фазы iptables -A in_phase_4 -m recent --name PHASE4 --set # Добавляем ее в список четвертой фазы iptables -N checked # Для записей, прошедших проверку iptables -A checked -j reset_knock # Очищаем списки iptables -A checked -j ACCEPT # Разрешаем пакет iptables -F INPUT # Очищаем цепочку INPUT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям # Первая фаза iptables -A INPUT -p tcp --dport 21210 -m recent --name PHASE1 --set -j RETURN # Для тех, кто присутствует в списке первой фазы — переход во вторую iptables -A INPUT -p tcp --dport 11992 -m recent --rcheck --name PHASE1 --seconds 5 -g in_phase_2 # И т.д. iptables -A INPUT -p tcp --dport 16043 -m recent --rcheck --name PHASE2 --seconds 5 -g in_phase_3 iptables -A INPUT -p tcp --dport 23050 -m recent --rcheck --name PHASE3 --seconds 5 -g in_phase_4 # Если стучатся не в том порядке — сброс iptables -A INPUT -p tcp -m multiport --dport 21210,11992,16043,23050 -j reset_knock # Для тех, кто прошел все четыре фазы — разрешаем доступ iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --rcheck --name PHASE4 --seconds 5 -j checked iptables -P INPUT DROP # Дефолтное правило цепочки INPUT </syntaxhighlight> Принцип прост — при стуке в порт, соответствующий очередной фазе, проверяется наличие записи в предыдущей фазе. Теперь порт 22 откроется на 5 секунд после стука в порты 21210, 11992, 16043, 23050 со строгим соблюдением порядка перечисления и интервалами не более 5 секунд. Обратите внимание на технику реализации процесса — цепочки фаз вызываются не через <tt>-j</tt>, а через <tt>-g</tt>, поэтому после прохождения этих цепочек к пакетам сразу применяется правило по умолчанию цепочки INPUT, то есть DROP. В противном случае пакеты доходили бы до правила сброса (которое с multiport), и процесс стука все время сбрасывался бы. Последовательный стук в порты можно организовать, например, утилитой {{w |netcat}} <syntaxhighlight lang="bash"> for it in {21210,11992,16043,23050}; do echo " " | nc -w 1 host $it done ssh user@host </syntaxhighlight> Другие примеры реализации port knocking’а при помощи критерия recent можно посмотреть на [http://wiki.opennet.ru/Iptables_-m_recent OpenNet wiki], [http://www.debian-administration.org/articles/268 debian-administration.org], [http://silverghost.org.ua/2007/06/13/ssh-portknocking/ silverghost.org.ua], [http://www.opennet.ru/openforum/vsluhforumID3/41732.html#32 форуме OpenNet]. ==== Критерий u32 ==== Данный критерий предоставляет очень гибкий инструмент, позволяющий производить сложные операции по анализу содержимого пакета. Алгоритм обработки содержимого исследуемого пакета задается на специальном [[Язык программирования|языке программирования]], своеобразном «[[w:Язык ассемблера|ассемблере]]». Такой подход позволяет получить огромную гибкость, но при этом его изучение и использование может представлять определенные трудности для пользователей, не знакомых с основами [[Программирование|программирования]] и принципами работы [[Машина Тьюринга|машины Тьюринга]]. Этот критерий имеет единственный параметр — <tt>[!] --u32</tt>, после которого в двойных кавычках записывается текст «программы». Если все проверки, заданные в программе, дают истинный результат, пакет считается удовлетворяющим данному критерию. Традиционно, если перед параметром указан восклицательный знак, означающий логическое отрицание, то удовлетворяющими критерию считаются только те пакеты, для которых хотя бы одна проверка дала ложный результат. Ключевые операторы языка критерия u32: * '''=''' — оператор сравнения. Собственно, на его основе и формируются все производимые проверки. Синтаксис его вполне очевиден: <tt>выражение = значение</tt>. В качестве значения можно использовать одно число, диапазон (в формате <tt>мин:макс</tt>) или список чисел и/или диапазонов разделенных запятой (например, <tt>1,3:5,8,11:14</tt>). В одном списке можно указывать не более 10 чисел/диапазонов. * '''&&''' — оператор логического И, объединяющий все производимые в программе проверки. В одном критерии u32 можно указывать не более 10 таких проверок. Обратите внимание, что операция логического ИЛИ отсутствует, так как это противоречит идеологии iptables (в каждом правиле все проверки объединяются логическим И, а логическое ИЛИ объединяет правила в одной цепочке). * '''&''' — оператор побитового логического И, позволяющий применить к обрабатываемому значению битовую маску. * '''«''' и '''»''' — операторы побитового сдвига влево и вправо соответственно. Эквивалентны домножению или делению обрабатываемого значения на 2 в соответствующей степени. Обратите внимание, что в одном выражении для проверки можно использовать не более 9 операторов &, << и >>. * '''@''' — оператор задания смещения. Добавляет результат предыдущего выражения к текущему значению начального смещения (в начале работы программы, до выполнения @-операций, начальное смещение считается нулевым). Очень полезен в тех случаях, когда нужно сместиться на некоторое значение, полученное в результате обработки пакета, например, узнав после некоторых вычислений длину IP-заголовка, мы можем сместиться на данные непосредственно после него, то есть на начало полезной нагрузки IP-пакета (как правило, там находится заголовок [[w:Транспортный уровень|транспортного уровня]]). Все операторы имеют равный приоритет, исполнение операций всегда происходит слева направо. Обратите внимание, что программа рассматривает все значения как целые беззнаковые величины, заданные 32 битами, или четырьмя октетами (что соответствует значениям от 0 до 4294967295). Именно поэтому критерий имеет такое название (u32 — unsigned 32-bit). Другой не вполне очевидный момент — синтаксис операторов =, &, << и >>. Дело в том, что в качестве первого операнда указывается не само значение, а его ''адрес'' в пределах пакета, заданный смещением в байтах от текущего начального смещения. Например, <tt>8 = 0x12345678</tt> означает, что нужно взять четыре байта, начиная с восьмого (обратите внимание, что нумерация байтов в пакете начинается с нуля), то есть байты 8, 9, 10 и 11, и сравнить полученное значение с шестнадцатеричным числом 0x12345678. Как уже говорилось, критерий u32 ''всегда'' манипулирует блоками по четыре байта, поэтому, если вас интересуют блоки меньшего размера, используйте оператор & и маску, например, <tt>8 & 0xFF = 0x78</tt> позволяет проверить только последний в блоке (11-й от начального смещения) байт. Также можно использовать и оператор смещения, например, <tt>8 >> 24 = 0x12</tt> возьмет первый в блоке (8-й от начального смещения) байт и сравнит его с числом 0x12. Более подробно о битовых операциях можно почитать в [[w:Битовые операции|соответствующей статье]]. Рассмотрим возможности критерия u32 на нескольких простых примерах из официальной документации: * Проверить, превышает ли длина пакета величину 256 байт: <tt>--u32 "0 & 0xFFFF = 0x100:0xFFFF"</tt>. Эта программа предписывает взять четыре байта, начиная с нулевого, затем занулить первые два байта (в них [[w:IP#Пакет (датаграмма)|содержится]] информация о версии протокола, длине заголовка и [[w:Тип обслуживания|типе обслуживания]], которая нас сейчас не интересует), и проверить значение, формируемого оставшимися двумя байтами (это и есть полная длина пакета в байтах) на принадлежность диапазону от 0x100 (256 в десятичном счислении) до 0xFFFF (65535, максимально возможная длина пакета). * Проверить, является ли данный пакет {{w |ICMP}}-пакетом с типом 0 (эхо-ответ). Учитывая переменную длину IP-заголовка, эта проверка требует несколько большего количества операций: <tt>--u32 "6 & 0xFF = 1 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 0 >> 24 = 0"</tt> Рассмотрим эти операции последовательно: :* '''6 & 0xFF = 1''' — проверка кода протокола. Код протокола хранится в 9-м (считая с нуля) байте IPv4-заголовка. Чтобы получить это значение, мы берем 4-х байтовый блок с шестого по девятый байт, а затем при помощи маски выделяем последний, интересующий нас байт в это блоке, и сравниваем его с единицей (код протокола ICMP). :* '''4 & 0x3FFF = 0''' — проверка, не является ли наш пакет фрагментом. Фрагменты ICMP-пакетов не содержат ICMP-заголовка, в котором должен храниться тип ICMP, поэтому для них дальнейшая проверка не имеет смысла. Пользуясь описанным выше принципом, наша программа выделяет последние 14 бит в блоке с 4-го по 7-й байт, и сравнивает полученное значение с нулем. Строго говоря, для наших целей достаточно было бы и 13 бит (маска 0x1FFF), выделяющих только поле смещения фрагмента (fragment offset, оно должно быть равным нулю для первого пакета в цепочке фрагментов), а использование 14 бит, как это сделано в примере из официальной документации, также захватит и флаг MF (more fragments), что отсечет вообще все фрагментированные пакеты, даже те, которые являются первыми в последовательности и содержат все нужные нам заголовки. :* '''0 >> 22 & 0x3C @''' — определение длины IP-заголовка в байтах. Последние четыре бита в первом байте IP-пакета показывают длину IP-заголовка в блоках по четыре байта. Смещая это значение на 22 позиции вправо, мы оставляем справа «зазор» в два бита, которые впоследствии зануляем при помощи маски (3C<sub>16</sub> = 111100<sub>2</sub>). Также эта маска отсекает лишние биты слева (версия протокола). Полученные два нулевых бита справа соответствуют умножению на четыре, так что в результате мы получаем длину заголовка уже в байтах. Например, если длина IP-заголовка составляет 5 четырехбайтовых блоков (то есть 20 байт), то изначально первый блок заголовка имеет вид <tt>xxxx0101 yyzzzzzz uuuuuuuu uuuuuuuu</tt> (где биты <tt>xxxx</tt> задают версию протокола, 0101<sub>2</sub>=5<sub>10</sub>­ — собственно длину заголовка, <tt>yyzzzzzz</tt> — тип обслуживания, а два байта <tt>uuuuuuuu uuuuuuuu</tt> показывают полную длину пакета вместе с нагрузкой), то после смещения вправо на 22 бита мы получим в этом блоке следующую картину: <tt>00000000 00000000 000000xx xx0101yy</tt>. После применения маски она пример вид <tt>00000000 00000000 00000000 00010100</tt>. Полученное число — 10100<sub>2</sub>=20<sub>10</sub> и будет равно длине заголовка в байтах. Наконец, оператор @ устанавливает полученное значение в качестве начального смещения, поэтому вся дальнейшая адресация ведется уже начиная с начала ICMP-заголовка, который следует непосредственно после IP-заголовка. :* '''0 >> 24 = 0''' — выделяет блок с нулевого по третий байт ICMP-заголовка, а затем при помощи смещения (на три байта вправо) оставляет от него только один, нулевой, байт, в котором и хранится тип ICMP. Нас интересует тип 0, поэтому мы и сравниваем этот байт с нулем. * Проверить, задают ли байты с восьмого по одиннадцатый полезной нагрузки {{w |TCP}}-пакета одно из значений: 1, 2, 5, 8. Достигается следующим кодом: <tt>--u32 "6 & 0xFF = 6 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8"</tt> :* '''6 & 0xFF = 6''' — выделение байта с кодом протокола и сравнение его с кодом 6 (соответствует TCP). Описание этой проверки уже приведено при рассмотрении предыдущего примера. :* '''4 & 0x3FFF = 0''' — проверка, не является ли данный пакет фрагментом. Полностью аналогична описанной в предыдущем примере. :* '''0 >> 22 & 0x3C @''' — определение длины IP-заголовка в байтах. Также полностью аналогично описанному в предыдущем примере. После данной операции, начальное смещение указывает на нулевой байт TCP-заголовка. :* '''12 >> 26 & 0x3C @''' — определение длины TCP-заголовка в байтах. Принцип действия аналогичен предыдущей операции, с тем лишь отличием, что длина TCP-заголовка закодирована в первых четырех битах двенадцатого байта (а не в последних четырех битах нулевого байта, как в случае с IP-заголовком), поэтому необходимое нам смещение вправо составляет уже 26 бит. Как и в предыдущей операции, мы оставляем справа зазор в два бита, которые впоследствии зануляем маской, и таким образом сразу получаем длину заголовка в байтах. Итак, после второго оператора @, начальное смещение будет указывать на начало полезной нагрузки TCP-пакета (следует непосредственно после заголовка). :* '''8 = 1,2,5,8''' — эта операция сравнения вполне тривиальна: выделяется четырехбайтовый блок, начиная с восьмого байта (разумеется, считая от начала полезной нагрузки), и полученное значение сравнивается с одним из допустимых по условию задачи. Также, в качестве полезных примеров использования критерия u32, можно упомянуть проверку портов источника и назначения в протоколе [[UDPLite]] ([[:en:UDPLite|en]]): <tt>--u32 "6 & 0xFF = 136 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 0 >> 16 = исходный_порт"</tt> и <tt>--u32 "6 & 0xFF = 136 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 0 & OxFFFF = порт_назначения"</tt> соответственно (после сказанного выше нетрудно догадаться, что исходный порт указывается в первой паре байт UDPLite-заголовка, а порт назначения — во второй, согласно {{RFC|3828}}). ==== Прочие критерии ==== {{В планах}} ==== Критерии из набора xtables-addons ==== {{В планах}} == Программы == === Основные === ==== iptables ==== ===== Работа с цепочками ===== iptables [-t table] -N chain Создать цепочку iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...] * -F — Удалить все правила из цепочки * -L — Просмотреть цепочку * -Z — Обнулить счётчики пакетов в цепочке iptables [-t table] -P chain target Установить политику по умолчанию для цепочки iptables [-t table] -X {chain} Удалить цепочку. Внимание! На удаляемую цепочку не должно быть ссылок. ===== Работа с правилами ===== iptables [-t table] -I chain [rulenum] rule-specification Вставить правило в начало цепочки (или в позицию rulenum, считая с 1) iptables [-t table] -R chain rulenum rule-specification Заменить правило с номером rulenum на rule-specification iptables [-t table] {-A|-C|-D} chain rule-specification * -A — добавить правило в конец * -С — проверить, что такое правило есть в таблице * -D — удалить правило по описанию или по rulenum ===== Вывод информации ===== Скрипты, которые удобно использовать для вывода информации о правилах. '''1. Скрипт - показать DNAT (show-dnat.sh)''' #!/bin/bash clear & \ iptables --line-numbers -nv -t nat -L PREROUTING | \ cut -b72-89,120- | \ awk 'NR<3{print $0;next}{print $0| "sort -r"}' ''Пример вывода'' destination 111.239.125.50 multiport dports 44123 match-set WL_1CUNIVER src to:192.168.200.21:80 111.239.125.50 multiport dports 44122 match-set WL_1CUNIVER src to:192.168.1.155:80 111.234.95.9 multiport dports 22,80 to:192.168.200.24 111.234.95.8 multiport dports 8443 to:192.168.200.25:8443 111.234.95.8 multiport dports 8080 to:10.3.10.6:80 '''2. Скрипт показать правила preMANGLE (show-pre-mangle.sh)''' #!/bin/bash clear & \ iptables --line-numbers -nv -t mangle -L PREROUTING ''Пример вывода'' Chain PREROUTING (policy ACCEPT 302M packets, 242G bytes) num pkts bytes target prot opt in out source destination 1 75 4124 WWW_SERV tcp -- eth2 * 10.192.0.0/14 0.0.0.0/0 multiport dports 80,443 state NEW 2 678 44648 DROP all -- eth2 * 0.0.0.0/0 10.0.0.0/8 connmark match ! 0x210000/0xff0000 3 0 0 DROP all -- eth3 * 0.0.0.0/0 10.0.0.0/8 4 0 0 DROP all -- eth4 * 0.0.0.0/0 10.0.0.0/8 5 1721K 326M DIVERT all -- * * 0.0.0.0/0 0.0.0.0/0 socket 6 3675K 224M WWW_SERV all -- !eth0 * 0.0.0.0/0 0.0.0.0/0 match-set DNAT dst state NEW 7 36M 10G LOCAL_WWW all -- eth0 * 192.168.0.0/16 0.0.0.0/0 8 103M 97G LOCAL_WWW all -- eth0 * 10.0.0.0/8 0.0.0.0/0 '''3. Скрипт раскрашивает вывод трейсов из syslog (view-trace.sh)''' #!/bin/bash # выводит последние N строк из /var/log/syslog tail /var/log/syslog -n $1 | cut -d" " -f8-10,12-14,20-22,31 | \ sed ' s/raw/\o33[30;47m&\o033[0m/g; s/filter/\o33[31m&\o33[0m/g; s/mangle/\o33[33m&\o033[0m/g; s/nat/\o33[32m&\o033[0m/g; s/OUT=/\o033[1m&\o033[0m/g; s/IN=/\o33[1m&\o033[0m/g; s/PROTO=/\o33[1m&\o033[0m/g; s/MARK=/\o33[1m&\o033[0m/g; s/DPT=/\o33[1m&\o033[0m/g; s/SPT=/\o33[1m&\o033[0m/' ''Пример вывода'' ==== iptables-save, iptables-restore и iptables-xml ==== ==== /etc/init.d/iptables ==== ==== iptables-apply ==== ==== ipset ==== ipset работает с типами данных, которые представляют собой (man ipset): * bitmap: ip — список IP адресов из определенной подсети * bitmap: ip, mac — связки IP+MAC * bitmap: port — список портов * hash: ip — произвольный набор IP * hash: net — произвольный набор сетей * hash: mac * hash: net, net * hash: ip, port * hash: net, port * hash: ip, port, ip * hash: ip, port, net * hash: ip, mark * hash: net, port, net * hash: net, iface * list: set Пример правила iptables с применением ipset (man iptables-extensions): iptables -I INPUT 1 -i eth0 -p tcp -m tcp --dport 8080 -m set --match-set test123 src -j ACCEPT -где test123 это заданное имя сета ipset create test123 hash:net === Вспомогательные === ==== Полезные при конфигурировании фаервола ==== <!-- Пожалуй, стоит оформить их просто как список, и не мусорить в оглавлении ===== sysctl ===== ===== modprobe ===== ===== shell ===== ===== ipcalc ===== --> ==== Полезные при тестировании фаервола ==== <!-- Пожалуй, стоит оформить их просто как список, и не мусорить в оглавлении ===== ping ===== ===== nmap ===== ===== nc и telnet ===== ===== netstat и ss ===== --><blockquote>iptables -L -n -v #Статистика всех правил iptables и счетчики обработанных пакетов<br> </blockquote> == Фронтенды == === С удобным интерфейсом === === С графическим интерфейсомм === === С веб-интерфейсом === [http://www.117.su iptadmin] — это пользовательский web интерфейс для iptables, редактор настроек файрволла операционной системы Linux. Реализован в виде отдельного http(s) сервера. Особенностью программы являются подробные сообщения об ошибках при редактировании правил файрволла. iptadmin работает на уровне iptables. Настройки файрволла сохраняются в стандартных файлах. В системе не создаются никакие вспомогательные данные. Логика работы спроектирована таким образом, что нарушение целостности конфигурации iptables исключено. Iptadmin можно в любой момент установить или удалить без потери настроек файрволла. === Программные интерфейсы === == Модули ядра == === Модули conntrack и nat === === Модули критериев и действий === == Параметры {{w |sysctl}}/{{w |procfs}} == === Псевдофайлы procfs === ==== Базовые ==== ==== Относящиеся к критериям и действиям ==== === Основные параметры sysctl === ip_forward=1 === Параметры конфигурации интерфейсов === === Параметры, относящиеся к протоколам === ==== {{w |TCP}} ==== ==== {{w |UDP}} ==== ==== {{w |ICMP}} ==== === Параметры [[conntrack]] === == Расширения == === Userspace-компоненты === ==== NuFW ==== ==== l7-filter-userspace ==== ==== iplist ==== === Наборы дополнительных критериев и действий === ==== Patch-o-Matic ==== Смотри на официальном сайте http://www.netfilter.org/projects/patch-o-matic/pom-external.html ==== Patch-o-Matic-NG ==== ==== xtables-addons ==== == Команды == Программа позволяет задать правила, которым должны соответствовать проходящие через [[w:Межсетевой экран|брандмауэр]] [[IP-пакет]]ы. Эти правила, как и все настройки [[Linux]], записываются в текстовый файл, находящийся в папке /etc. Последовательность правил называется цепочкой (CHAIN). Для одного и того же сетевого интерфейса используются несколько цепочек. Если проходящий пакет не соответствует ни одному из правил, то выполняется действие по умолчанию. При вызове, параметром указывается команда, которую нужно выполнить. Обычно можно указать только одну команду (но есть исключения). Команду можно указать одной большой буквой или словом. Если при вызове любой команды не указано название таблицы, то команда выполняется в таблице filter. Программа имеет подробную справку, вызываемую командой ''man iptables''. ;Вывести правила (<tt>-L</tt>, <tt>--list</tt>) <tt>'''iptables''' [-t ''таблица''] -L [''цепочка''] [''параметры'']</tt> Вывести список правил для указанной таблицы и цепочки. Если цепочка не указана, то выводятся список правил для каждой цепочки. Например для вывода правил из таблицы nat: <tt>iptables -t nat -n -L</tt> Часто используются параметры -n (во избежение медленных запросов {{w |DNS}}) и -v (для вывода более подробной информации). Команду -L можно использовать с -Z (<tt>iptables -L -Z</tt>) для вывода значений счетчиков и одновременного их обнуления. ;Удалить все правила из цепи (<tt>-F</tt>, <tt>--flush</tt>) <tt>'''iptables''' [-t ''таблица''] -[F] [''цепочка''] [''параметры'']</tt> Если цепочка не указана, то удаляются все цепочки из таблицы. ;Обнулить все счетчики (<tt>-Z</tt>, <tt>--zero</tt>) <tt>'''iptables''' [-t ''таблица''] -Z [''цепочка''] [''параметры'']</tt> Присваивает счетчикам числа пакетов и объема данных нулевые значения. Если цепочка не указана, то обнуление выполняется для всех цепочек. Команду -Z можно использовать с -L (<tt>iptables -L -Z</tt>) для вывода значений счетчиков и одновременного их обнуления. ;Создать новую цепочку (<tt>-N</tt>, <tt>--new-chain</tt>) <tt>'''iptables''' [-t ''таблица''] -N ''цепочка''</tt> Создать новую цепочку в указанной таблице с указанным именем. Если в указанной таблице уже есть цепочка с указанным именем, то новая не создается. ;Удалить созданную цепочку (<tt>-X</tt>, <tt>--delete-chain</tt>) <tt>'''iptables''' [-t ''таблица''] -X [''цепочка'']</tt> Удалить цепочку ранее созданную с помощью команды '''-N'''. Перед удалением цепи необходимо удалить или заменить все правила, которые ссылаются на эту цепочку. Если цепочка не указана, то из таблицы будут удалены все цепи кроме стандартных (INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING). Стандартные цепочки не удаляются. ;Переименование цепи (<tt>-E</tt>, <tt>--rename-chain</tt>) <tt>'''iptables''' [-t ''таблица''] -E ''цепочка'' ''новое_название''</tt> Присваивает указанной цепочке новое название. Косметическая функция, не влияющая на функциональность. ;Установить политику для стандартной цепи (<tt>-P</tt>, <tt>--policy</tt>) <tt>'''iptables''' [-t ''таблица''] -P ''цепочка'' ''действие'' [''параметры'']</tt> Над пакетами которые доходят до конца указанной цепочки будет выполняться указанное действие. В качестве действия можно указать только ACCEPT или DROP. Устанавливать политику можно только на встроенных цепочках. Например: <tt>iptables -P INPUT DROP.</tt> === Команды модификации правил === ;Добавить новое правило (<tt>-A</tt>, <tt>--append chain</tt>) <tt>'''iptables''' [-t ''таблица''] -A ''цепочка'' ''спецификация_правила'' [''параметры'']</tt> Правило добавляется в конец указанной цепочки. Если в спецификации правила указано имя отправителя или получателя, которое одновременно соответствует нескольким адресам, то в конец цепочки добавляются правила для всех возможных комбинаций. ;Вставить новое правило (<tt>-I</tt>, <tt>--insert</tt>) <tt>'''iptables''' [-t ''таблица''] -I ''цепочка'' [''номер_правила''] спецификация_правила [''параметры'']</tt> Указанное правило вставляется в указанное место указанной цепочки. Правила нумеруются с 1, поэтому если указать номер 1 (или не указать вообще), то правило будет вставлено в начало цепочки. ;Удалить правило (<tt>-D</tt>, <tt>--delete</tt>) <tt>'''iptables''' [-t ''таблица''] -D ''цепочка'' ''номер_правила'' [''параметры'']</tt> <tt>'''iptables''' [-t ''таблица''] -D ''цепочка'' ''спецификация_правила'' [''параметры'']</tt> Правило можно указывать при помощи его номера в цепочке (нумерация начинается с 1) или его спецификации. ;Заменить правило (<tt>-R</tt>, <tt>--replace</tt>) <tt>'''iptables''' [-t ''таблица''] -R ''цепочка'' ''номер_правила'' ''спецификация_правила'' [''параметры'']</tt> Заменить правило с указанным номером в указанной цепочке. Правила нумеруются с 1. Спецификация правила не может содержать имени отправителя или получателя, которое одновременно соответствует нескольким адресам. === Параметры определения правил === '''Важно.''' В последующих версиях описанный ниже синтаксис изменился. Например, старому синтаксису * <tt>'''-s'''</tt>, <tt>--src</tt>, <tt>--source [!] ''адрес''[/''маска'']</tt> теперь соответствует новый * <tt>[!] '''-s'''</tt>, <tt>--src</tt>, <tt>--source ''адрес''[/''маска'']</tt> Перечисленные ниже параметры используются при задании спецификации правил и указываются с командами модификации правил. Эти параметры ограничивают применение правил — если обрабатываемый пакет не соответствует указанным в спецификации критериям, то указанное в правиле действие на этот пакет не распространяется. * <tt>'''-p'''</tt>, <tt>--protocol [!] ''протокол''</tt> Ограничение протокола. Основные значения: <tt>[[tcp]]</tt>, <tt>[[udp]]</tt>, <tt>[[icmp]]</tt>, или <tt>all</tt>. Протокол также можно указать с помощью номера, или названия указанного в файле <tt>/etc/protocols</tt>. Знак «!» перед именем протокола изменяет критерий на противоположенный (например <tt>!tcp</tt> означает «любой протокол, кроме TCP»). Значение «Любой протокол» можно указать с помощью слова <tt>all</tt> или числа 0. Если протокол не указан, то подразумевается «Любой протокол». * <tt>'''-s'''</tt>, <tt>--src</tt>, <tt>--source [!] ''адрес''[/''маска'']</tt> Ограничение отправителя. Адрес может быть {{w |IP-адрес}}ом (возможно с [[w:Маска подсети|маской]]), именем хоста, или доменным именем. Маска может быть в стандартном формате (например 255.255.255.0) или же в виде числа, указывающего число единиц с «левой стороны» маски (например 24). Знак «!» перед адресом изменяет критерий на противоположенный. Настоятельно не рекомендуется использовать имена, для разрешения которых требуется удаленный запрос, например по системе {{w |DNS}}. * <tt>'''-d'''</tt>, <tt>--dst</tt>, <tt>--destination [!] ''address''[/''mask'']</tt> Ограничение получателя. Синтаксис такой же, как у --src. * <tt>'''-i'''</tt>, <tt>--in-interface [!] ''имя_интерфейса''</tt> Ограничение входящего сетевого интерфейса. Знак «!» перед адресом изменяет критерий на противоположенный. Если указанное имя интерфейса заканчивается на «+», то критерию соответствуют все интерфейсы, чьи имена начинаются на указанное имя. Если параметр --in-interface не указан, то критерию соответствуют пакеты из любого сетевого интерфейса. * <tt>'''-o'''</tt>, <tt>--out-interface [!] ''имя_интерфейса''</tt> Ограничение выходящего сетевого интерфейса. Синтаксис такой же, как и для --in-interface. * <tt>[!] '''-f'''</tt>, <tt>--fragment</tt> Ограничение по фрагментам: критерию соответствуют только фрагменты пакета, начиная со второго фрагмента. Знак «!» перед адресом изменяет критерий на противоположенный. У таких фрагментов начиная со второго нет заголовка с портами отправителя и получателя (или с типом ICMP). Следовательно, такие фрагменты не соответствуют критериям, указывающим номера портов. * <tt>'''-j'''</tt>, <tt>--jump ''действие_или_цепочка''</tt> * <tt>'''-g'''</tt>, <tt>--goto ''цепочка''</tt> Спецификация действий и переходов. Если указанно название цепочки ранее созданной командой -N, то пакеты соответствующие критериям правила переносится в начало указанной цепочки (запрещено указывать название цепочки, в котором это правило находится). Если указано действие, то оно выполняется над пакетами соответствующим критериям правила. Если в правиле нет параметров --jump и --goto, то правило не влияет на проверяемые пакеты (но счетчик правила продолжает работать). --goto отличается от --jump поведением при действии RETURN. Действие RETURN переводит пакет в правило, следующее после того, которое вызвало предыдущий переход --jump. То есть, если пакет перешел из цепочки X в цепочку Y при помощи --jump, а потом в Z опять при помощи --jump, то действие RETURN из цепочки Z возвращает его в Y. Если же пакет перешел в Z при помощи --goto, то RETURN возвращает его в X. * <tt>'''-c'''</tt>, <tt>--set-counters ''пакеты байты''</tt> Параметр позволяет при добавлении или изменении правил одновременно инициализировать счетчики числа пакетов и размера данных. <sub>Подстрочный текст</sub> == Модули == Кроме фильтров по умолчанию поддерживаются дополнительные модули, подключающиеся автоматически при выборе протокола ('''-p''') или вручную опцией '''-m''' (''--match''), после которой следует имя подключаемого фильтра и его опции. Также как и для остальных правил фильтрации, здесь можно использовать '''!''' в качестве отрицания. === Некоторые из встроенных (входящие в стандартный пакет) === ==== state ==== Соединением для NetFilter является закономерно оформленная последовательность обмена пакетами между хостами, с выделением роли каждого пакета в соединении. Эта особенность позволяет контролировать трафик с точки зрения транспортного уровня (модели OSI). Ядро NetFilter отслеживает соединения и ведёт активное наблюдение за открытием новых, протеканием и завершением установленных соединений. Каждый пакет может быть классифицирован по одному из следующих состояний: NEW, ESTABLISHED, RELATED и INVALID. NEW — типов пакетов, участвующих в установке нового соединения. ESTABLISHED — пакет уже установленного соединения RELATED — Соединение получает статус RELATED если оно связано с другим соединением, имеющим признак ESTABLISHED. Это означает, что соединение получает признак RELATED тогда, когда оно инициировано из уже установленного соединения, имеющего признак ESTABLISHED. Состояние RELATED относится к служебному трафику, протоколу ICMP стека TCP/IP. INVALID — неправильный/ошибочный/испорченный пакет. Обычно для таких пакетов применяют действие DROP ПРИМЕР: iptables -t nat -A PREROUTING -s 10.10.10.10 -m conntrack --ctstate NEW,INVALID -j DROP Все новые и ошибочные пакеты, идущие с адреса 10.10.10.10 отбрасываются ==== connlimit ==== Позволяет задавать возможное количество одновременных подключений к машине от заданного IP или блока адресов <tt>[!] --connlimit-above n</tt> — пакет подойдет под описание, если количество одновременных подключений на данный момент больше (меньше), чем n <tt>--connlimit-mask bits</tt> — позволяет задать маску блока адресов iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset ==== iprange ==== Выделяет не один адрес, как <tt>--src</tt>, а все адреса от ip1 до ip2 Нужно учитывать тот факт что перед использованием данного критерия, необходимо подгрузить модуль его реализующий «-m iprange» <tt>[!]--src-range ip1-ip2</tt> <tt>[!]--dst-range ip1-ip2</tt> ==== multiport ==== Выделяет не один порт, как <tt>--dport</tt> или <tt>--sport</tt>, а несколько по списку (до 15 штук). Можно задавать диапазоны как первый_порт: последний_порт. Может быть использовано только вместе с <tt>-p udp</tt> или <tt>-p tcp</tt>. <tt>[!]--source-ports port1,port2,port3:port4</tt> <tt>[!]--destination-ports port1,port2,port3:port4</tt> <tt>[!]--ports port1,port2,port3:port4</tt> ==== mac ==== Сравнение не IP источника пакета, а его {{w |ethernet}}-адреса <tt>[!] --mac-source address</tt>. {{w |MAC-адрес}} должен быть указан в стандартном формате XX:XX:XX:XX:XX:XX. Если нужна фильтрация по MAC-адресу в мостовых соединениях (например, pppoe), то можно воспользоваться утилитой {{w |ebtables}}, которая предназначена как раз для более низкоуровневой фильтрации пакетов. Фиксируем получение IP-адреса по DHCP не из доверенного источника (MAC-адреса 00:50:8D:FD:E6:32): iptables -A INPUT -i eth0 -p UDP --sport 68 --dport 67 -m mac ! --mac-source 00:50:8D:FD:E6:32 -m limit --limit 3/minute -j LOG --log-prefix "IPT::DHCP: " --log-level warning iptables -A INPUT -i eth0 -p UDP --sport 68 --dport 67 -j ACCEPT == Примечания == {{примечания}} == Литература == * {{книга |заглавие = Linux iptables. Pocket Reference |автор = Gregor N. Purdy |isbn = 0-596-00569-5 |страницы = 97 |год = 2004 |издательство = O’Reilly }} == Ссылки == * [[Настройка межсетевого экрана в Linux]] * https://netfilter.org — Сайт проекта {{w |Netfilter}} * [http://security.maruhn.com/iptables-manual.html Man page of iptables]{{ref-en}} * [http://www.frozentux.net/documents/iptables-tutorial/ Frozentux Iptables Tutorial]*{{ref-en}} * [http://www.opennet.ru/docs/RUS/iptables Руководство по iptables (Iptables Tutorial 1.1.19)]*{{ref-ru}} * [http://wiki.archlinux.org/index.php/Simple_stateful_firewall_HOWTO#Prerequisites Простой полноценный межсетевой экран (готовый шаблон для дектопа)]{{ref-en}} * [http://posix.ru/network/iptables Настройка межсетевого экрана Iptables (готовый шаблон для дектопа)]*{{ref-ru}} * http://freecode.com/projects/flex-fw — гибкая надстройка над iptables для построения сервис-ориентированного statefull-фаервола с простым синтаксисом команд. * {{Unix man |iptables|8}}{{ref-en}} * {{Unix man |ufw|8}}{{ref-en}} * {{Unix man |gufw|8}}{{ref-en}} * https://help.ubuntu.com/community/IptablesHowTo{{ref-en}} * https://help.ubuntu.com/community/UFW{{ref-en}} * https://help.ubuntu.com/community/Gufw{{ref-en}} * https://help.ubuntu.com/9.10/serverguide/C/firewall.html{{ref-en}} * https://wiki.ubuntu.com/UncomplicatedFirewall{{ref-en}} * https://help.ubuntu.com/community/Firewall{{ref-en}} kebkhdjg3mul0fcwwahi0p551eopidf Библиотека классов RxFtp 0 12649 270429 258181 2026-10-27T07:11:20Z Jcb 79968 270429 wikitext text/x-wiki {{Название учебника |Категория = Программирование |Тип = Одностраничный }} <div align="center"> <font size="+3"> '''<br />Open Object Rexx<br />Библиотека классов RxFtp<br />Cправочник<br /><br /><br />W. David Ashley<br />Rony G. Flatscher<br />Mark Hessling<br />Rick McGuire<br />Mark Miesfeld<br />Lee Peedin<br />Jon Wolfers''' </font> </div> <div align="center"> <br />Перевод, комментарии и дополнения<ref name="tolmach" />: [[Участник:StLeutnant|StLeutnant]] <br />Оригинал: смотри на [http://www.oorexx.org/ сайте ooRexx] </div> <div align="justify"> <br />Версия 4.1.1 <br />Опубликовано {{nobr|в мае}} 2012 года. <br />Copyright (с) 1995, 2004 IBM Corporation и другие. Все права защищены. <br />Copyright (с) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Rexx Language Association. Все права защищены. Данная программа {{nobr|и сопутствующие}} материалы доступны {{nobr|для использования}} {{nobr|в соответствии}} {{nobr|с условиями}} [[w:Common_Public_License|Common Public License {{nobr|Version 1.0}}]]. {{nobr|Перед использованием}} {{nobr|этой информации}} {{nobr|и продуктов}}, доступных {{nobr|на данных}} условиях, внимательно прочитайте общие положения {{nobr|в разделах}} Уведомления. Собственником {{nobr|и обладателем}} прав {{nobr|на данный}} документ изначально являлась [[w:IBM|{{nobr|IBM Corporation}}]]. {{nobr|В 2004 году}} {{nobr|он был}} пожертвован Rexx Language Association {{nobr|на условиях}} [[w:Common_Public_License|Common Public License {{nobr|Version 1.0}}]], как «[[w:Открытое_программное_обеспечение|программное обеспечение {{nobr|с открытым}} исходным кодом]]». Благодарим Julian Choy {{nobr|за разработку}} [[w:Логотип|логотипа]] [[w:Object_REXX|ooRexx]]. </div> == Об этой книге == <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Данная книга содержит описание библиотеки {{nobr|классов RxFtp}} Open Object Rexx {{nobr|и её методов}}. Она ориентирована {{nobr|на тех пользователей}}, которые планируют вести разработку приложений {{nobr|для [[w:FTP|FTP]]}}, {{nobr|используя [[w:Rexx|Rexx]]}}, {{nobr|и может}} использоваться широким кругом читателей — {{nobr|от новичков}}, обладающих некоторыми навыками программирования {{nobr|на каком-либо}} языке, {{nobr|но не знающих}} {{nobr|ни [[w:Rexx|Rexx]]}}, {{nobr|ни [[w:FTP|FTP]]}}, {{nobr|до матёрых}} разработчиков приложений, имеющих опыт работы {{nobr|и с [[w:Object_REXX|Object Rexx]]}}, {{nobr|и с [[w:FTP|FTP]]}}. Эта книга — справочник, {{nobr|а не учебное}} пособие. Подразумевается, {{nobr|что читатели}} уже знакомы {{nobr|с концепциями}} [[w:Объектно-ориентированное_программирование|{{nobr|объектно-ориентированного}} программирования]]. Описания включают {{nobr|в себя}} синтаксис {{nobr|и использование}} конструкций языка, {{nobr|а также}} объяснение того, {{nobr|как языковый}} процессор интерпретирует их {{nobr|во время}} выполнения программы. |} </div> === Связанная информация === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Смотри также: '''Open Object Rexx: Справочник''' |} </div> === Как читать синтаксические диаграммы === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | В тексте этой книги синтаксис описывается {{nobr|в соответствии}} {{nobr|с приведёнными}} ниже правилами. * Синтаксические диаграммы читаются слева направо, сверху вниз, следуя вдоль линии маршрута. <br />Символы <span style="color:#004040"><tt>{{nobr|&gt;&gt;——}}</tt></span> начинают описание синтаксиса оператора. <br />Символы <span style="color:#004040"><tt>{{nobr|——&gt;}}</tt></span> обозначают, {{nobr|что описание}} синтаксиса оператора будет продолжено {{nobr|на следующей}} строке. <br />Символы <span style="color:#004040"><tt>{{nobr|&gt;——}}</tt></span> отмечают продолжение описания синтаксиса оператора, начатого {{nobr|в предыдущей}} строке. <br />Символы <span style="color:#004040"><tt>{{nobr|——&gt;&lt;}}</tt></span> завершают описание синтаксиса оператора. <br />Диаграммы синтаксических единиц, {{nobr|не являющихся}} полностью законченными операторами, начинаются {{nobr|с символов}} <span style="color:#004040"><tt>{{nobr|&gt;——}}</tt></span> {{nobr|и заканчиваются}} символами <span style="color:#004040"><tt>{{nobr|——&gt;}}</tt></span>. * Обязательные элементы размещаются {{nobr|на линии}} главного маршрута (горизонтальная линия {{nobr|на диаграмме}}). <span style="color:#004040">&gt;&gt;——ОПЕРАТОР——обязательный_элемент—————————————————————————————&gt;&lt;</span> * Необязательные (дополнительные) элементы размещаются ниже линии главного маршрута. <span style="color:#004040">&gt;&gt;——ОПЕРАТОР——+————————————————————————+———————————————————————&gt;&lt; +—дополнительный_элемент—+</span> * Если требуется сделать выбор одного {{nobr|из двух}} {{nobr|или более}} элементов, {{nobr|то элементы}} помещаются {{nobr|в вертикальный}} список. <br />{{nobr|Если выбор}} надо сделать обязательно, {{nobr|то первый}} элемент списка размещается {{nobr|на линии}} главного маршрута. <span style="color:#004040">&gt;&gt;——ОПЕРАТОР——+—обязательный_выбор1—+——————————————————————————&gt;&lt; +—обязательный_выбор2—+</span> * Если выбор необязательный, {{nobr|то весь}} список размещается ниже линии главного маршрута. <span style="color:#004040">&gt;&gt;——ОПЕРАТОР——+——————————————————+—————————————————————————————&gt;&lt; +—возможный_выбор1—+ +—возможный_выбор2—+</span> * Если один {{nobr|из элементов}} списка используется {{nobr|как выбор}} {{nobr|по умолчанию}}, {{nobr|то этот}} элемент размещается выше линии главного маршрута, {{nobr|а остальной}} список — ниже. <span style="color:#004040">+—выбор_по_умолчанию——+ &gt;&gt;——ОПЕРАТОР——+—————————————————————+——————————————————————————&gt;&lt; +—возможный_выбор1————+ +—возможный_выбор2————+</span> * Стрелка, возвращающаяся влево выше линии главного маршрута, означает, {{nobr|что элемент}} может повторяться. <span style="color:#004040">+———————————————————————+ V | &gt;&gt;——ОПЕРАТОР————повторяющийся_элемент—+————————————————————————&gt;&lt;</span> * Стрелка повторения элементов {{nobr|над списком}} означает, {{nobr|что можно}} повторно выбирать элементы {{nobr|из этого}} списка. * Две вертикальные полосы вокруг элемента отмечают фрагмент. Часть синтаксической диаграммы, относящаяся {{nobr|к нему}}, будет приведена {{nobr|с высокой}} детализацией сразу {{nobr|после главной}} диаграммы. <span style="color:#004040">&gt;&gt;——ОПЕРАТОР——&#124; фрагмент &#124;—————————————————————————————————————&gt;&lt; фрагмент: &#124;——расширение_с_высокой_детализациeй———————————————————————————&#124;</span> * Ключевые слова отображаются {{nobr|на диаграмме}} прописными буквами (например, <span style="color:#004040"><tt>PARM1</tt></span>). {{nobr|В тексте}} программы они {{nobr|должны быть}} записаны точно {{nobr|так же}}, {{nobr|как и на диаграмме}}, {{nobr|но можно}} использовать {{nobr|как прописные}}, {{nobr|так и строчные}} буквы. <br />Переменные отображаются {{nobr|на диаграмме}} строчными буквами (например, <span style="color:#004040"><tt>parmx</tt></span>). {{nobr|Они представляют}} собой назначаемые пользователем имена {{nobr|или значения}}<ref name="keywords" />. * Если {{nobr|на диаграмме}} отображены знаки пунктуации, скобки, арифметические операторы {{nobr|или другие}} символы, {{nobr|то их требуется}} вводить {{nobr|как часть}} синтаксиса. Следующий пример показывает {{nobr|как описывается}} синтаксис {{nobr|в таком}} случае: <span style="color:#004040">+—,——————+ V | &gt;&gt;——MAX(————number—+——)————————————————————————————————————————&gt;&lt;</span> |} </div> === Замечание о примере программы в этом документе=== <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Пример программы {{nobr|в этом}} документе представлен {{nobr|с использованием}} моноширинного шрифта, который {{nobr|не всегда}} совместим {{nobr|с функциями}} {{nobr|копирования-вставки}} текстовых редакторов. Вставка текста {{nobr|в редактор}} может привести {{nobr|к такому}} результату, {{nobr|когда часть}} символов выйдет {{nobr|за пределы}} стандартного набора {{nobr|[[w:Ascii|ASCII]]-символов}}. Особенно часто {{nobr|при вставке}} {{nobr|в текстовые}} редакторы некорректно конвертируются символы «одиночная кавычка» {{nobr|и «двойная}} кавычка». |} </div> === Помощь и обратная связь === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Проект Open Object Rexx позволяет пользователям получить помощь {{nobr|и обеспечить}} обратную связь {{nobr|с разработчиками}} несколькими способами. {{nobr|Эти способы}} перечислены ниже {{nobr|в произвольном}} порядке. |} </div> ==== Почтовая рассылка Rexx Language Association ==== <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | [http://www.rexxla.org/ Rexx Language Association] обеспечивает членов ассоциации почтовой рассылкой. {{nobr|Эта почтовая}} рассылка доступна только членам ассоциации RexxLA. {{nobr|Таким образом}}, {{nobr|для включения}} {{nobr|в список}} рассылки требуется вступить {{nobr|в RexxLA}}. Взносы {{nobr|для членов}} ассоциации невелики {{nobr|и оплачиваются}} ежегодно. {{nobr|За подробностями}} вступления {{nobr|в RexxLA}} следует обратиться [http://rexxla.org/ {{nobr|на домашнюю}} страницу {{nobr|сайта RexxLA}}] или [http://www.rexxla.org/rexxla/join.html {{nobr|на страницу}} оформления заявки {{nobr|на вступление}}]. |} </div> ==== Проект Open Object Rexx на сайте SourceForge ==== <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | [http://www.oorexx.org/ Проект Open Object Rexx] использует [http://sourceforge.net/ SourceForge] {{nobr|в качестве}} домашней площадки [http://sourceforge.net/projects/oorexx проекта ooRexx] {{nobr|для организации}} хранилищ исходных кодов, почтовых рассылок {{nobr|и прочих служб}} проекта. {{nobr|Ниже приведён}} список наиболее востребованных возможностей. '''Форумы ooRexx''' Проект ooRexx обслуживает группу форумов, {{nobr|на которых}} каждый может поднять любые темы, связанные {{nobr|с ooRexx}}, принять участие {{nobr|в их обсуждении}} {{nobr|или наблюдать}} {{nobr|за обсуждением}}. Форумы размещены [http://sourceforge.net/forum/?group_id=119701 {{nobr|на странице}} фoрумов ooRexx]. {{nobr|В настоящее}} время доступны три форума: Помощь, Разработчики {{nobr|и Открытое}} Обсуждение. Дополнительно, можно наблюдать {{nobr|за дискуссиями}} {{nobr|на форумах}} {{nobr|с помощью}} электронной почты. '''Список почтовой рассылки разработчиков''' Подписаться {{nobr|на почтовую}} рассылку разработчиков ooRexx можно [http://sourceforge.net/mail/?group_id=119701 {{nobr|на странице}} подписки {{nobr|на почтовые}} рассылки ooRexx]. {{nobr|Эта рассылка}} предназначена {{nobr|для обсуждения}} новых разработок проекта ooRexx {{nobr|и дальнейших}} усовершенствований интерпретатора. Также поддерживается исторический архив прошедших обсуждений. '''Список почтовой рассылки пользователей''' Подписаться {{nobr|на почтовую}} рассылку пользователей ooRexx можно [http://sourceforge.net/mail/?group_id=119701 {{nobr|на странице}} подписки {{nobr|на почтовые}} рассылки ooRexx]. {{nobr|Эта рассылка}} предназначена {{nobr|для обсуждения}} применения ooRexx. Также поддерживается исторический архив прошедших обсуждений. '''Список почтовой рассылки оповещений''' Подписаться {{nobr|на почтовую}} рассылку оповещений {{nobr|о событиях}} ooRexx можно [http://sourceforge.net/mail/?group_id=119701 {{nobr|на странице}} подписки {{nobr|на почтовые}} рассылки ooRexx]. {{nobr|Эта рассылка}} используется только {{nobr|для оповещения}} {{nobr|о значимых}} {{nobr|для проекта}} ooRexx событиях. '''Список почтовой рассылки системы учёта ошибок''' Подписаться {{nobr|на почтовую}} рассылку системы учёта ошибок ooRexx можно [http://sourceforge.net/mail/?group_id=119701 {{nobr|на странице}} подписки {{nobr|на почтовые}} рассылки ooRexx]. {{nobr|Эта рассылка}} используется только {{nobr|для наблюдения}} {{nobr|за изменением}} состояния записей {{nobr|в системе}} учёта ошибок ooRexx. '''Отчёты от ошибках''' Создать отчёт {{nobr|об ошибках}} можно [http://sourceforge.net/tracker/?group_id=119701&atid=684730 {{nobr|на странице}} отчётов {{nobr|об ошибках}} ooRexx]. Пожалуйста, убедитесь, {{nobr|что в отчёте}} предоставлено {{nobr|как можно}} больше информации, {{nobr|чтобы разработчики}} могли {{nobr|как можно}} быстрее решить проблему. Примеры программ, {{nobr|в которых}} воспроизводится возникшая проблема, позволят облегчить поиски {{nobr|её решения}}. '''Обратная связь для обсуждения документации''' Предоставить обратный адрес {{nobr|для обсуждения}} документации {{nobr|или сообщить}} {{nobr|об ошибках}} {{nobr|в ней}} можно [http://sourceforge.net/tracker/?group_id=119701&atid=1001880 {{nobr|на странице}} отчётов {{nobr|о документации}} ooRexx]. Пожалуйста, убедитесь, {{nobr|что в отчёте}} предоставлено {{nobr|как можно}} больше информации. Выделение проблемного места кавычками, {{nobr|в дополнение}} {{nobr|к распечатке}} документа {{nobr|и указанию}} номера раздела, поможет разработчикам определить местоположение текста {{nobr|в исходном}} материале, использованном {{nobr|при подготовке}} документации (номера разделов генерируются {{nobr|при подготовке}} документации {{nobr|и отсутствуют}} {{nobr|в исходных}} материалах {{nobr|как таковые}}). {{nobr|Также следует}} включить предложения {{nobr|о том}}, {{nobr|как перефразировать}} {{nobr|или исправить}} существующий текст. '''Запрос на усовершенствование''' Предложить реализовать новые возможности ooRexx можно [http://sourceforge.net/tracker/?group_id=119701&atid=684733 {{nobr|на странице}} запросов усовершенствований ooRexx]. '''Отчёты об исправлениях''' Если вы создали исправление, улучшающее функционирование {{nobr|или расширяющее}} возможности ooRexx, пожалуйста, {{nobr|перешлите его}}, используя [http://sourceforge.net/tracker/?group_id=119701&atid=684732 страницу отчётов {{nobr|об исправлениях}} ooRexx]. Пожалуйста, предоставьте {{nobr|в отчёте}} {{nobr|как можно}} больше информации {{nobr|об исправлении}}, {{nobr|чтобы разработчики}} могли {{nobr|как можно}} быстрее {{nobr|оценить его}}. Пожалуйста, {{nobr|не пересылайте}} {{nobr|этим путём}} исправления, устраняющие ошибки; используйте {{nobr|для этого}} отчёт {{nobr|об ошибках}} {{nobr|и вложите}} {{nobr|в сообщение}} {{nobr|своё исправление}}. |} </div> ==== Группа новостей comp.lang.rexx ==== <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Группа новостей comp.lang.rexx — прекрасное место {{nobr|для получения}} помощи {{nobr|от множества}} представителей сообщества специалистов, {{nobr|использующих Rexx}}. {{nobr|Здесь можно}} получить помощь {{nobr|не только}} {{nobr|по Open}} Object Rexx, {{nobr|но и по любому}} количеству других интерпретаторов {{nobr|и инструментов Rexx}}. |} </div> == Что такое RxFtp? == <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | RxFtp — это библиотека классов Object Rexx, предоставляющая доступ {{nobr|к [[w:TCP|TCP]]/[[w:IP|IP]]}} {{nobr|интерфейсу [[w:FTP|FTP]]}}, основанному {{nobr|на {{RFC|959}}}}. Предполагается, {{nobr|что читатель}} знаком {{nobr|с базовой}} {{nobr|функциональностью [[w:FTP|FTP]]}} {{nobr|и её}} спецификой {{nobr|в системе}}. {{nobr|За более}} подробной информацией обратитесь {{nobr|к книге}} {{nobr|Douglas Comer}} «Internetworking {{nobr|with TCP/IP}}, {{nobr|Volume I}}: Principles, Protocols {{nobr|and Architecture}}» (Prentice {{nobr|Hall PTR}}). {{nobr|Для работы}} {{nobr|пакету RxFtp}} требуется пакет внешних {{nobr|функций RxSock}}, поддерживаемый Open Object Rexx. |} </div> == Установка == <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Пакет RxFtp содержится {{nobr|в файле '''rxftp.cls'''}}. {{nobr|Этот файл}} {{nobr|должен быть}} помещен {{nobr|в один}} {{nobr|из каталогов}}, перечисленных {{nobr|в переменной}} {{nobr|окружения PATH}}. {{nobr|Для получения}} доступа {{nobr|к классу}} {{nobr|и его методам}} необходимо добавить {{nobr|директиву '''::REQUIRES'''}} {{nobr|в каждый}} скрипт {{nobr|Object Rexx}}, {{nobr|который будет}} использовать {{nobr|этот класс}}: <span style="color:#004040">. . . ::requires &quot;rxftp.cls&quot;</span> Создать конкретный экземпляр класса можно {{nobr|по обычным}} соглашениям {{nobr|Object Rexx}}: <span style="color:#004040">obj = .rxftp~new</span> Каждый экземпляр класса полностью инкапсулирует сессию {{nobr|с сервером [[w:FTP|FTP]]}}. {{nobr|Это значит}}, {{nobr|что возможно}} создание множества экземпляров класса {{nobr|и наличие}} множества открытых соединений {{nobr|с серверами [[w:FTP|FTP]]}} одновременно. |} </div> === Замечания по использованию RxFtp === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | # Метод '''FtpProxy''' отсутствует в классе RxFtp. # [[w:Firewall|Межсетевые экраны]] могут препятствовать нормальной работе многих {{nobr|методов RxFtp}}, например, ограничением передачи данных {{nobr|как в активном}}, {{nobr|так и в пассивном}} {{nobr|режимах [[w:FTP|FTP]]}}. Особенно {{nobr|это касается}} активного {{nobr|режима [[w:FTP|FTP]]}}, {{nobr|когда клиент}} работает {{nobr|за локальным}} [[w:Firewall|межсетевым экраном]] (например, {{nobr|в [[w:Windows_XP|WindowsXP]] SP2}} {{nobr|или в большинстве}} современных {{nobr|сборок [[w:Linux|Linux]]}}). # Каждый экземпляр класса RxFtp устанавливает собственное соединение {{nobr|с сервером [[w:FTP|FTP]]}}. {{nobr|Таким образом}}, можно создать множество экземпляров {{nobr|этого класса}} {{nobr|и соединиться}} {{nobr|с множеством}} {{nobr|серверов [[w:FTP|FTP]]}} одновременно. {{nobr|Также каждый}} экземпляр класса можно использовать повторно — экземпляр класса, деинициализированный методом '''FtpLogoff''', {{nobr|можно повторно}} инициализировать методом '''FtpSetUser''', {{nobr|который установит}} {{nobr|новое соединение}} {{nobr|с сервером [[w:FTP|FTP]]}}. |} </div> == Методы RxFtp == <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Каждый параграф этой главы описывает вызов одного из методов RxFtp в программном окружении [[w:Rexx|Rexx]]. |} </div> === FtpAppend === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpAppend''' дописывает содержимое локального файла {{nobr|в конец}} существующего {{nobr|на сервере [[w:FTP|FTP]]}} файла. {{nobr|Если указанный}} файл {{nobr|не существует}} {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|то он создаётся}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpAppend(——localfile,——remotefile——+———————————+——)———————&gt;&lt; +——,——type——+</span> '''''Аргументы''''': :'''localfile''' ::Имя и, возможно, путь {{nobr|к локальному}} файлу, {{nobr|который будет}} дописан {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}. :'''remotefile''' ::Имя и, возможно, путь {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|к которому}} будет дописано содержимое локального файла. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то используется}} текущий каталог {{nobr|на сервере [[w:FTP|FTP]]}}. {{nobr|Если файл}} отсутствует {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|то он создаётся}}. :'''type'''<ref name="transfer_mode" /> ::Строка, идентифицирующая тип представления данных, используемый {{nobr|при передаче}}: ::'ASCII' :::Данные в текстовом представлении [[w:Ascii|ASCII]]. ::'BINARY' :::Данные в двоичном представлении. ::Значащим является только первый символ строки, независимо от регистра. {{nobr|Если аргумент}} опущен, {{nobr|то используется}} текущий<ref name="default" /> тип представления. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpChDir === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpChDir''' назначает текущим каталогом {{nobr|на сервере [[w:FTP|FTP]]}} указанный каталог. {{nobr|Если во время}} выполнения возникли ошибки, {{nobr|то текущий}} каталог {{nobr|не изменяется}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpChDir(——remotedir——)————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''remotedir''' ::Имя и, возможно, путь {{nobr|к каталогу}} {{nobr|на сервере [[w:FTP|FTP]]}}, который будет назначен текущим. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpDelete === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpDelete''' удаляет указанный файл {{nobr|с сервера [[w:FTP|FTP]]}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpDelete(——remotefile——)——————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''remotefile''' ::Имя и, возможно, путь {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}, который будет удалён. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то используется}} текущий каталог {{nobr|на сервере [[w:FTP|FTP]]}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpDir === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpDir''' возвращает список содержимого каталога {{nobr|сервера [[w:FTP|FTP]]}} {{nobr|в полном}} формате. {{nobr|Список содержимого}} каталога помещается {{nobr|в атрибут '''Response'''}} экземпляра класса {{nobr|в виде}} массива Object Rexx, элементами которого являются строки этого списка. {{nobr|В случае}} ошибки возвращается пустой массив. {{nobr|Формат возвращаемого}} списка содержимого каталога зависит {{nobr|от операционной}} системы, установленной {{nobr|на машине}} {{nobr|с сервером [[w:FTP|FTP]]}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpDir(——+———————————+——)——————————————————————————————————&gt;&lt; +——pattern——+</span> '''''Аргументы''''': :'''pattern''' ::Шаблон имени файлов, применяемый {{nobr|для выборки}} содержимого каталога. {{nobr|В шаблоне}} можно использовать стандартные {{nobr|символы-заменители}} '*' {{nobr|и '?'}}. {{nobr|Если аргумент}} опущен, {{nobr|то, по умолчанию,}} используется {{nobr|шаблон './*'}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpGet === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpGet''' получает {{nobr|от сервера [[w:FTP|FTP]]}} одиночный файл. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpGet(——localfile,——remotefile——+———————————+——)——————————&gt;&lt; +——,——type——+</span> '''''Аргументы''''': :'''localfile''' ::Имя и, возможно, путь {{nobr|к локальному}} файлу, {{nobr|в котором}} будет сохранён полученный {{nobr|от сервера [[w:FTP|FTP]]}} файл. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то используется}} локальный текущий каталог. :'''remotefile''' ::Имя и, возможно, путь {{nobr|к отправляемому}} {{nobr|сервером [[w:FTP|FTP]]}} файлу. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то будет}} отправлен файл {{nobr|из текущего}} каталога {{nobr|сервера [[w:FTP|FTP]]}}. :'''type'''<ref name="transfer_mode" /> ::Строка, идентифицирующая тип представления данных, используемый {{nobr|при передаче}}: ::'ASCII' :::Данные в текстовом представлении [[w:Ascii|ASCII]]. ::'BINARY' :::Данные в двоичном представлении. ::Значащим является только первый символ строки, независимо от регистра. {{nobr|Если аргумент}} опущен, {{nobr|то используется}} текущий<ref name="default" /> тип представления. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpGetMode === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpGetMode'''<ref name="typo_get" /> возвращает строку, идентифицирующую текущий<ref name="default" /> {{nobr|режим [[w:FTP|FTP]]}}<ref name="ftp_mode" />. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpGetMode()———————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': :Строка, идентифицирующая текущий {{nobr|режим [[w:FTP|FTP]]}}: :'ACTIVE' ::Активный режим [[w:FTP|FTP]]. :'PASSIVE' ::Пассивный режим [[w:FTP|FTP]]. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpGetType === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpGetType'''<ref name="typo_get" /> возвращает строку, идентифицирующую текущий<ref name="default" /> тип представления<ref name="ftp_type" /> данных, использующийся {{nobr|при приёме/передаче}} данных. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpGetType()———————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': :Строка, идентифицирующая текущий тип представления данных, использующийся {{nobr|при приёме/передаче}} данных: :'ASCII' ::Данные в текстовом представлении [[w:Ascii|ASCII]]. :'BINARY' ::Данные в двоичном представлении. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpLogoff === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpLogoff''' завершает сессию {{nobr|и закрывает}} соединение {{nobr|с сервером [[w:FTP|FTP]]}}. {{nobr|Он также}} переинициализирует экземпляр класса {{nobr|и его}} {{nobr|можно будет}} использовать снова. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpLogoff()————————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpLs === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpLs''' возвращает список содержимого каталога {{nobr|сервера [[w:FTP|FTP]]}} {{nobr|в кратком}} формате. {{nobr|Список содержимого}} каталога помещается {{nobr|в атрибут '''Response'''}} экземпляра класса {{nobr|в виде}} массива Object Rexx, элементами которого являются строки этого списка. {{nobr|В случае}} ошибки возвращается пустой массив. Обычно {{nobr|в элементы}} массива помещаются только имена файлов {{nobr|из списка}} содержимого указанного каталога. {{nobr|Но формат}} данных может отличаться {{nobr|в некоторых}} случаях. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpLs(——+———————————+——)———————————————————————————————————&gt;&lt; +——pattern——+</span> '''''Аргументы''''': :'''pattern''' ::Шаблон имени файлов, применяемый {{nobr|для выборки}} содержимого каталога. {{nobr|В шаблоне}} можно использовать стандартные {{nobr|символы-заменители}} '*' {{nobr|и '?'}}. {{nobr|Если аргумент}} опущен, {{nobr|то, по умолчанию,}} используется {{nobr|шаблон './*'}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpMkDir === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpMkDir''' создаёт новый подкаталог {{nobr|на сервере [[w:FTP|FTP]]}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpMkDir(——remotedir——)————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''remotedir''' ::Имя нового подкаталога {{nobr|на сервере [[w:FTP|FTP]]}} и, возможно, путь {{nobr|к нему}}. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то подкаталог}} создаётся {{nobr|в текущем}} каталоге {{nobr|на сервере [[w:FTP|FTP]]}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpPut === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpPut''' передаёт {{nobr|на сервер [[w:FTP|FTP]]}} одиночный файл. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpPut(——localfile,——remotefile——+———————————+——)——————————&gt;&lt; +——,——type——+</span> '''''Аргументы''''': :'''localfile''' ::Имя и, возможно, путь {{nobr|к локальному}} файлу, {{nobr|который будет}} передан {{nobr|на сервер [[w:FTP|FTP]]}}. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то используется}} локальный текущий каталог. :'''remotefile''' ::Имя и, возможно, путь {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|в который}} будет сохранён передаваемый {{nobr|локальный файл}}. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то файл}} будет сохранён {{nobr|в текущий}} каталог {{nobr|сервера [[w:FTP|FTP]]}}. :'''type'''<ref name="transfer_mode" /> ::Строка, идентифицирующая тип представления данных, используемый {{nobr|при передаче}}: ::'ASCII' :::Данные в текстовом представлении [[w:Ascii|ASCII]]. ::'BINARY' :::Данные в двоичном представлении. ::Значащим является только первый символ строки, независимо от регистра. {{nobr|Если аргумент}} опущен, {{nobr|то используется}} текущий<ref name="default" /> тип представления. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpPutUnique === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpPutUnique''' передаёт {{nobr|на сервер [[w:FTP|FTP]]}} одиночный файл. {{nobr|Если файл}} существует {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|то он}} сохраняется {{nobr|с новым}} уникальным именем<ref name="name_unique" />. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpPutUnique(——localfile,——remotefile——+———————————+——)————&gt;&lt; +——,——type——+</span> '''''Аргументы''''': :'''localfile''' ::Имя и, возможно, путь {{nobr|к локальному}} файлу, {{nobr|который будет}} передан {{nobr|на сервер [[w:FTP|FTP]]}}. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то используется}} локальный текущий каталог. :'''remotefile''' ::Имя и, возможно, путь {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|в который}} будет сохранён передаваемый {{nobr|локальный файл}}. {{nobr|Если файл}} существует {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|то он}} сохраняется {{nobr|с новым}} уникальным именем<ref name="name_unique" />. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то файл}} будет сохранён {{nobr|в текущий}} каталог {{nobr|сервера [[w:FTP|FTP]]}}. :'''type'''<ref name="transfer_mode" /> ::Строка, идентифицирующая тип представления данных, используемый {{nobr|при передаче}}: ::'ASCII' :::Данные в текстовом представлении [[w:Ascii|ASCII]]. ::'BINARY' :::Данные в двоичном представлении. ::Значащим является только первый символ строки, независимо от регистра. {{nobr|Если аргумент}} опущен, {{nobr|то используется}} текущий<ref name="default" /> тип представления. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpPwd === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpPwd''' возвращает имя текущего каталога {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|включая путь}} {{nobr|к нему}}. {{nobr|Информация помещается}} {{nobr|в атрибут '''Response'''}} экземпляра класса {{nobr|в виде}} массива Object Rexx, единственным элементом которого является строка {{nobr|с именем}} текущего каталога, {{nobr|включая путь}} {{nobr|к нему}}. {{nobr|В случае}} ошибки возвращается пустой массив. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpPwd()———————————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpQuote === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpQuote''' отправляет {{nobr|серверу [[w:FTP|FTP]]}} команду {{nobr|на выполнение}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpQuote(——command——)——————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''command''' ::Команда, которую должен выполнить {{nobr|сервер [[w:FTP|FTP]]}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpRename === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpRename''' переименовывает существующий файл {{nobr|на сервере [[w:FTP|FTP]]}}. {{nobr|На серверах [[w:FTP|FTP]]}}, работающих {{nobr|под [[w:UNIX|UNIX]]}}, {{nobr|этот метод}} может также перемещать файл {{nobr|из одного}} каталога {{nobr|в другой}} {{nobr|с новым}} {{nobr|или прежним}} именем. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpRename(——remoteold,——remotenew——)———————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''remoteold''' ::Имя и, возможно, путь {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}, {{nobr|который будет}} переименован. :'''remotenew''' ::Новое имя и, возможно, путь {{nobr|к файлу}} {{nobr|на сервере [[w:FTP|FTP]]}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpRmDir === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpRmDir''' удаляет каталог {{nobr|с сервера [[w:FTP|FTP]]}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpRmDir(——remotedir——)————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''remotedir''' ::Имя удаляемого каталога {{nobr|на сервере [[w:FTP|FTP]]}} и, возможно, путь {{nobr|к нему}}. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то каталог}} удаляется {{nobr|из текущего}} каталога {{nobr|на сервере [[w:FTP|FTP]]}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpSetMode === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpSetMode''' устанавливает текущий<ref name="default" /> {{nobr|режим [[w:FTP|FTP]]}} {{nobr|для приёма/передачи}} данных. {{nobr|В случае}} ошибки текущий {{nobr|режим [[w:FTP|FTP]]}} {{nobr|не изменяется}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpSetMode(——mode——)———————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''mode''' ::Строка, идентифицирующая {{nobr|режим [[w:FTP|FTP]]}}, устанавливаемый {{nobr|в качестве}} текущего: ::'ACTIVE' :::Активный режим [[w:FTP|FTP]]. ::'PASSIVE' :::Пассивный режим [[w:FTP|FTP]]. ::Значащим является только первый символ строки, независимо от регистра. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpSetType === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpSetType''' устанавливает текущий<ref name="default" /> тип представления<ref name="ftp_type" /> данных, использующийся {{nobr|при приёме/передаче}} данных. {{nobr|В случае}} ошибки текущий тип представления данных {{nobr|не изменяется}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpSetType(——type——)———————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''type''' ::Строка, идентифицирующая тип представления данных, устанавливаемый {{nobr|в качестве}} текущего: ::'ASCII' :::Данные в текстовом представлении [[w:Ascii|ASCII]]. ::'BINARY' :::Данные в двоичном представлении. ::Значащим является только первый символ строки, независимо от регистра. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpSetUser === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpSetUser''' открывает сессию {{nobr|с сервером [[w:FTP|FTP]]}}, {{nobr|то есть}} устанавливает соединение {{nobr|и регистрирует}} пользователя. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpSetUser(——host,——user——+————————————————————————+——)————&gt;&lt; +——,——passw——+———————————+ +——,——accn——+</span> '''''Аргументы''''': :'''host''' ::Имя или [[w:IP|IP]]-адрес узла сервера [[w:FTP|FTP]]. :'''user''' ::Имя пользователя на сервере [[w:FTP|FTP]]. :'''passw''' ::Пароль пользователя. :'''accn''' ::Информация об аккаунте пользователя. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. :'''FTPHOST''' ::Имя узла неизвестно или сервер не отвечает. :'''FTPSOCKET''' ::Ошибка функции библиотеки RxSock. :'''FTPCONNECT''' ::Сервер не отвечает или не доступен. :'''FTPLOGIN''' ::Имя пользователя, пароль или информация об аккаунте не верны. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpSite === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpSite''' отправляет {{nobr|серверу [[w:FTP|FTP]]}} сервисную команду. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpSite(——command——)———————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :'''command''' ::Сервисная команда, управляющая {{nobr|сервером [[w:FTP|FTP]]}}. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpSys === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpSys''' возвращает информацию {{nobr|об операционной}} системе {{nobr|сервера [[w:FTP|FTP]]}}. {{nobr|Информация помещается}} {{nobr|в атрибут '''Response'''}} экземпляра класса {{nobr|в виде}} массива Object Rexx, единственным элементом которого является строка {{nobr|с информацией}} {{nobr|об операционной}} системе. {{nobr|В случае}} ошибки возвращается пустой массив. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpSys()———————————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpTrace === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpTrace''' запускает трассировку {{nobr|команд [[w:FTP|FTP]]}}. {{nobr|В начальном}} состоянии трассировка отключена. {{nobr|После включения}} трассировки {{nobr|на консоли}} будут отображаться {{nobr|все команды}}, отправляемые {{nobr|на сервер [[w:FTP|FTP]]}}, {{nobr|и полученные}} {{nobr|от него}} ответы. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpTrace()—————————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpTraceLog === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpTraceLog''' помещает {{nobr|все команды}}, отправляемые {{nobr|на сервер [[w:FTP|FTP]]}}, {{nobr|и полученные}} {{nobr|от него}} ответы {{nobr|в текущий}} буфер трассировки {{nobr|с последующей}} записью его {{nobr|в файл}} журнала. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpTraceLog(——localfile——+—————————————+——)————————————————&gt;&lt; +——,——action——+</span> '''''Аргументы''''': :'''localfile''' ::Имя и, возможно, путь {{nobr|к локальному}} файлу журнала. {{nobr|Если путь}} {{nobr|не указан}}, {{nobr|то используется}} локальный текущий каталог. :'''action''' ::Строка, задающая действие {{nobr|при записи}} файла журнала: ::'REPLACE' :::Если файл журнала уже существует, то перед записью новых данных {{nobr|он будет}} очищен. ::Значащим является только первый символ строки, независимо от регистра. {{nobr|Если аргумент}} опущен {{nobr|и файл}} журнала существует, {{nobr|то новые}} данные дописываются {{nobr|в конец}} файла. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpTraceLogoff === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpTraceLogoff''' останавливает трассировку {{nobr|команд [[w:FTP|FTP]]}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpTraceLogoff()———————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': ::Значение '''0''' возвращается {{nobr|в случае}} успешного выполнения. Значение '''-1''' возвращается {{nobr|в случае}} возникновение ошибки {{nobr|в ходе}} выполнения. Конкретный код ошибки можно узнать, обратившись {{nobr|к атрибуту '''FtpErrno'''}} экземпляра класса. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpVersion === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Метод '''FtpVersion''' возвращает номер версии библиотеки {{nobr|классов RxFtp}} {{nobr|в формате '''x.y.z'''}}. '''''Синтаксис''''': <span style="color:#004040">&gt;&gt;——obj~FtpVersion()———————————————————————————————————————————————&gt;&lt;</span> '''''Аргументы''''': :Аргументов нет. '''''Возвращаемое значение''''': :Строка с номером версии библиотеки {{nobr|классов RxFtp}} {{nobr|в формате '''x.y.z'''}}. [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> == Дополнительные атрибуты RxFtp == <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Каждый параграф этой главы описывает один {{nobr|из дополнительных}} атрибутов {{nobr|класса RxFtp}}. |} </div> === BufSize === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Атрибут '''BufSize''' содержит размер буфера, используемого {{nobr|методами RxFtp}}. {{nobr|По умолчанию}}, {{nobr|он равен 4096}} {{nobr|и может быть}} изменён присвоением любого целого положительного значения. Увеличение размера буфера может ускорить выполнение {{nobr|транзакций [[w:FTP|FTP]]}}. {{nobr|Однако, чрезмерно}} большой размер буфера может, наоборот, {{nobr|замедлить их}}. {{nobr|В каждом}} конкретном случае {{nobr|это выясняется}} экспериментальным путём. {{nobr|Приведённый ниже}} пример демонстрирует отображение текущего размера буфера {{nobr|на консоли}} {{nobr|и изменение}} его размера {{nobr|до 8192}}. '''''Пример''''': <span style="color:#004040">. . . say obj~BufSize obj~BufSize = 8192 . . .</span> [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === CmdResponse === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Атрибут '''CmdResponse''' представляет собой массив Object Rexx, содержащий, {{nobr|в качестве}} элементов, строки {{nobr|с командами}}, отправленными {{nobr|серверу [[w:FTP|FTP]]}}, {{nobr|и его ответы}} {{nobr|на них}}. {{nobr|Новые элементы}} последовательно добавляются {{nobr|к этому}} массиву {{nobr|при каждом}} вызове методов класса {{nobr|в текущей}} {{nobr|сессии [[w:FTP|FTP]]}}. {{nobr|Этот массив}} содержит полный протокол действий пользователя {{nobr|и реакции}} сервера {{nobr|на них}} {{nobr|в форме}} {{nobr|«команда - ответ»}}. {{nobr|Приведённый ниже}} пример отображает {{nobr|на консоли}} содержимое атрибута. '''''Пример''''': <span style="color:#004040">. . . do i = 1 to obj~cmdresponse~items say obj~cmdresponse[i] end . . .</span> [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === CR_Remove === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Атрибут '''CR_Remove''' может находиться {{nobr|в одном}} {{nobr|из двух}} состояний. {{nobr|Если он}} установлен {{nobr|в состояние '''.true'''}}, {{nobr|то символы}} {{nobr|«возврат каретки» ('0D'x, CR)}} будут автоматически удаляться {{nobr|при загрузке}} файлов {{nobr|в текстовом}} {{nobr|представлении [[w:Ascii|ASCII]]}}, {{nobr|когда класс RxFtp}} исполняется {{nobr|на платформе [[w:UNIX|UNIX]]}}. {{nobr|Если он}} установлен {{nobr|в состояние '''.false'''}}, {{nobr|то символы}} {{nobr|«возврат каретки» ('0D'x, CR)}} останутся {{nobr|в сохраняемом}} {{nobr|локальном файле}}. {{nobr|Атрибут игнорируется}} машинами {{nobr|на платформах}}, отличных {{nobr|от [[w:UNIX|UNIX]]}}. {{nobr|По умолчанию}} используется {{nobr|значение '''.true'''}}. {{nobr|Приведённый ниже}} пример отключает удаление {{nobr|символов «возврат каретки»}}. '''''Пример''''': <span style="color:#004040">. . . obj~cr_remove = .false . . .</span> [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === Debug === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Атрибут '''Debug''' может находиться {{nobr|в одном}} {{nobr|из двух}} состояний. {{nobr|Если он}} установлен {{nobr|в состояние '''.true'''}}, {{nobr|то на STDOUT}} будут отправляться отладочные сообщения. {{nobr|Если он}} установлен {{nobr|в состояние '''.false'''}}, {{nobr|то все}} отладочные сообщения подавляются. {{nobr|По умолчанию}} используется {{nobr|значение '''.false'''}}. {{nobr|Приведённый ниже}} пример включает режим отладки. '''''Пример''''': <span style="color:#004040">. . . obj~debug = .true . . .</span> [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === FtpErrno === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Атрибут '''FtpErrno''' содержит расширенную информацию {{nobr|об ошибке}}, возникшей {{nobr|во время}} выполнения {{nobr|метода RxFtp}}. {{nobr|Это может быть}} строка {{nobr|с кодом}} ошибки {{nobr|или строка}} нулевой длины, {{nobr|если метод}} завершился {{nobr|без ошибок}}. '''''Возможные значения кода ошибки''''': :'''FTPCOMMAND''' ::Ошибка {{nobr|при выполнении}} внутренней {{nobr|команды [[w:FTP|FTP]]}} {{nobr|или в аргументах}}, переданных методу {{nobr|при вызове}}. :'''FTPHOST''' ::Имя узла неизвестно или сервер не отвечает. :'''FTPSOCKET''' ::Ошибка функции библиотеки RxSock. :'''FTPCONNECT''' ::Сервер не отвечает или не доступен. :'''FTPLOGIN''' ::Имя пользователя, пароль или информация об аккаунте не верны. {{nobr|Приведённый ниже}} пример демонстрирует отображение информации {{nobr|об ошибке}} {{nobr|на консоли}}. '''''Пример''''': <span style="color:#004040">. . . if obj~ftperrno &lt;&gt; &quot;&quot; then say obj~ftperrno . . .</span> [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> === Response === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Атрибут '''Response''' может находиться {{nobr|в одном}} {{nobr|из двух}} состояний. {{nobr|Если он}} тождественнен {{nobr|объекту '''.nil'''}}, {{nobr|то это}} значит, {{nobr|что выполненная}} команда {{nobr|не сгенерировала}} ответ. {{nobr|Во всех}} остальных случаях {{nobr|атрибут '''Response'''}} представляет собой массив {{nobr|Object Rexx}}, содержащий, {{nobr|в качестве}} элементов, строки сгенерированного {{nobr|командой ответа}}. Типичным {{nobr|значением '''Response'''}} можно считать возвращаемый {{nobr|методом '''FtpDir'''}} список содержимого каталога. {{nobr|Приведённый ниже}} пример отображает {{nobr|на консоли}} содержимое атрибута. '''''Пример''''': <span style="color:#004040">. . . if obj~response &lt;&gt; .nil then do i = 1 to obj~response~items say obj~response[i] end . . .</span> [[#BufSize|BufSize]]&nbsp;. [[#CmdResponse|CmdResponse]]&nbsp;. [[#CR_Remove|CR_Remove]]&nbsp;. [[#Debug|Debug]]&nbsp;. [[#FtpAppend|FtpAppend]]&nbsp;. [[#FtpChDir|FtpChDir]]&nbsp;. [[#FtpDelete|FtpDelete]]&nbsp;. [[#FtpDir|FtpDir]]&nbsp;. [[#FtpErrno|FtpErrno]]&nbsp;. [[#FtpGet|FtpGet]]&nbsp;. [[#FtpGetMode|FtpGetMode]]&nbsp;. [[#FtpGetType|FtpGetType]]&nbsp;. [[#FtpLogoff|FtpLogoff]]&nbsp;. [[#FtpLs|FtpLs]]&nbsp;. [[#FtpMkDir|FtpMkDir]]&nbsp;. [[#FtpPut|FtpPut]]&nbsp;. [[#FtpPutUnique|FtpPutUnique]]&nbsp;. [[#FtpPwd|FtpPwd]]&nbsp;. [[#FtpQuote|FtpQuote]]&nbsp;. [[#FtpRename|FtpRename]]&nbsp;. [[#FtpRmDir|FtpRmDir]]&nbsp;. [[#FtpSetMode|FtpSetMode]]&nbsp;. [[#FtpSetType|FtpSetType]]&nbsp;. [[#FtpSetUser|FtpSetUser]]&nbsp;. [[#FtpSite|FtpSite]]&nbsp;. [[#FtpSys|FtpSys]]&nbsp;. [[#FtpTrace|FtpTrace]]&nbsp;. [[#FtpTraceLog|FtpTraceLog]]&nbsp;. [[#FtpTraceLogoff|FtpTraceLogoff]]&nbsp;. [[#FtpVersion|FtpVersion]]&nbsp;. [[#Response|Response]]&nbsp;. |} </div> == Приложения == === Пример программы, использующей класс RxFtp === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Следующий ниже пример демонстрирует использование методов библиотеки {{nobr|классов RxFtp}}. <span style="color:#004040"> /*============================================================*/ /* Basic RxFTP sample to send a file with cmd/reply logging */ /*============================================================*/ /* Define the variables for: */ server = &quot;127.0.0.1&quot; /* IP address or server name */ userid = &quot;remote_user_ID&quot; passwd = &quot;password_of_remote_user&quot; trclog = &quot;logfile.txt&quot; /* Trace log file name */ retc = 0 /* Set return code to 0 */ myftp = .rxftp~new() /* Start tracing FTP commands and logging of replies */ retc = myftp~FtpTrace() /* Trace log file will be replaced, not appended to. */ retc = myftp~FtpTraceLog(trclog, &quot;R&quot;) If retc = 0 then Say &quot; Replies will be written to log file: &quot;trclog&quot;.&quot; Else Say &quot; No writing to log file: &quot;trclog&quot; possible.&quot; /* Define remote host and user to be used during the session */ retc = myftp~FtpSetUser(server, userid, passwd) If retc = 0 then Say &quot; Connection established.&quot; Else Call Terminate &quot; *** Connection failed.&quot; /* Transfer an ASCII file to the remote ftp server */ retc = myftp~FtpPut(&quot;sample.rex&quot;, &quot;sample.put&quot;, &quot;ASCII&quot;) If retc = 0 then Call Terminate &quot; File has been sent. &quot; Else Call Terminate &quot; *** File has NOT been sent.&quot; /* Terminate the file transfer */ Terminate: Parse Arg Message Say Message Say &quot;FtpErrNo =&quot; myftp~ftperrno retc = myftp~FtpLogoff() retc = myftp~FtpTraceLogoff() retc = myftp~FtpTrace() exit retc ::requires &quot;rxftp.cls&quot; </span> |} </div> === Замечания === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Любая ссылка {{nobr|на продукт}}, программу {{nobr|или службу}}, {{nobr|не являющуюся}} программным обеспечением {{nobr|с открытым}} исходным кодом, {{nobr|не означает}} {{nobr|и не подразумевает}}, {{nobr|что может}} использоваться только продукт, программа {{nobr|или служба}}, {{nobr|не явлющаяся}} программным обеспечением {{nobr|с открытым}} {{nobr|исходным кодом}}. {{nobr|Вместо этого}} может использоваться любой функционально эквивалентный продукт, программа {{nobr|или служба}}, {{nobr|не нарушающая}} право интеллектуальной собственности Rexx Language {{nobr|Association (RexxLA)}}. {{nobr|Однако, пользователь}} может оценить {{nobr|и проверить}} работу {{nobr|любого продукта}}, программы {{nobr|или службы}}, {{nobr|не явлющихся}} программным обеспечением {{nobr|с открытым}} исходным кодом. {{nobr|Все данные}} {{nobr|о производительности}}, {{nobr|содержащиеся здесь}}, {{nobr|были получены}} {{nobr|в определенной}} {{nobr|операционной среде}}. {{nobr|Поэтому результаты}}, полученные {{nobr|в другой}} операционной среде, могут {{nobr|значительно отличаться}}. {{nobr|Некоторые замеры}}, возможно, были сделаны {{nobr|в системах}} уровня разработки {{nobr|и нет}} {{nobr|никакой гарантии}}, {{nobr|что такие же}} замеры дадут {{nobr|те же самые}} результаты {{nobr|в общедоступных}} системах. {{nobr|Кроме того}}, некоторые результаты, возможно, были получены методом экстраполяции. {{nobr|Фактические же}} результаты могут отличаться. Пользователи этого документа должны проверить применимость данных {{nobr|для своей}} операционной среды. Информация {{nobr|о продуктах}}, {{nobr|не являющихся}} программным обеспечением {{nobr|с открытым}} исходным кодом, была получена {{nobr|от поставщиков}} {{nobr|этих продуктов}}, опубликованных объявлений {{nobr|или других}} публично доступных источников. {{nobr|RexxLA не тестировала}} {{nobr|эти продукты}} {{nobr|и не может}} подтвердить точность сведений {{nobr|о производительности}}, совместимости {{nobr|или любых}} {{nobr|других требований}}, связанных {{nobr|с пакетами}}, {{nobr|не принадлежащими RexxLA}}. Вопросы {{nobr|о возможностях}} пакетов, {{nobr|не принадлежащих RexxLA}}, должны адресоваться поставщикам {{nobr|этих продуктов}}. {{nobr|Все заявления}} относительно будущего направления {{nobr|и перспектив}} {{nobr|развития RexxLA}} {{nobr|могут быть}} измененены {{nobr|или отброшены}} {{nobr|без уведомления}} {{nobr|и отражают}} только поставленные цели {{nobr|и задачи}}. Этот документ содержит примеры данных {{nobr|и отчетов}}, использующихся {{nobr|в ежедневных}} {{nobr|деловых операциях}}. {{nobr|Чтобы проиллюстрировать}} их максимально полно, примеры включают {{nobr|в себя}} имена людей, компаний, брендов {{nobr|и продуктов}}. {{nobr|Все эти имена}} — вымышленные {{nobr|и любые}} совпадения имен {{nobr|и адресов}}, используемых вымышленными коммерческими предприятиями, полностью случайны. |} </div> ==== Торговые марки ==== <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Open Object Rexx и ooRexx — торговая марка Rexx Language Association. Следующие названия являются торговыми марками IBM Corporation {{nobr|в США}}, {{nobr|в других}} странах {{nobr|или во всём}} мире: :1-2-3 :AIX :IBM :Lotus :OS/2 :S/390 :VisualAge AMD — торговая марка Advance Micro Devices, Inc. Intel, Intel Inside (логотипы), MMX и Pentium — торговые марки Intel Corporation {{nobr|в США}}, {{nobr|в других}} странах {{nobr|или во всём}} мире. Java и все, относящиеся к Java, торговые марки принадлежат Sun {{nobr|Microsystems, Inc}}. {{nobr|в США}}, {{nobr|в других}} странах {{nobr|или во всём}} мире. Linux — торговая марка Linus Torvalds {{nobr|в США}}, {{nobr|в других}} странах {{nobr|или во всём}} мире. Microsoft, Windows, Windows NT и логотип Windows — торговые марки Microsoft Corporation {{nobr|в США}}, {{nobr|в других}} странах {{nobr|или во всём}} мире. UNIX — зарегистрированная торговая марка Open Group {{nobr|в США}} {{nobr|и в других}} странах. Имена других компаний, продуктов {{nobr|или служб}} могут быть {{nobr|чьими-то}} торговыми {{nobr|или сервисными}} марками. |} </div> ==== Исходный код документа ==== <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | Исходный код этого документа доступен {{nobr|на условиях}} [[w:Common_Public_License|Common Public License {{nobr|Version 1.0}}]], которая распространяется {{nobr|вместе с документом}} {{nobr|и доступна}} {{nobr|в приложении}} «Common Public License {{nobr|Version 1.0}}». {{nobr|Сам исходный код}} документа доступен {{nobr|на странице}} [http://sourceforge.net/project/showfiles.php?group_id=119701 http://sourceforge.net/project/showfiles.php?group_id=119701]. {{nobr|Исходный код}} {{nobr|этого документа}} подготовлен {{nobr|в формате}} DocBook {{nobr|SGML/XML}}. |} </div> === Common Public License Version 1.0 === <div align="justify" style="background:#e8e8e8"> {| border="0" cellpadding="10" | '''От переводчика:''' ссылки {{nobr|на перевод}} текста лицензии можно найти {{nobr|на странице}} [[w:Common_Public_License|Common Public License {{nobr|Version 1.0}}]] {{nobr|в Википедии}}. |} </div> == Примечания переводчика == <div align="justify"> <references> <ref name="tolmach">Дополнения от переводчика, касающиеся сравнения данной библиотеки {{nobr|с библиотекой}} {{nobr|функций RxFtp}} {{nobr|Classic Rexx}}, вынесены {{nobr|на отдельные}} страницы. </ref> <ref name="keywords">Дополнительно к сказанному, авторы документа придерживаются правила записи имен методов {{nobr|и атрибутов}} класса {{nobr|на синтаксических}} диаграммах смешанным стилем {{nobr|с использованием}} прописных {{nobr|и строчных}} букв, например, <span style="color:#004040"><tt>FtpAppend</tt></span>. </ref> <ref name="transfer_mode">В оригинале — '''mode'''. {{nobr|А в описании}} аргумента авторы используют термин «режим передачи» ({{lang-en|transfer mode}}). Однако, {{nobr|в {{RFC|959}}}} понятие «режим передачи» ({{lang-en|transfer mode}}) увязано {{nobr|со способом}} организации данных {{nobr|для передачи}}, задаваемым {{nobr|командой [[w:FTP|FTP]]}} '''MODE''': STREAM, BLOCK {{nobr|или COMPRESSED}}. {{nobr|А ключевые}} слова BINARY {{nobr|и ASCII}} связаны {{nobr|с понятием}} «тип представления» ({{lang-en|representation type}}), {{nobr|то есть с тем}}, {{nobr|что представляют}} собой передаваемые данные — {{nobr|текст в [[w:Ascii|ASCII]]}}, {{nobr|текст в [[w:EBCDIC|EBCDIC]]}}, просто двоичные данные {{nobr|и так далее}}. Задаёт тип представления данных, используемый {{nobr|при передаче}} {{nobr|и хранении}}, {{nobr|команда [[w:FTP|FTP]]}} '''TYPE''': ASCII, EBCDIC, IMAGE {{nobr|(он же BINARY)}} {{nobr|и так далее}}. Поэтому {{nobr|при переводе}}, {{nobr|чтобы устранить}} возникающую путаницу, переводчик счёл возможным изменить имя аргумента '''mode''' {{nobr|на '''type'''}} {{nobr|в описании}} синтаксиса {{nobr|и применить}} более подходящий термин «тип представления» {{nobr|в описании}} аргумента. </ref> <ref name="default">При инициализации экземпляра класса текущими становятся пассивный {{nobr|режим [[w:FTP|FTP]]}} {{nobr|и тип}} представления данных {{nobr|в виде}} {{nobr|текста [[w:Ascii|ASCII]]}}. </ref> <ref name="typo_get">В оригинале — '''FtpSetType''', но это явно опечатка. </ref> <ref name="ftp_mode">В оригинале — {{lang-en|transfer mode}} (режим передачи). Однако, {{nobr|в {{RFC|959}}}} понятие «режим передачи» ({{lang-en|transfer mode}}) увязано {{nobr|со способом}} организации данных {{nobr|для передачи}}, задаваемым {{nobr|командой [[w:FTP|FTP]]}} '''MODE''': STREAM, BLOCK {{nobr|или COMPRESSED}}. {{nobr|Понятия же}} {{nobr|«активный режим»}} {{nobr|и «пассивный режим»}} связаны {{nobr|с различием}} способов организации канала данных, применяемых {{nobr|командами [[w:FTP|FTP]]}} '''PORT''' {{nobr|и '''PASV'''}}. Поэтому {{nobr|при переводе}}, {{nobr|чтобы устранить}} возникающую путаницу, переводчик использовал термин {{nobr|«режим [[w:FTP|FTP]]»}}. </ref> <ref name="ftp_type">В оригинале — {{lang-en|transfer type}} (тип передачи). Переводчик счёл более уместным использовать термин {{nobr|«тип представления»}} {{nobr|({{lang-en|representation type}})}} {{nobr|из {{RFC|959}}}}. </ref> <ref name="name_unique">Новое уникальное имя обычно образуется добавлением цифрового индекса {{nobr|к имени}} файла. </ref> </references> </div> j7p3h3o9wvvbe48qkkenqptgniv0p36 Python/Учебник Python 3.6 0 21968 270437 256476 2026-10-27T07:39:27Z Jcb 79968 270437 wikitext text/x-wiki {{Python/DocPart}} __TOC__ === Описание === Python — мощный и простой для изучения язык программирования. В нём предоставлены проработанные высокоуровневые структуры данных и простой, но эффективный подход к объектно-ориентированному программированию. Сочетание изящного синтаксиса и динамической типизации, совмещённых с интерпретируемой сущностью, делает Python идеальным языком для написания сценариев и ускоренной разработки приложений в различных сферах и на большинстве платформ. Интерпретатор Python и разрастающаяся стандартная библиотека находятся в свободном доступе в виде исходников и бинарных файлов для всех основных платформ на официальном сайте Python http://www.python.org и могут распространяться без ограничений. Кроме этого на сайте содержатся дистрибутивы и ссылки на многочисленные модули третьих сторон для языка Python, различные программы и инструменты, а также дополнительная документация. Интерпретатор Python может быть легко расширен с помощью новых функций и типов данных, написанных на C/C++ (или других языков, к которым можно получить доступ из C). Также Python можно применять как язык расширений для настраиваемых приложений. Этот учебник неформально представляет читателю основные концепции и возможности языка и системы Python. Полезно держать интерпретатор Python под рукой для получения практического опыта, но при этом все примеры самодостаточны, так что учебник вполне возможно читать вне сети. Описание стандартных объектов и модулей вы можете найти в [[Справочник по библиотеке Python 3.1|справочнике по библиотеке Python]]. [[Справочник по языку Python 3.1|Руководство по языку]] даёт более формальное описание языка. Перед написанием расширений на C/C++ ознакомьтесь с [[Расширение и встраивание - Python 3.1|руководством по расширению и встраиванию в интерпретатор]] и [[Python 3.1 - C API|справочником по Python/C API]]. Существует также несколько книг, в которых подробно рассмотрен язык Python. Этот учебник не претендует на звание всеобъемлющего и не описывает каждую особенность Python: он даже не описывает ''всех'' его часто использующихся особенностей. Вместо этого он знакомит читателя с наиболее заслуживающими внимания из них и даёт вам представление о стиле и ''привкусе'' языка. После прочтения учебника вы сможете писать и читать программы и модули, написанные на Python, и будете готовы узнать больше о различных модулях библиотеки Python, описанных в [[Справочник по библиотеке Python 3.1|справочнике по библиотеке Python]]. Кроме того, будет нелишним полистать [[Глоссарий Python 3.1|Глоссарий]]. == Разжигая ваш аппетит == Если вы много работаете за компьютером — то периодически обнаруживаете задачи, которые хотели бы автоматизировать. Например, вы были бы не против ускорить операцию поиска и замены большого количества текстовых файлов, или как-то своеобразно переименовать и отсортировать набор фотографий. Возможно, вам хотелось бы написать небольшую базу данных на заказ, специализированное GUI-приложение или простую игру. Если вы профессиональный разработчик программных продуктов — вероятно, вы привыкли работать с несколькими библиотеками на C/C++/Java, но находите обычный цикл написания/компиляции/тестирования/перекомпиляции кода чересчур медленным. Возможно, вы пишете набор тестов для такой библиотеки и процесс написания тестирующего кода воспринимается утомительным. Или же вы написали программу, которая должна использовать специальный язык для расширений и не хотите проектировать и разрабатывать полностью новый язык для вашего приложения. Python — язык, который вам подойдёт. Вы можете написать шелл-сценарий для Unix или использовать пакетные файлы Windows для некоторых из этих задач, но шелл-сценарии хороши лишь для перемещения файлов и замены текстовых данных — они вряд ли подойдут для написания приложений, снабженных графическим интерфейсом, или игр. Вы можете написать программу на C/C++/Java, но разработка может занять довольно много времени — даже на то, чтобы получить первый рабочий набросок, его требуется немало. Python — проще в использовании, доступен на операционных системах Windows, Mac OS X и Unix, и поможет сделать работу намного быстрее. Даже учитывая лёгкость использования, Python — полноценный язык программирования, предлагающий много больше возможностей для структурирования и поддержки крупных программ, чем могут позволить себе шелл-сценарии или пакетные файлы. С другой стороны, Python также предоставляет намного больше информации для отладки ошибок чем C и, будучи ''сверх-высокоуровневым-языком'', имеет встроенные высокоуровневые типы данных — такие, как гибкие массивы и словари. Благодаря наличию обобщённых типов данных Python применим для более широкого круга приложений, чем Awk или даже Perl, и при этом очень многие вещи остаются в языке Python как минимум настолько же простыми, насколько просты в этих языках. Python позволяет вам разделить вашу программу на модули, которые могут быть заново использованы в других программах на Python. Он поставляется вместе с внушительной коллекцией стандартных модулей, которые вы можете использовать в качестве фундамента ваших программ; или в качестве примеров для того, чтобы начать изучение Python. Многие из этих модулей предоставляют различную полезную функциональность: например, ввод-вывод для файлов, системные вызовы, сокеты, и даже инструменты для создания графического пользовательского интерфейса&nbsp;— например, Tk. Python — интерпретируемый язык, и это может сохранить вам немало времени при разработке — в компиляции и связывании нет необходимости. Интерпретатор может использоваться в интерактивном режиме, что позволяет легко экспериментировать с возможностями языка, писать программы-однодневки или проверять функции во время разработки программ методом снизу-вверх. И, кроме всего прочего — это удобный настольный калькулятор. Python даёт возможность писать компактные и удобочитаемые программы. Программы, написанные на Python, отличаются большей краткостью, чем эквиваленты на C, C++ или Java по нескольким причинам: * высокоуровневые типы данных позволяют вам выражать сложные операции в одной инструкции; * группировка инструкций выполняется отступами, а не операторными скобками; * нет необходимости в описании переменных или аргументов. Python ''расширяем'': если вы знаете, как программировать на C, то вам легко будет добавить к интерпретатору новую встроенную функцию или модуль, выполнить критические операции на максимальной скорости или связать программы на Python с библиотеками, которые могут быть доступны только в бинарной форме (например, зависящие от поставщика графические библиотеки). Если вы действительно увлечены — вы можете привязать интерпретатор Python к приложению, написанному на C — чтобы использовать его как язык расширений или командный язык этого приложения. Кстати, язык назван в честь шоу «Летающий цирк Монти Пайтона» на BBC и не имеет ничего общего с рептилиями. Ссылки на скетчи Монти Пайтона в документации не только позволены, но и поощряются! Теперь, когда ваш интерес к Python полностью пробужден, вам наверняка захочется изучить его более детально. В связи с тем, что лучший способ выучить язык — использовать его — автор приглашает вас использовать интерпретатор Python в процессе чтения. В следующей главе описана механика использования интерпретатора. Это довольно приземленная информация, но она необходима для работы с примерами, которые будут представлены позже. Остальная часть учебника описывает различные возможности языка и системы Python за счёт примеров — начиная с простых выражений, операторов и типов данных, рассматривая функции и модули, и заканчивая прикосновением к таким продвинутым концепциям как исключения и определённые пользователем<ref>''(Прим. перев.)'' Здесь и далее по учебнику понятия пользователя и программиста в некоторые моменты пересекаются, ввиду того что последний рассматривается как «пользователь языка». Обычно это понятно из контекста, но тем не менее, на всякий случай, поясняю.</ref> классы. == Использование интерпретатора Python == === Запуск интерпретатора === Интерпретатор Python после установки располагается, обычно, по пути <tt>/usr/local/bin/python3.1</tt> — на тех компьютерах, где этот путь доступен. Добавление каталога <tt>/usr/local/bin</tt> к пути поиска Unix-шелла (переменная <tt>PATH</tt>) позволит запустить интерпретатор набором команды <code>python3.1</code> прямо из шелла<ref>В случае операционных систем UNIX, интерпретатор версии 3.1 по умолчанию устанавливается с исполняемым файлом, имеющим имя, отличное от <tt>python</tt> — дабы не иметь конфликтов с (возможно) установленным исполняемым файлом версии 2.6</ref>. Поскольку выбор каталога, в котором будет обитать интерпретатор, осуществляется при его установке, то возможны и другие варианты — посоветуйтесь с вашим Python-гуру или системным администратором. (Например, путь <tt>/usr/local/python</tt> тоже популярен в качестве альтернативного расположения.) На машинах с ОС Windows, инсталляция Python обычно осуществляется в каталог <tt>C:\Python31</tt>, но и он может быть изменён во время установки. Чтобы добавить этот каталог к вашему пути поиска, вы можете набрать в окне DOS следующую команду, в ответ на приглашение: <code>set path=%path%;C:\python31</code> При наборе символа конца файла (<tt>Ctrl-D</tt> в Unix, <tt>Ctrl-Z</tt> в Windows) в ответ на основное приглашение интерпретатора, последний будет вынужден закончить работу с нулевым статусом выхода. Если это не сработает — вы можете выйти из интерпретатора путём ввода следующих команд: <syntaxhighlight lang="python">import sys; sys.exit()</syntaxhighlight> Особенности редактирования строк в интерпретаторе не оказываются обычно чересчур сложными. Те, кто установил интерпретатор на машину Unix, потенциально имеют поддержку библиотеки <tt>GNU readline</tt>, обеспечивающей усовершенствованное интерактивное редактирование и сохранение истории. Самый быстрый, наверное, способ проверить, поддерживается ли расширенное редактирование командной строки, заключается в нажатии <tt>Ctrl-P</tt> в ответ на первое полученное приглашение Python. Если вы услышите сигнал — значит вам доступно редактирование командной строки — тогда обратитесь к [[Учебник Python 3.1 — Приложения#Интерактивное редактирование входных данных и подстановка истории|Приложению об Интерактивном редактировании входных данных]] за описанием клавиш. Если на ваш взгляд ничего не произошло или отобразился символ <tt>^P</tt> — редактирование командной строки недоступно — удалять символы из текущей строки возможно будет лишь использованием клавиши <tt>Backspace</tt>. Интерпретатор ведёт себя сходно шеллу Unix: если он вызван, когда ''стандартный ввод'' привязан к устройству <tt>tty</tt> — он считывает и выполняет команды в режиме диалога; будучи вызванным с именем файла в качестве параметра или с файлом, назначенным на ''стандартный ввод'' — он читает и выполняет сценарий из этого файла. Другой способ запустить интерпретатор — директива <code>'''python -c''' ''команда'' <tt>[arg]</tt> ...</code> — при её использовании поочередно выполняются инструкции(-ция) из ''команды'' (как при использовании опции '''-c''' Unix-шелла). В связи с тем, что инструкции Python часто содержат пробелы или другие специальные для шелла символы, рекомендуется заключать ''команды'' полностью в одинарные кавычки. Некоторые модули Python оказываются полезными при использовании их в качестве сценариев. Они могут быть запущены в этом виде командой <code>'''python -m''' ''модуль'' <tt>[arg]</tt> ...</code> — таким образом исполняется исходный файл модуля (как произошло бы, если бы вы ввели его полное имя в командной строке). Обратите внимание на различие между командами <tt>python file</tt> и <tt>python <file</tt>. В последнем случае запросы на ввод из программы, такие как вызов <code>sys.stdin.read()</code>, удовлетворяются из самого файла. Поскольку файл уже был прочитан до конца ещё до начала выполнения программы — символ конца файла будет обнаружен программой незамедлительно. В большинстве случаев (это, чаще всего, и есть те ситуации, которых вы ожидали) вызовы удовлетворяются независимо от того, файл или устройство привязаны к стандартному вводу интерпретатора Python. При использовании файла сценария иногда полезно иметь возможность запустить сценарий и затем войти в интерактивный режим. Это может быть сделано через указание параметра '''-i''' перед именем сценария. (Этот способ не сработает, если сценарий считывается со стандартного ввода — по той самой причине, которая описана в предыдущем абзаце). ==== Передача параметров ==== В случае, если интерпретатору известны имя сценария и дополнительные параметры, с которыми он вызван, все они передаются сценарию в переменной <code>sys.argv</code>, представляющей собой список (<code>list</code>) строк. Длина (<code>length</code>) списка — минимум, единица; если не переданы ни имя сценария, ни аргументы — то <code>sys.argv[0]</code> содержит пустую строку. Когда в качестве имени сценария передан <code>'-'</code> (означает ''стандартный ввод''), <code>sys.argv[0]</code> устанавливается в <code>'-'</code>. Если используется директива '''-c''' ''команда'' — <code>sys.argv[0]</code> содержит <code>'-c'</code>. В случае, если используется директива '''-m''' ''модуль'' — то <code>sys.argv[0]</code> устанавливается равным полному имени модуля по расположению. Опции, обнаруженные после сочетаний '''-c''' ''команда'' или '''-m''' ''модуль'' не обрабатываются интерпретатором Python, но остаются в переменной <code>sys.argv</code>, дабы обеспечить возможность отслеживания в самой команде или в модуле. ==== Интерактивный режим ==== Если команды считываются с <tt>tty</tt> — говорят, что интерпретатор находится в ''интерактивном режиме'' (режиме диалога). В этом режиме он приглашает к вводу следующей команды, отобразив ''основное приглашение''<ref>''(Прим. перев.)'' <tt>primary prompt</tt> — ''зд.'', основное приглашение: приглашение к вводу команды или нескольких команд (сценария);</ref> (обычно это три знака «больше-чем» — <tt>&gt;&gt;&gt;</tt>); в то же время, для ''продолжающих строк''<ref>''(Прим. перев.)'' <tt>continuation lines</tt> — ''зд.'', продолжающие строки (строки продолжения): строки, продолжающие текст команды (оператора, выражения), или раскрывающие внутреннее устройство внешнего оператора (команды, выражения), в последнем случае определяются дополнительным отступом от края — углублением в структуру;</ref> выводится ''вспомогательное приглашение''<ref>''(Прим. перев.)'' <tt>secondary prompt</tt> — ''зд.'', вспомогательное приглашение: приглашение к продолжению ввода команды или набора команд (сценария) с использованием ''продолжающих строк'';</ref> (по умолчанию — три точки — <tt>...</tt>). Перед выводом первого приглашения интерпретатор отображает приветственное сообщение, содержащее номер его версии и пометку о правах копирования: <syntaxhighlight lang="python">$ python3.1 Python 3.1a1 (py3k, Sep 12 2007, 12:21:02) [GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>></syntaxhighlight> ''Продолжающие строки'' используются в случаях, когда необходимо ввести многострочную конструкцию. Взгляните, например, на следующий оператор <code>if</code><ref>''(Прим. перев.)'' Здесь и далее тексты некоторых исходных кодов также будут переведены в примечаниях (вместе с ключевыми словами, поэтому их нельзя будет запустить в интерпретаторе), чтобы показать их смысл или задумку, которые не всегда очевидны без перевода (если он вам нужен :)):<br /><br /> <code style="background-color: inherit !important;"><span style="color: #aaa">>>></span> мир_плоский = 1<br/> <span style="color: #aaa">>>></span> '''если''' мир_плоский:<br/> <span style="color: #aaa">...</span>&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("Будьте осторожны — не упадите!")<br/> <span style="color: #aaa">...</span> <br/> <span style="color: #030">Будьте осторожны — не упадите!</span></code><br /></ref>: <syntaxhighlight lang="python">>>> the_world_is_flat = 1 >>> if the_world_is_flat: ... print("Be careful not to fall off!") ... Be careful not to fall off!</syntaxhighlight> === Интерпретатор и его окружение === ==== Обработка ошибок ==== В случае появления ошибки интерпретатор выводит сообщение об ошибке, завершая его стеком вызовов. В интерактивном режиме он снова возвращается в состояние приглашения для ввода команд; если ввод происходит из файла — интерпретатор выходит с ненулевым статусом, сразу после распечатки стека вызовов. (Исключения, обрабатываемые в блоке <code>except</code> оператора <code>try</code> в этом контексте не считаются ошибками.) Некоторые ошибки исключительно фатальны и вызывают собой принудительное завершение работы с ненулевым статусом — это применимо к внутренним противоречиям языка и к некоторым случаям нехватки памяти. Все сообщения об ошибках выводятся в ''стандартный поток ошибок'' (<tt>error stream</tt>). Обычный вывод исполняемых команд направляется в ''стандартный вывод''. Нажатие клавиш прерывания процесса (обычно <tt>Ctrl-C</tt> или <tt>DEL</tt>), в ответ на приглашение в основном или вспомогательном режиме, отменяет ввод и возвращает вас к основному приглашению.<ref>Известная проблема в пакете <tt>GNU Readline</tt> может этому помешать.</ref> Символ прерывания, набранный во время выполнения какой-либо команды порождает исключение <code>KeyboardInterrupt</code>, которое, в свою очередь, может быть перехвачено оператором <code>try</code>. ==== Исполняемые сценарии на Python ==== На Unix-системах семейства BSD сценарии на Python могут быть сделаны исполняемыми, также как и шелл-сценарии, путём добавления следующей строки <code>#! /usr/bin/env python3.1</code> (предполагается, что интерпретатор может быть найден по одному из путей, указанных в пользовательской переменной <tt>PATH</tt>) в начало сценария и установки файла в исполняемый режим. Символы <tt>#!</tt> должны быть первыми символами в файле. На некоторых платформах строка должна оканчиваться символом конца строки в стиле Unix (<tt>'\n'</tt>), а не в стиле Windows (<tt>'\r\n'</tt>). Заметьте, что символ решётки <tt>'#'</tt> используется в Python для указания начала комментария. Исполняемый режим (или разрешение на исполнение) может быть установлен сценарию использованием команды '''chmod''': <code>$ chmod +x myscript.py</code> У систем с операционной системой Windows нет такого понятия, как исполняемый режим. Установщик Python автоматически связывает файлы <tt>.py</tt> с файлом <tt>python.exe</tt>, таким образом двойной клик на файле Python запустит его в виде сценария. Расширение может быть и <tt>.pyw</tt> в случае, если окно консоли (которое, обычно, отображается) при запуске сценария подавляется. ==== Кодировка исходных файлов ==== По умолчанию, исходники Python считаются созданными в кодировке <tt>UTF-8</tt>. В этой кодировке в строковых литералах, идентификаторах и комментариях могут быть использованы символы большинства языков мира — учитывая то, что стандартная библиотека Python использует символы <tt>ASCII</tt> для именования идентификаторов — и этому соглашению должен следовать любой переносимый код. Для корректного отображения всех этих символов, ваш редактор должен опознавать файл как закодированный в <tt>UTF-8</tt> и должен использовать шрифт, который содержит все символы, используемые в файле. Также, есть возможность указать другую кодировку для исходных файлов. Для этого нужно добавить специальный комментарий следом за строкой <tt>#!</tt>, дабы описать кодировку исходного файла: <code># -*- coding: encoding -*-</code> Если используется это описание — всё, что находится в этом файле будет опознаваться как имеющее соответствующую кодировку ''<tt>encoding</tt>'', а не <tt>UTF-8</tt>. Список возможных кодировок представлен в [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке]] — в разделе, описывающем модуль [[Справочник по библиотеке Python 3.1#codecs|codecs]]. Например, если выбранный вами редактор не поддерживает файлы, закодированные <tt>UTF-8</tt> и требует применения какой-либо другой кодировки, допустим <tt>Windows-1252</tt>, вы можете написать: <code># -*- coding: cp-1252 -*-</code> И, с этого момента, использовать в исходных файлах только символы из таблицы символов <tt>Windows-1252</tt>. Устанавливающий (отличную от установленной по умолчанию) кодировку специальный комментарий должен являться первой или второй строкой файла. ==== Интерактивный файл запуска ==== Если вы используете Python интерактивно — часто бывает удобным выполнить некоторые стандартные команды перед запуском интерпретатора. Вы можете сделать это, установив переменную окружения с именем <tt>PYTHONSTARTUP</tt> равной имени файла, содержащего ваши команды запуска. Способ схож с использованием файла <tt>.profile</tt> в Unix-шелле. Этот файл читается только в интерактивных сессиях, но не в случае считывания команд из сценария, и не в случае, если <tt>/dev/tty</tt> назначен как независимый источник команд (который в других случаях ведет себя сходно интерактивным сессиям). Файл исполняется в том же пространстве имён, что и исполняемые команды — поэтому объекты и импортированные модули, которые он определяет могут свободно использоваться в интерактивной сессии. Также в этом файле вы можете изменить приглашения: <code>sys.ps1</code> и <code>sys.ps2</code>. Если вы хотите прочитать дополнительный файл запуска из текущего каталога — вы можете использовать код вроде: <syntaxhighlight lang="python">if os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read())</syntaxhighlight> Если вы хотите использовать файл запуска в сценарии — вам нужно будет указать это явно: <syntaxhighlight lang="python">import os filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): exec(open(filename).read())</syntaxhighlight> == Неформальное введение в Python == В приведенных далее примерах, ввод и вывод различаются присутствием и отсутствием приглашений соответственно (приглашениями являются <tt>>>></tt> и <tt>...</tt>): чтобы воспроизвести пример — вам нужно ввести всё, что следует за приглашением, после его появления; строки, не начинающиеся с приглашений являются выводом интерпретатора. Обратите внимание, что строка, в которой содержится лишь вспомогательное приглашение («<tt>... </tt>») означает, что вам нужно ввести пустую строку — этот способ используется для завершения многострочных команд. Большинство примеров в этом руководстве — даже те, которые вводятся в интерактивном режиме — содержат комментарии. Комментарии в Python начинаются с символа решетки # (<tt>hash</tt>) — и продолжаются до физического конца строки. Комментарии могут находиться как в начале строки, так и следовать за пробельными символами или кодом — но не содержаться внутри строки. Символ решётки в строке остаётся лишь символом решётки. Поскольку комментарии предназначены для того, чтобы сделать код более понятным, и не интерпретируются Python — при вводе примеров они могут быть опущены. Несколько примеров: <syntaxhighlight lang="python"># это первый комментарий SPAM = 1 # а это второй комментарий # ... и наконец третий! STRING = "# Это не комментарий."</syntaxhighlight> === Использование Python в качестве калькулятора === Давайте опробуем несколько простых команд Python. Запустите интерпретатор и дождитесь появления основного приглашения — <tt>>>></tt>. (Это не должно занять много времени.) ==== Числа ==== Вот вам маленький пример: print("Привет, как дела?") Поведение интерпретатора сходно поведению калькулятора: вы вводите выражение, а в ответ он выводит значение. Синтаксис выражений привычен: операции <code>+</code>, <code>-</code>, <code>*</code> и <code>/</code> работают так же как и в большинстве других языков (например, Паскале или C); для группировки можно использовать скобки. Например: <syntaxhighlight lang="python">>>> 2+2 4 >>> # Это комментарий ... 2+2 4 >>> 2+2 # а вот комментарий на одной строке с кодом 4 >>> (50-5*6)/4 5.0 >>> 8/5 # При делении целых чисел дробные части не теряются 1.6000000000000001 </syntaxhighlight> ''Заметьте'': Вы можете получить результат, несколько отличный от представленного: результаты деления с плавающей запятой могут различаться на разных системах. Позже мы расскажем о том, как контролировать вывод чисел с плавающей запятой. Здесь использован наиболее информативный вариант вывода этого значения, а не более легко-читаемый, какой возможен: <syntaxhighlight lang="python">>>> print(8/5) 1.6 </syntaxhighlight> Чтобы учебник читался легче, мы будем показывать упрощённый вывод чисел с плавающей точкой и объясним позже, почему эти два способа отображения чисел с плавающей точкой стали различными. Обратитесь к приложению [[Учебник Python 3.1 — Приложения#Арифметика с плавающей точкой - Проблемы и ограничения|Арифметика с плавающей точкой: Проблемы и ограничения]], чтобы ознакомиться с подробным обсуждением. Для получения целого результата при делении целых чисел, отсекая дробные результаты, предназначена другая операция: <tt>//</tt>: <syntaxhighlight lang="python">>>> # Деление целых чисел возвращает округлённое к минимальному значение: ... 7//3 2 >>> 7//-3 -2</syntaxhighlight> Знак равенства (<code>'='</code>) используется для присваивания переменной какого-либо значения. После этого действия в интерактивном режиме ничего не выводится: <syntaxhighlight lang="python">>>> width = 20 >>> height = 5*9 >>> width * height 900</syntaxhighlight> Значение может быть присвоено нескольким переменным одновременно: <syntaxhighlight lang="python">>>> x = y = z = 0 # Нулевые x, y и z >>> x 0 >>> y 0 >>> z 0</syntaxhighlight> Переменные должны быть ''определены'' (<tt>defined</tt>) (должны иметь присвоенное значение) перед использованием, иначе будет сгенерирована ошибка: <syntaxhighlight lang="python">>>> # попытка получить доступ к неопределённой переменной ... n Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'n' is not defined</syntaxhighlight> Присутствует полная поддержка операций с плавающей точкой; операции над операндами смешанного типа конвертируют целочисленный операнд в число с плавающей запятой: <syntaxhighlight lang="python">>>> 3 * 3.75 / 1.5 7.5 >>> 7.0 / 2 3.5</syntaxhighlight> Поддерживаются и комплексные числа, добавлением к мнимым частям суффикса <code>j</code> или <code>J</code>. Комплексные числа с ненулевым вещественным компонентом записываются в виде <code>(''<вещественная_часть>''+''<мнимая_часть>''j)</code>, или могут быть созданы с помощью функции <code>complex(''<вещественная_часть>'', ''<мнимая_часть>'')</code>. <syntaxhighlight lang="python">>>> 1j * 1J (-1+0j) >>> 1j * complex(0, 1) (-1+0j) >>> 3+1j*3 (3+3j) >>> (3+1j)*3 (9+3j) >>> (1+2j)/(1+1j) (1.5+0.5j)</syntaxhighlight> Комплексные числа всегда представлены в виде двух чисел с плавающей запятой — вещественной и мнимой частями. Для получения этих частей из комплексного числа <code>z</code> используется <code>z.real</code> и <code>z.imag</code> соответственно. <syntaxhighlight lang="python">>>> a=1.5+0.5j >>> a.real 1.5 >>> a.imag 0.5</syntaxhighlight> Функции конвертации (приведения) к вещественным и целым числам (<code>float()</code>, <code>int()</code>) не работают с комплексными числами, так как нет единственно правильного способа сконвертировать комплексное число в вещественное. Используйте функцию <code>abs(z)</code> чтобы получить ''модуль'' числа (в виде числа с плавающей точкой) или <code>z.real</code> чтобы получить его вещественную часть: <syntaxhighlight lang="python">>>> a=3.0+4.0j >>> float(a) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: can`t convert complex to float; use abs(z) >>> a.real 3.0 >>> a.imag 4.0 >>> abs(a) # sqrt(a.real**2 + a.imag**2) 5.0 >>></syntaxhighlight> В интерактивном режиме последнее выведенное выражение сохраняется в переменной <code>_</code>. Это значит, что если вы используете Python в качестве настольного калькулятора — всегда есть способ продолжить вычисления с меньшими усилиями, например: <syntaxhighlight lang="python">>>> tax = 12.5 / 100 >>> price = 100.50 >>> price * tax 12.5625 >>> price + _ 113.0625 >>> round(_, 2) 113.06 >>></syntaxhighlight> Эта переменная для пользователя должна иметь статус ''только для чтения''. Не навязывайте ей значение собственноручно — вы создадите независимую переменную с таким же именем, скрывающую встроенную переменную вместе с её магическими свойствами. ==== Строки ==== Помимо чисел, Python может работать со строками, которые, в свою очередь, могут быть описаны различными способами. Строки могут быть заключены в одинарные или двойные кавычки: <syntaxhighlight lang="python">>>> 'spam eggs' 'spam eggs' >>> 'doesn\'t' "doesn't" >>> "doesn't" "doesn't" >>> '"Yes," he said.' '"Yes," he said.' >>> "\"Yes,\" he said." '"Yes," he said.' >>> '"Isn\'t," she said.' '"Isn\'t," she said.'</syntaxhighlight> Интерпретатор выводит результаты операций над строками тем же способом, каким они были введены: обрамляя в кавычки, и, кроме того, экранируя обратными слэшами внутренние кавычки и другие забавные символы — для того, чтобы отобразить точное значение. Строка заключается в двойные кавычки, если строка содержит одинарные кавычки и ни одной двойной, иначе она заключается в одинарные кавычки. Повторимся, функция <tt>print()</tt> предоставляет более читаемый вывод. Строковые литералы могут быть разнесены на несколько строк различными способами. Могут быть использованы ''продолжающие строки'', с обратным слэшем в качестве последнего символа строки, сообщающим о том, что следующая строка есть продолжение текущей<ref>''(Прим. перев.):''<syntaxhighlight lang="python">hello = "Это довольно длинная строка, содержащая\n\ несколько строк текста — такой вы бы представили её в C.\n\ Обратите внимание, что пробельное пространство в начале строки\ имеет значение." print(hello)</syntaxhighlight></ref>: <syntaxhighlight lang="python">hello = "This is a rather long string containing\n\ several lines of text just as you would do in C.\n\ Note that whitespace at the beginning of the line is\ significant." print(hello)</syntaxhighlight> Обратите внимание, что новые строки все ещё нужно подключать в строку через <code>\n</code>; новая строка, за которой следут обратный слэш — не обрабатывается. Запуск примера выведет следующее: <pre>This is a rather long string containing several lines of text just as you would do in C. Note that whitespace at the beginning of the line is significant.</pre> Если мы объявим строковой литерал ''сырым'' (<tt>raw</tt>)<ref>''(Прим. перев.)'' ''raw string'' — для описания ''сырой строки'' (не требующей последующей обработки) используется префикс '''<code>r</code>'''.</ref> — символы <code>\n</code> не будут конвертированы в новые строки, но и обратный слэш в конце строки, и символ новой строки в исходном коде — будут добавлены в строку в виде данных. Следовательно, код из примера: <syntaxhighlight lang="python">hello = r"This is a rather long string containing\n\ several lines of text much as you would do in C." print(hello)</syntaxhighlight> выведет: <pre>This is a rather long string containing\n\ several lines of text much as you would do in C.</pre> Или, строки могут быть обрамлены совпадающей парой тройных кавычек: <code>"""</code> или <code><nowiki>'''</nowiki></code>. Окончания строк не нужно завершать тройными кавычками — при этом будут включены в строку. <syntaxhighlight lang="python">print(""" Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to """)</syntaxhighlight> выводит в результате следующее: <syntaxhighlight lang="text">Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to</syntaxhighlight> Строки могут конкатенироваться (склеиваться вместе) операцией <code>+</code> и быть повторенными операцией <code>*</code>: <syntaxhighlight lang="python">>>> word = 'Help' + 'A' >>> word 'HelpA' >>> '<' + word*5 + '>' '<HelpAHelpAHelpAHelpAHelpA>'</syntaxhighlight> Два строковых литерала, расположенные друг за другом, автоматически конкатенируются; первая строка в предыдущем примере также могла быть записана как <code>word = 'Help' 'A'</code>; это работает только с двумя литералами — не с произвольными выражениями, содержащими строки. <syntaxhighlight lang="python">>>> 'str' 'ing' # <- Так — верно 'string' >>> 'str'.strip() + 'ing' # <- Так — верно 'string' >>> 'str'.strip() 'ing' # <- Так — не верно File "<stdin>", line 1, in ? 'str'.strip() 'ing' ^ SyntaxError: invalid syntax</syntaxhighlight> Строки могут быть проиндексированы; также как и в C, первый символ строки имеет индекс <tt>0</tt>. Отсутствует отдельный тип для символов; символ является строкой с единичной длиной. Как и в языке программирования Icon, подстроки могут определены через нотацию срезов (<tt>slice</tt>): два индекса, разделенных двоеточием. <syntaxhighlight lang="python">>>> word[4] 'A' >>> word[0:2] 'He' >>> word[2:4] 'lp'</syntaxhighlight> Индексы срезов имеют полезные значения по умолчанию; опущенный первый индекс заменяется нулём, опущенный второй индекс подменяется размером срезаемой строки. <syntaxhighlight lang="python">>>> word[:2] # Первые два символа 'He' >>> word[2:] # Всё, исключая первые два символа 'lpA'</syntaxhighlight> В отличие от строк в C, строки Python не могут быть изменены. Присваивание по позиции индекса строки вызывает ошибку: <syntaxhighlight lang="python">>>> word[0] = 'x' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'str' object doesn't support item assignment >>> word[:1] = 'Splat' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'str' object doesn't support slice assignment</syntaxhighlight> Тем не менее, создание новой строки со смешанным содержимым — процесс легкий и очевидный: <syntaxhighlight lang="python">>>> 'x' + word[1:] 'xelpA' >>> 'Splat' + word[4] 'SplatA'</syntaxhighlight> Полезный инвариант операции среза: <code>s[:i] + s[i:]</code> эквивалентно <code>s</code>. <syntaxhighlight lang="python">>>> word[:2] + word[2:] 'HelpA' >>> word[:3] + word[3:] 'HelpA'</syntaxhighlight> Вырождения индексов срезов обрабатываются элегантно: чересчур большой индекс заменяется на размер строки, а верхняя граница меньшая нижней возвращает пустую строку. <syntaxhighlight lang="python">>>> word[1:100] 'elpA' >>> word[10:] '' >>> word[2:1] ''</syntaxhighlight> Индексы могут быть отрицательными числами, обозначая при этом отсчет справа налево. Например: <syntaxhighlight lang="python">>>> word[-1] # Последний символ 'A' >>> word[-2] # Предпоследний символ 'p' >>> word[-2:] # Последние два символа 'pA' >>> word[:-2] # Всё, кроме последних двух символов 'Hel'</syntaxhighlight> Но обратите внимание, что <tt>-0</tt> действительно эквивалентен <tt>0</tt> — это не отсчет справа. <syntaxhighlight lang="python">>>> word[-0] # (поскольку -0 равен 0) 'H'</syntaxhighlight> Отрицательные индексы вне диапазона обрезаются, но не советуем делать это с одно-элементными индексами (''не-срезами''): <syntaxhighlight lang="python">>>> word[-100:] 'HelpA' >>> word[-10] # ошибка Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: string index out of range</syntaxhighlight> Один из способов запомнить, как работают срезы — думать о них, как об указателях на места между символами, где левый край первого символа установлен в ноль, а правый край последнего символа строки из <code>n</code> символов имеет индекс <code>n</code>, например: <pre> +---+---+---+---+---+ | H | e | l | p | A | +---+---+---+---+---+ 0 1 2 3 4 5 -5 -4 -3 -2 -1</pre> Первый ряд чисел дает позицию индексов строки от 0 до 5; второй ряд описывает соответствующие отрицательные индексы. Срез от i до j состоит из всех символов между правым и левым краями, отмеченными, соответственно, через <code>i</code> и <code>j</code>. Для всех индексов, больших или равных нулю, длина среза — разность между индексами, при условии что оба индекса находятся в диапазоне. Например, длина <code>word[1:3]</code> — 2. Встроенная функция <code>len()</code> возвращает длину строки<ref>''(Прим. перев.)'': [[w:en:Supercalifragilisticexpialidocious|Supercalifragilisticexpialidocious]] — английское слово из одноименной песни, прозвучавшей в фильме [[w:en:Mary Poppins (film)|Мэри Поппинс]]</ref>: <syntaxhighlight lang="python">>>> s = 'supercalifragilisticexpialidocious' >>> len(s) 34</syntaxhighlight> {{Смотрите также| ;[[Справочник по библиотеке Python 3.1#Перечисляемые типы|Перечисляемые типы]]: Строки — вид перечисляемых типов и они поддерживают привычные для этих типов операции. ;[[Справочник по библиотеке Python 3.1#Строковые методы|Строковые методы]]: Строки поддерживают большое количество методов для поиска и простых трансформаций. ;[[Справочник по библиотеке Python 3.1#Форматирование строк|Форматирование строк]]: Здесь описано форматирование строк с применением функции <code>str.format()</code> ;[[Справочник по библиотеке Python 3.1#Форматирование строк в старом стиле|Операции форматирования строк в старом стиле]]:Операции форматирования, вызывающиеся тогда, когда обычные строки или строки в Unicode оказываются левым операндом относительно операции <code>%</code>, более детально рассмотрены здесь.<ref>''(Прим. перев.) Эти операции будут отключены в финальном релизе 3.1''</ref> }} ==== О Unicode ==== Начиная с Python версии 3.0, строковый тип поддерживает только Unicode (см. http://www.unicode.org/). Преимущество набора Unicode состоит в том, что он предоставляет порядковый номер для любого символа из любой письменности, использовавшейся в современных или древнейших текстах. До этих пор для символов в сценарии было доступно лишь 256 номеров. Тексты обычно привязывались к кодовой странице, которая устанавливала в соответствие порядковые номера и символы сценария. Это приводило к серьезной путанице, особенно в том, что касалось интернационализации<ref>Часто записывается как <tt>'''i18n'''</tt> — <tt>''internationalization'' = '''i''' + '''18''' символов + '''n'''</tt></ref> программного продукта. Unicode решает эти проблемы, определяя единую кодовую страницу для всех письменностей. Для вставки в строку специального символа можно использовать Unicode-экранирование (<tt>Python Unicode-Escape encoding</tt>). Следующий пример всё пояснит: <syntaxhighlight lang="python">>>> 'Hello\u0020World !' 'Hello World !'</syntaxhighlight> Экранированная последовательность <code>\u0020</code> задаёт символ Unicode с порядковым номером <tt>0x0020</tt> (символ пробела). Другие символы интерпретируются с использованием соответствующих им порядковых значений тем же способом, что и порядковые номера Unicode. Первые 128 символов кодировки Unicode полностью совпадают с 128 символами кодировки <tt>Latin-1</tt>, использующейся во многих западных странах. Помимо стандартных способов кодирования, Python предоставляет целый набор различных способов создания Unicode-строк, основываясь на известной кодировке. Для конвертирования Unicode-строки в последовательность байтов с использованием желаемой кодировки, строковые объекты предоставляют метод <code>encode()</code>, принимающий единственный параметр — название кодировки. Предпочитаются названия кодировок, записанные в нижнем регистре. <syntaxhighlight lang="python">>>>"Äpfel".encode('utf-8') b'\xc3\x84pfel'</syntaxhighlight> ==== Списки ==== В языке Python доступно некоторое количество ''составных'' типов данных, использующихся для группировки прочих значений вместе. Наиболее гибкий из них — список (<tt>list</tt>). Его можно выразить в тексте программы через разделённые запятыми значения (''элементы''), заключённые в квадратные скобки. Элементы списка могут быть разных типов. <syntaxhighlight lang="python">>>> a = ['spam', 'eggs', 100, 1234] >>> a ['spam', 'eggs', 100, 1234]</syntaxhighlight> Подобно индексам в строках, индексы списков начинаются с нуля, списки могут быть срезаны, объединены (''конкатенированы'') и так далее: <syntaxhighlight lang="python">>>> a[0] 'spam' >>> a[3] 1234 >>> a[-2] 100 >>> a[1:-1] ['eggs', 100] >>> a[:2] + ['bacon', 2*2] ['spam', 'eggs', 'bacon', 4] >>> 3*a[:3] + ['Boo!'] ['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boo!']</syntaxhighlight> В отличие от строк, являющихся неизменяемыми, изменить индивидуальные элементы списка вполне возможно: <syntaxhighlight lang="python">>>> a ['spam', 'eggs', 100, 1234] >>> a[2] = a[2] + 23 >>> a ['spam', 'eggs', 123, 1234]</syntaxhighlight> Присваивание срезу также возможно, и это действие может даже изменить размер списка или полностью его очистить: <syntaxhighlight lang="python">>>> # Заменим некоторые элементы: ... a[0:2] = [1, 12] >>> a [1, 12, 123, 1234] >>> # Удалим немного: ... a[0:2] = [] >>> a [123, 1234] >>> # Вставим пару: ... a[1:1] = ['bletch', 'xyzzy'] >>> a [123, 'bletch', 'xyzzy', 1234] >>> # Вставим (копию) самого себя в начало >>> a[:0] = a >>> a [123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234] >>> # Очистка списка: замена всех значений пустым списком >>> a[:] = [] >>> a []</syntaxhighlight> Встроенная функция <code>len()</code> также применима к спискам: <syntaxhighlight lang="python">>>> a = ['a', 'b', 'c', 'd'] >>> len(a) 4</syntaxhighlight> Вы можете встраивать списки (создавать списки, содержащие другие списки), например так: <syntaxhighlight lang="python">>>> q = [2, 3] >>> p = [1, q, 4] >>> len(p) 3 >>> p[1] [2, 3] >>> p[1][0] 2</syntaxhighlight> Вы можете добавить что-нибудь в конец списка. <syntaxhighlight lang="python">>>> p[1].append('xtra') >>> p [1, [2, 3, 'xtra'], 4]</syntaxhighlight> Обратите внимание, что в последнем примере <code>p[1]</code> и <code>q</code> на самом деле ссылаются на один и тот же объект! <syntaxhighlight lang="python">>>> q [2, 3, 'xtra']</syntaxhighlight> Мы вернёмся к ''семантике объектов'' позже. === Первые шаги к программированию === Безусловно, Python можно использовать для более сложных задач, чем сложение двух чисел. Например, мы можем вывести начало последовательности чисел Фибоначчи таким образом: <syntaxhighlight lang="python">>>> # Ряд Фибоначчи: ... # сумма двух элементов определяет следующий элемент ... a, b = 0, 1 >>> while b < 10: ... print(b) ... a, b = b, a+b ... 1 1 2 3 5 8</syntaxhighlight> Этот пример показывает нам некоторые новые возможности. * Первая строка содержит ''множественное присваивание'' (<tt>multiple assignment</tt>): переменные <code>a</code> и <code>b</code> параллельно получают новые значения — <code>0</code> и <code>1</code>. В последней строке этот метод используется снова, демонстрируя тот факт, что выражения по правую сторону [от оператора присваивания] всегда вычисляются раньше каких бы то ни было присваиваний. Сами же разделённые запятыми выражения вычисляются слева направо. * Цикл <code>while</code> (пока) исполняется до тех пор, пока условие (здесь: <code>b < 10</code>) остается истиной. В Python, также как и в C, любое ненулевое значение является истиной (<code>True</code>); ноль является ложью (<code>False</code>). Условием может быть строка, список или вообще любая последовательность; все, что имеет ненулевую длину, играет роль истины, пустые последовательности — лжи. Использованная в примере проверка — простое условие. Стандартные операции сравнения записываются так же, как и в C: <code><</code> (меньше чем), <code>></code> (больше чем), <code>==</code> (равно), <code><=</code> (меньше или равно), <code>>=</code> (больше или равно) и <code>!=</code> (не равно). * ''Тело'' цикла выделено ''отступом'' (<tt>indented</tt>). Отступы — это средство группировки операторов в Python. Интерактивный режим Python (пока!) не имеет какого-либо разумного и удобного средства для редактирования строк ввода, поэтому необходимо использовать табуляции или пробелы для отступа в каждой строке. На практике более сложный текст на Python готовится в текстовом редакторе, большинство из которых имеют функцию авто-отступа. По окончании ввода составного выражения в интерактивном режиме его необходимо закончить пустой строкой — признаком завершения (поскольку интерпретатор не может угадать, когда вами была введена последняя строка). Обратите внимание, что размер отступа в каждой строке основного блока должен быть одним и тем же<ref>''(Прим. перев.)'' Размер отступа для блока не унифицирован — табуляция может чередоваться с пробелами, это может быть один пробел или же пять — главное, чтобы у всего блока он был одинаковым и был больше по величине чем у внешнего (обрамляющего) блока. Тем не менее, чаще всего программисты на Python устанавливают в редакторах режим замены табуляции четырьмя пробелами и при наборе кода вложенность блока обозначают отступом с соответствующим количеством нажатий клавиш табуляции. Благодаря этому код остается читабельным во всех текстовых редакторах и в большинстве браузеров (или, в редких случаях, требует минимального форматирования для корректного отображения)).''</ref>. * Функция <code>print()</code> выводит значения переданных ей выражений. Поведение этой функции отличается от обычного вывода выражения (как происходило выше в примерах с калькулятором) тем, каким способом обрабатываются ряды выражений, величины с плавающей точкой и строки. Строки выводятся без кавычек, и между элементами вставляются пробелы, благодаря чему форматирование вывода улучшается — как, например, здесь: <syntaxhighlight lang="python">>>> i = 256*256 >>> print('Значением i является', i) Значением i является 65536</syntaxhighlight> : Для отключения перевода строки после вывода или завершения вывода другой строкой используется именованный параметр <code>end</code>: <syntaxhighlight lang="python">>>> a, b = 0, 1 >>> while b < 1000: ... print(b, end=' ') ... a, b = b, a+b ... 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987</syntaxhighlight> == Больше средств для управления потоком команд<ref>''(Прим. перев.)'' More Control Flow Tools; [[w:en:Control Flow|Control Flow]] — поток команд, процесс управления, алгоритм; подразделы в оригинале используют множественное число: "Операторы (выражения, инструкции) <code>if</code>, «Операторы (выражения, инструкции) <code>for</code>», и. т. п.</ref> == Помимо описанного выше оператора <code>while</code>, в Python доступны привычные операторы управления потоком из других языков, но с некоторыми особенностями. === Оператор <code>if</code> === Возможно, наиболее широко известный тип оператора — оператор <code>if</code> (если). Пример: <syntaxhighlight lang="python">>>> x = int(input("Введите, пожалуйста, целое число: ")) Введите, пожалуйста, целое число: 42 >>> if x < 0: ... x = 0 ... print('Отрицательное значение, изменено на ноль') ... elif x == 0: ... print('Ноль') ... elif x == 1: ... print('Один') ... else: ... print('Больше') ...</syntaxhighlight> Блока <code>elif</code> может не быть вообще, он может быть один или их может быть несколько, а блок <code>else</code> (иначе) необязателен. Ключевое слово <tt>elif</tt> — краткая запись <tt>else if</tt> (иначе если) — позволяет избавиться от чрезмерного количества отступов. Оператор <code>if</code> <tt>...</tt> <code>elif</code> <tt>...</tt> <code>elif</code> <tt>...</tt> — аналог оператора выбора <code>switch</code> или <code>case</code>, которые можно встретить в других языках программирования. === Оператор <code>for</code> === Оператор <code>for</code> в Python немного отличается от того, какой вы, возможно, использовали в C или Pascal. Вместо неизменного прохождения по арифметической прогрессии из чисел (как в Pascal) или предоставления пользователю возможности указать шаг итерации и условие остановки (как в С), оператор <code>for</code> в Python проходит по всем элементам любой последовательности (списка или строки) в том порядке, в котором они в ней располагаются. Например (игра слов не подразумевалась):<ref>''(Прим. перев.)'' Defenestrate{{ref-en}} — выкидывать кого-либо из окна с целью покалечить. Другие слова — «кошка» и «окно».</ref> <syntaxhighlight lang="python">>>> # Измерим несколько строк: ... a = ['cat', 'window', 'defenestrate'] >>> for x in a: ... print(x, len(x)) ... cat 3 window 6 defenestrate 12</syntaxhighlight> Изменять содержимое последовательности, по которой проходит цикл, небезопасно (это в принципе-то возможно только для изменяемых типов, таких как списки). Если необходимо модифицировать список, использующийся для организации цикла, (например, для того чтобы продублировать отдельные элементы) нужно передать циклу его копию. Нотация срезов делает это практически безболезненным: <syntaxhighlight lang="python">>>> for x in a[:]: # создать срез-копию всего списка ... if len(x) > 6: a.insert(0, x) ... >>> a ['defenestrate', 'cat', 'window', 'defenestrate']</syntaxhighlight> === Функция <code>range()</code> === Если вам нужно перебрать последовательность чисел, встроенная функция <code>range()</code> придёт на помощь. Она генерирует арифметические прогрессии: <syntaxhighlight lang="python">>>> for i in range(5): ... print(i) ... 0 1 2 3 4</syntaxhighlight> Указанный конец интервала никогда не включается в сгенерированный список; вызов <code>range(10)</code> генерирует десять значений, которые являются подходящими индексами для элементов последовательности длины 10. Можно указать другое начало интервала и другую, даже отрицательную, величину шага. <syntaxhighlight lang="python">range(5, 10) от 5 до 9 range(0, 10, 3) 0, 3, 6, 9 range(-10, -100, -30) -10, -40, -70</syntaxhighlight> Чтобы пройти по всем индексам какой-либо последовательности, скомбинируйте вызовы <code>range()</code> и <code>len()</code> следующим образом: <syntaxhighlight lang="python">>>> a = ['Mary', 'had', 'a', 'little', 'lamb'] >>> for i in range(len(a)): ... print(i, a[i]) ... 0 Mary 1 had 2 a 3 little 4 lamb</syntaxhighlight> В большинстве таких случаев удобно использовать функцию <code>enumerate()</code>, обратитесь к [[Учебник Python 3.1#Организация циклов|Организация циклов]]. Странные вещи начинают происходить при попытке вывода последовательности: <syntaxhighlight lang="python">>>> print(range(10)) range(0, 10)</syntaxhighlight> Во многих случаях объект, возвращаемый функцией <code>range()</code>, ведёт себя как список, но фактически им не является. Этот объект возвращает по очереди элементы желаемой последовательности, когда вы проходите по нему в цикле, но на самом деле не создаёт списка, сохраняя таким образом пространство в памяти. Мы называем такие объекты ''итерируемыми'' (<tt>iterable</tt>), и это все объекты, которые предназначаются для функций и конструкций, ожидающих от них поочерёдного предоставления элементов до тех пор, пока источник не иссякнет. Мы видели, что оператор <code>for</code> является таким ''итератором'' <tt>iterator</tt>. Функция <code>list()</code> тоже из их числа — она создаёт списки из ''итерируемых'' объектов: <syntaxhighlight lang="python">>>> list(range(5)) [0, 1, 2, 3, 4]</syntaxhighlight> Позже мы познакомимся и с другими функциями, которые возвращают и принимают ''итерируемые'' объекты в качестве параметров. === Операторы <code>break</code> и <code>continue</code>, а также условие <code>else</code> в циклах === Оператор <code>break</code> прерывает выполнение самого ближайшего вложенного цикла <code>for</code> или <code>while</code> (по аналогии с языком C). Оператор <code>continue</code>, также заимствованный из C, продолжает выполнение цикла со следующей итерации. Операторы циклов могут иметь ветвь <code>else</code>. Она исполняется, когда цикл выполнил перебор до конца (в случае <code>for</code>) или когда условие становится ложным (в случае <code>while</code>), но не в тех случаях, когда цикл прерывается по <code>break</code>. Это поведение иллюстрируется следующим примером, в котором производится поиск простых чисел: <syntaxhighlight lang="python">>>> for n in range(2, 10): ... for x in range(2, int(n ** 0.5) + 1): ... if n % x == 0: ... print(n, 'равно', x, '*', n//x) ... break ... else: ... print(n, '- простое число') ... 2 - простое число 3 - простое число 4 равно 2 * 2 5 - простое число 6 равно 2 * 3 7 - простое число 8 равно 2 * 4 9 равно 3 * 3</syntaxhighlight> === Оператор <code>pass</code> === Оператор <code>pass</code> не делает ничего. Он может использоваться когда синтаксически требуется присутствие оператора, но от программы не требуется действий. Например: <syntaxhighlight lang="python">>>> while True: ... pass # Ожидание прерывания c клавиатуры (Ctrl+C) в режиме занятости ...</syntaxhighlight> Этот оператор часто используется для создания минималистичных классов, к примеру ''исключений'' (<tt>exceptions</tt>), или для игнорирования нежелательных исключений: <syntaxhighlight lang="python">>>> class ParserError(Exception): ... pass ... >>> try: ... import audioop ... except ImportError: ... pass ...</syntaxhighlight> Другой вариант: <code>pass</code> может применяться в качестве заглушки для тела функции или условия при создании нового кода, позволяя вам сохранить абстрактный взгляд на вещи. С другой стороны, оператор <code>pass</code> игнорируется без каких-либо сигналов и лучшим выбором было бы породить исключение <code>NotImplementedError</code>: <syntaxhighlight lang="python">>>> def initlog(*args): ... raise NotImplementedError # Открыть файл для логгинга, если он ещё не открыт ... if not logfp: ... raise NotImplementedError # Настроить заглушку для логгинга ... raise NotImplementedError('Обработчик инициализации лога вызовов') ...</syntaxhighlight> Если бы здесь использовались операторы <code>pass</code>, а позже вы бы запускали тесты, они могли бы упасть без указания причины. Использование <code>NotImplementedError</code> принуждает этот код породить исключение, сообщая вам конкретное место, где присутствует незавершённый код. Обратите внимание на два способа порождения исключений. Первый способ, без сообщения, но сопровождаемый комментарием, позволяет вам оставить комментарий когда вы будете подменять выброс исключения рабочим кодом, который, в свою очередь, в идеале, будет хорошим описанием блока кода, для которого исключение предназначалось заглушкой. Однако, передача сообщения вместе с исключением, как в третьем примере, обуславливает более насыщенный информацией вывод при отслеживании ошибки. === Определение функций === Мы можем создать функцию, которая выводит числа Фибоначчи до некоторого предела: <syntaxhighlight lang="python">>>> def fib(n): # вывести числа Фибоначчи меньшие (вплоть до) n ... """Выводит ряд Фибоначчи, ограниченный n.""" ... a, b = 0, 1 ... while b < n: ... print(b, end=' ') ... a, b = b, a+b ... >>> # Теперь вызовем определенную нами функцию: ... fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597</syntaxhighlight> Зарезервированное слово <code>def</code> предваряет ''определение'' функции. За ним должны следовать имя функции и заключённый в скобки список формальных параметров. Выражения, формирующие тело функции, начинаются со следующей строки и должны иметь отступ. Первым выражением в теле функции может быть строковой литерал — этот литерал является строкой документации функции, или ''док-строкой'' (<tt>docstring</tt>). (Больше информации о ''док-строках'' вы найдёте в разделе [[Учебник Python 3.1#Строки документации|Строки документации]]) Существуют инструменты, которые используют ''док-строки'' для того, чтобы сгенерировать печатную или онлайн-документацию или чтобы позволить пользователю перемещаться по коду интерактивно; добавление строк документации в ваш код — это хорошая практика, постарайтесь к ней привыкнуть. ''Исполнение'' функции приводит к созданию новой таблицы символов<ref>''(Прим. перев.)'' Здесь слово «символ» используется не в привычном значении — под ''символом'' подразумевается нечто лингвистическое, описывающее какую-либо сущность (близко к значению ''символизировать''), в данном случае: имя переменной — саму переменную.</ref>, использующейся для хранения локальных переменных функции. Если быть более точными, все присваивания переменных в функции сохраняют значение в локальной таблице символов; при обнаружении ссылки на переменную, в первую очередь просматривается локальная таблица символов, затем локальная таблица символов для окружающих функций, затем глобальная таблица символов и, наконец, таблица встроенных имён. Таким образом, глобальным переменным невозможно прямо присвоить значения внутри функций (если они конечно не упомянуты в операторе <code>global</code>) несмотря на то, что ссылки на них могут использоваться. Фактические параметры при вызове функции помещаются в локальную таблицу символов вызванной функции; в результате аргументы передаются через ''вызов по значению'' (<tt>call by value</tt>) (где значение — это всегда ''ссылка'' (<tt>reference</tt>) на объект, а не значение его самого)<ref>На самом деле, лучшим определением был бы ''вызов по ссылке на объект'' (<tt>call by object reference</tt>), так как при передаче изменяемого объекта, вызывающему будут видны все изменения, которые производит над объектом вызываемый (вставка элементов в список)</ref>. Если одна функция вызывает другую — то для этого вызова создается новая локальная таблица символов. При определении функции её имя также помещается в текущую таблицу символов. Тип значения, связанного с именем функции, распознается интерпретатором как функция, определённая пользователем (<tt>user-defined function</tt>). Само значение может быть присвоено другому имени, которое затем может также использоваться в качестве функции. Эта система работает в виде основного механизма переименования: <syntaxhighlight lang="python">>>> fib <function fib at 10042ed0> >>> f = fib >>> f(100) 1 1 2 3 5 8 13 21 34 55 89</syntaxhighlight> Если вы использовали в работе другие языки программирования, вы можете возразить, что <code>fib</code> — это не функция, а процедура, поскольку не возвращает никакого значения. На самом деле, даже функции без ключевого слова <code>return</code> возвращают значение, хотя и более скучное. Такое значение именуется <code>None</code> (это встроенное имя). Вывод значения <code>None</code> обычно подавляется в интерактивном режиме интерпретатора, если оно оказывается единственным значением, которое нужно вывести. Вы можете проследить за этим процессом, если действительно хотите, используя функцию <code>print()</code>: <syntaxhighlight lang="python">>>> fib(0) >>> print(fib(0)) None</syntaxhighlight> Довольно легко написать функцию, которая возвращает список чисел из ряда Фибоначчи, вместо того, чтобы выводить их: <syntaxhighlight lang="python">>>> def fib2(n): # вернуть числа Фибоначчи меньшие (вплоть до) n ... """Возвращает список чисел ряда Фибоначчи, ограниченный n.""" ... result = [] ... a, b = 0, 1 ... while b < n: ... result.append(b) # см. ниже ... a, b = b, a+b ... return result ... >>> f100 = fib2(100) # вызываем >>> f100 # выводим результат [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]</syntaxhighlight> И на этот раз пример демонстрирует некоторые новые возможности Python: * Оператор <code>return</code> завершает выполнение функции, возвращая некоторое значение. Оператор <code>return</code> без аргумента возвращает <code>None</code>. Достижение конца функции также возвращает <code>None</code>. * Выражение <code>result.append(b)</code> вызывает метод <code>append</code> объекта-списка <code>result</code>. Метод — это функция, которая «принадлежит» объекту и указывается через выражение вида <code>obj.methodname</code>, где <code>obj</code> — некоторый объект (может быть выражением), а <code>methodname</code> — имя метода, присущий объекту данного типа. Различные типы определяют различные методы. Методы разных типов могут иметь одинаковые имена, не вызывая неопределённостей. (Позже в этом учебнике будет рассмотрено как определять собственные типы объектов и методы, используя классы.) Метод <code>append()</code>, показанный в примере, определён для объектов типа список. Он добавляет в конец списка новый элемент. В данном примере это действие эквивалентно выражению <code>result = result + [b]</code>, но более эффективно. === Подробнее об определении функций === Также есть возможность определять функции с переменным количеством параметров. Для этого существует три формы, которые также можно использовать совместно. ==== Значения аргументов по умолчанию ==== Наиболее полезной формой является задание значений по умолчанию для одного или более параметров. Таким образом создаётся функция, которая может быть вызвана с меньшим количеством параметров, чем в её определении: при этом неуказанные при вызове параметры примут данные в определении функции значения. Например<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' спросить_подтверждения(вопрос, попытки=4, протест='Да или нет, пожалуйста!'):<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''пока''' ''Истина'':<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ответ = ''ввод''(вопрос)<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''если''' ответ '''среди''' ('д', 'да', 'ага'): '''вернуть''' ''Истина''<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''если''' ответ '''среди''' ('н', 'не', 'нет', 'не-а'): '''вернуть''' ''Ложь''<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;попытки = попытки - 1<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''если''' попытки < 0: '''породить''' ОшибкаВВ('пользователь-отказник')<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''(протест)</code><br /><br /> (''Refusenik''{{ref-en}} — [[w:ru:Отказник|Отказник]]). Ниже: «…<code>спросить_подтверждения('Вы действительно хотите выйти?')</code> или так: <code>спросить_подтверждения('Согласны ли вы перезаписать файл?', 2)</code>…»</ref>: <syntaxhighlight lang="python">def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while True: ok = input(prompt) if ok in ('y', 'yeah', 'yes', 'yep'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise IOError('refusenik user') print(complaint)</syntaxhighlight> Эта функция может быть вызвана, например, так: <code>ask_ok('Do you really want to quit?')</code> или так: <code>ask_ok('OK to overwrite the file?', 2)</code>. Этот пример также знакомит вас с зарезервированным словом <code>in</code>. Посредством его можно проверить, содержит ли последовательность определённое значение или нет. Значения по умолчанию вычисляются в месте определения функции, в ''определяющей'' области, поэтому код <syntaxhighlight lang="python">i = 5 def f(arg=i): print(arg) i = 6 f()</syntaxhighlight> выведет 5. '''Важное предупреждение:''' Значение по умолчанию вычисляется лишь единожды. Это особенно важно помнить, когда значением по умолчанию является изменяемый объект, такой как список, словарь (<tt>dictionary</tt>) или экземпляры большинства классов. Например, следующая функция накапливает переданные ей параметры: <syntaxhighlight lang="python">def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3))</syntaxhighlight> Она выведет <syntaxhighlight lang="python">[1] [1, 2] [1, 2, 3]</syntaxhighlight> Если вы не хотите, чтобы значение по умолчанию распределялось между последовательными вызовами, вместо предыдущего варианта вы можете использовать такую идиому: <syntaxhighlight lang="python">def f(a, L=None): if L is None: L = [] L.append(a) return L</syntaxhighlight> ==== Именованные параметры<ref>''(Прим. перев.)'' В оригинале — Keyword Arguments — параметры по ключевым словам, ключевые параметры (далее используется слово ''keywords'' для набора имён параметров непостоянного количества. ''Ключевые'' — возможно, корректнее, но как мне показалось — менее понятно ([http://www.infocity.kiev.ua/prog/python/content/sempit_14.phtml альтернативный перевод]))</ref> ==== Функции также могут быть вызваны с использованием именованных параметров (<tt>keyword arguments</tt>) в форме «''имя = значение''». Например, нижеприведённая функция<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' попугай(вольтаж, состояние='труп', действие='ввум', тип='Норвежский Голубой'):<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Этот попугай не сделает ", действие, завершить=' ')<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("если вы пропустите через него ", вольтаж, " вольт.")<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Великолепное оперенье, ", тип)<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Он", состояние, "!")</code><br /><br /> (''Из [http://www.ibras.dk/montypython/episode08.htm#6 скетча Монти Пайтона]'')</ref>: <syntaxhighlight lang="python">def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It's", state, "!")</syntaxhighlight> могла бы быть вызвана любым из следующих способов<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">попугай(действие='ВВУУУУМ', вольтаж=1000000)<br/> попугай('тысячу', состояние='слёг в могилу')<br/> попугай('миллион', 'лишённый жизни', 'прыжок')</code><br /><br /></ref>: <syntaxhighlight lang="python">parrot(1000) parrot(action='VOOOOOM', voltage=1000000) parrot('a thousand', state='pushing up the daisies') parrot('a million', 'bereft of life', 'jump')</syntaxhighlight> а эти случаи оказались бы неверными<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">попугай()<br/> попугай(вольтаж=5.0, 'мёртв')<br/> попугай(исполнитель='Джон Клиз')</code><br /><br /></ref>: <syntaxhighlight lang="python">parrot() # пропущен требуемый аргумент parrot(voltage=5.0, 'dead') # позиционный параметр вслед за именованным parrot(110, voltage=220) # повторное значение параметра parrot(actor='John Cleese') # неизвестное имя параметра</syntaxhighlight> В общем случае, список параметров должен содержать любое количество позиционных (<tt>positional</tt>) параметров, за которыми может следовать любое количество именованных, и при этом имена аргументов выбираются из формальных параметров. Неважно, имеет формальный параметр значение по умолчанию или нет. Ни один из аргументов не может получать значение более чем один раз — имена формальных параметров, совпадающие с именами позиционных параметров, не могут использоваться в качестве именующих в одном и том же вызове<ref>''(Прим. перев.)'' В главе о функциях автор отталкивается не от привычного по другим учебникам первоначального полного описания определения функций, а уже потом — описания их вызова, а объединяет обе темы вместе (как минимум в случае с непостоянным списком аргументов это возможно непривычно, но оправдано), отдавая приоритет описанию вызова. Учебник рассчитан на тех, кто уже программирует на каком-либо языке программирования и потенциально не должен смутить читателя.</ref>. Вот пример, завершающийся неудачей по причине описанного ограничения: <syntaxhighlight lang="python">>>> def function(a): ... pass ... >>> function(0, a=0) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: function() got multiple values for keyword argument 'a'</syntaxhighlight> Если в определении функции присутствует завершающий параметр в виде ''**имя'', он получит в качестве значения словарь (подробнее в разделе [[Справочник по библиотеке Python 3.1#Типы-отображения|Справочника — Типы-отображения — словари]]), содержащий все именованные параметры и их значения, исключая те, которые соответствуют формальным параметрам. Можно совместить эту особенность с поддержкой формального параметра в формате ''*имя'' (описывается в следующем подразделе), который получает кортеж (<tt>tuple</tt>), содержащий все позиционные параметры, следующие за списком формальных параметров. (параметр в формате ''*имя'' должен описываться перед параметром в формате ''**имя''.) Например, если мы определим такую функцию<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' лавка_сыров(сорт, *аргументы, **именованные):<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Есть ли у вас ", сорт, '?')<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Простите, весь ", сорт, " у нас закончился.")<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''для''' аргумент '''из''' аргументы: '''вывести'''(аргумент)<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''('-' * 40)<br/> &nbsp;&nbsp;&nbsp;&nbsp;имена = '''сортированные'''(именованные.''ключи''())<br/> &nbsp;&nbsp;&nbsp;&nbsp;'''для''' имя '''из''' имена: '''вывести'''(имя , ":", именованные[имя])</code><br /><br /> (''Из [http://www.ibras.dk/montypython/episode33.htm#7 скетча Монти Пайтона]'')</ref>: <syntaxhighlight lang="python">def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any", kind, "?") print("-- I'm sorry, we're all out of", kind) for arg in arguments: print(arg) print("-" * 40) keys = sorted(keywords.keys()) for kw in keys: print(kw, ":", keywords[kw])</syntaxhighlight> то её можно будет вызвать так<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">лавка_сыров("Лимбургер", "Это очень расстраивает, сэр.",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Это действительно очень, ОЧЕНЬ расстраивает, сэр.",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;торговец="Майкл Палин",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;клиент="Джон Клиз",<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;скетч="Скетч о сырной лавке")</code></ref>: <syntaxhighlight lang="python">cheeseshop('Limburger', "It's very runny, sir.", "It's really very, VERY runny, sir.", client="John Cleese", shopkeeper="Michael Palin", sketch="Cheese Shop Sketch")</syntaxhighlight> и она, конечно же, выведет<ref>''(Прим. перев.):'' <br/><br/> <code style="background-color: inherit !important;">-- Есть ли у вас Лимбургер ?<br/> -- Простите, весь Лимбургер у нас закончился.<br/> Это очень расстраивает, сэр.<br/> Это действительно очень, ОЧЕНЬ расстраивает, сэр.<br/> <nowiki>----------------------------------------</nowiki><br/> клиент: Джон Клиз<br/> торговец : Майкл Палин<br/> скетч : Скетч о сырной лавке</code><br /><br /></ref>: <code>-- Do you have any Limburger ?<br/> -- I'm sorry, we're all out of Limburger<br/> It's very runny, sir.<br/> It's really very, VERY runny, sir.<br/> <nowiki>----------------------------------------</nowiki><br/> client : John Cleese<br/> shopkeeper : Michael Palin<br/> sketch : Cheese Shop Sketch</code> Обратите внимание, что список имён (ключей) именованных параметров (<code>keys</code>) создается посредством сортировки содержимого списка ключей <code>keys()</code> словаря <code>keywords</code>; если бы этого не было сделано, порядок вывода параметров был бы произволен. ==== Списки параметров произвольной длины ==== Наконец, наиболее редко используется возможность указания того, что функция может быть вызвана с произвольным числом аргументов. При этом сами параметры будут обёрнуты в кортеж (см. раздел [[Учебник Python 3.1#Кортежи|Кортежи]]). Переменное количество параметров могут предварять ноль или более обычных. <syntaxhighlight lang="python">def write_multiple_items(file, separator, *args): file.write(separator.join(args))</syntaxhighlight> Обычно параметры неизвестного заранее количества (<tt>variadic</tt>) указываются последними в списке формальных параметров, поскольку включают в себя все остальные переданные в функцию параметры. Все формальные параметры, которые следуют за параметром <code>*args</code>, должны быть только именованными, то есть, они могут быть заданы только по имени (в отличие от позиционных параметров). <syntaxhighlight lang="python">>>> def concat(*args, sep="/"): ... return sep.join(args) ... >>> concat("earth", "mars", "venus") 'earth/mars/venus' >>> concat("earth", "mars", "venus", sep=".") 'earth.mars.venus'</syntaxhighlight> ==== Распаковка списков параметров ==== Обратная ситуация возникает когда параметры уже содержатся в списке или в кортеже, но должны быть распакованы для вызова функции, требующей отдельных позиционных параметров. Например, встроенная функция <code>range()</code> ожидает отдельные параметры ''start'' и ''stop'' соответственно. Если они не доступны раздельно, для распаковки аргументов из списка или кортежа в вызове функции используйте *-синтаксис: <syntaxhighlight lang="python">>>> list(range(3, 6)) # обычный вызов с отдельными параметрами [3, 4, 5] >>> args = [3, 6] >>> list(range(*args)) # вызов с распакованными из списка параметрами [3, 4, 5]</syntaxhighlight> Схожим способом, словари могут получать именованные параметры через **-синтаксис<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">'''опред''' попугай(вольтаж, состояние='труп', действие='ввум', тип='Норвежский Голубой'):<br/> ...&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Этот попугай не сделает ", действие, конец=' ')<br/> ...&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("если вы пропустите через него ", вольтаж, " вольт.", конец=' ')<br/> ...&nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''("-- Это", состояние, "!")<br/> ...<br/> >>> d = {"вольтаж": "четыре миллиона", "состояние": "кровавая кончина", "действие": "ВВУМ"}<br/> >>> попугай(**d)<br/> -- Этот попугай не сделает ВВУМ если вы пропустите через него четыре миллиона вольт. Это кровавая смерть !</code><br /><br /> (''Из [http://www.ibras.dk/montypython/episode08.htm#6 скетча Монти Пайтона]'')</ref>: <syntaxhighlight lang="python">>>> def parrot(voltage, state='a stiff', action='voom'): ... print("-- This parrot wouldn't", action, end=' ') ... print("if you put", voltage, "volts through it.", end=' ') ... print("It's", state, "!") ... >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"} >>> parrot(**d) -- This parrot wouldn't VOOM if you put four million volts through it. It's bleedin' demised !</syntaxhighlight> ==== Модель <tt>lambda</tt> ==== В связи с неустанными просьбами, в Python были добавлены несколько возможностей, которые были привычны для функциональных языков программирования, таких как Lisp. Используя зарезервированное слово <code>lambda</code>, вы можете создать небольшую безымянную функцию. Например, функцию, которая возвращает сумму двух своих аргументов, можно записать так: <code>lambda a, b: a+b</code>. Формы <code>lambda</code> могут быть использованы в любом месте где требуется объект функции. При этом они синтаксически ограничены одним выражением. Семантически, они лишь «синтаксический сахар» для обычного определения функции. Как и определения вложенных функций, <code>lambda</code>-формы могут ссылаться на переменные из содержащей их области видимости: <syntaxhighlight lang="python">>>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43</syntaxhighlight> ==== Строки документации ==== Перечислим некоторые существующие соглашения по содержимому строк документации и их форматированию. По поводу форматирования строк документации и их содержимого постоянно появляются всё новые соглашения. Первая строка всегда должна быть сжатой, лаконичной сводкой о назначении объекта. Для краткости, в ней не обязательно присутствие имени типа или объекта, поскольку они доступны другими способами (исключая случай, когда имя функции оказывается глаголом, описывающим суть операции). Эта строка должна начинаться с прописной буквы и оканчиваться точкой. Если строке документации (литералу, объекту строки) требуется больше строк (физических), вторая строка должна быть пустой, визуально отделяя сводку от остального описания. Следующие строки могут быть одним или более абзацем, описывающим соглашения по вызову объекта, сторонние эффекты, и т. д. Парсер Python не обрабатывает отступы в много-строковых литералах, поэтому инструментам, которые работают над документацией, предлагается, по желанию, делать это самим. Производится это по следующему соглашению. Первая непустая строка после первой строки литерала определяет величину отступа всего литерала документации. (Мы не можем использовать первую строку, поскольку она обычно выравнивается по открывающим кавычкам и её отступ в литерале не явен). Пробельный «эквивалент» этого отступа затем отрезается от начала всех строк литерала. Строк с меньшим отступом не должно обнаруживаться, но если они встретились, весь их начальный отступ должен быть обрезан. Эквивалентность пробельных замен может быть протестирована развертыванием табуляции (обычно, к 8 пробелам). Вот пример многострочной документации (''док-строки''): <syntaxhighlight lang="python">>>> def my_function(): ... """Не делаем ничего, но документируем. ... ... Нет, правда, эта функция ничего не делает. ... """ ... pass ... >>> print(my_function.__doc__) Не делаем ничего, но документируем. Нет, правда, эта функция ничего не делает.</syntaxhighlight> === Интермеццо: Стиль написания кода === Теперь, когда вам предстоит писать более объёмные и сложные блоки кода на Python, настало время поговорить о ''стиле написания кода'' (<tt>coding style</tt>). Код на большинстве языков программирования может быть записан (или, точнее говоря, ''отформатирован'' (<tt>formatted</tt>)) различными способами; некоторые из них более читабельны, некоторые — нет. Стремление к написанию лёгкого для прочтения другими кода всегда считалось хорошим тоном, и выбор правильного стиля для кода крайне ему способствует. В случае языка Python, в качестве руководства по стилю было создано предложение [http://www.python.org/dev/peps/pep-0008 PEP8]<ref>''(Прим. перев.)'' — <tt>[[w:Python_Enhancement_Proposal|PEP]]</tt> (</tt>''Python Enchancement Proprosal</tt>'', Предложение по улучшению Python) — документ, имеющий стандартизированный формат и описывающий какую-либо из возможностей или какое-либо из свойств языка Python, планируемые для разработки в будущем (или уже разработанную). В завершённом варианте используется как основное соглашение по данной функциональности. (см. также [[w:Python#Дальнейшая разработка|пояснение на странице языка Python]])</ref>, которого придерживаются создатели большинства проектов. В нём учреждается чрезвычайно читабельный и приятный для глаза стиль написания кода. В некоторый момент с ним должен ознакомиться каждый разработчик на Python. Приведём здесь избранные, наиболее важные, пункты: * Используйте отступ в 4 пробела, не используйте табуляцию : 4 пробела легко опознаются и в случае небольших отступов (хватает места для глубоких вложений) и в случае больших отступов (приятнее читается). Табуляция вносит путаницу и лучше от неё воздержаться. * Разделяйте строки так, чтобы их длина не превышала 79-и символов : Это поможет пользователям с небольшими экранами, а пользователям с большими экранами позволит уложить несколько файлов с исходным кодом рядом. * Используйте пустые строки для отделения функций, классов, и крупных блоков внутри функций. * При возможности располагайте комментарий на отдельной строке. * Используйте строки документации (''док-строки'') * Применяйте пробелы вокруг символов операций и после запятых, но не добавляйте их в конструкции со скобками: <code>a = f(1, 2) + g(3, 4)</code> * Называйте ваши классы и функции единообразно; соглашение следующее: используйте <code>CamelCase</code><ref>''(Прим. перев.)'' <tt>CamelCase</tt> (''ВерблюжийСтиль'') — стиль именования идентификаторов, при котором все слова, записанные строчными буквами, объединяются в одно и первая буква каждого слова выделяется заглавной буквой — такая запись напоминает верблюжьи горбы, в связи с чем и названа.</ref> для именования классов и <code>нижний_регистр_с_подчёркиваниями</code></tt><ref>''(Прим. перев.)'' Пусть данный пример по вине переводчика и использует русские буквы, соглашение корректно настаивает на использовании латиницы для именования идентификаторов, см. следующий пункт соглашения</ref> для функций и методов. (обращайтесь к разделу [[Учебник Python 3.1#Первый взгляд на классы|Первый взгляд на классы]] за дополнительной информацией о классах и методах) * Не используйте в вашем коде изощрённых кодировок<ref>''(Прим. перев.)'' В строковых литералах (не комментариях) это, конечно же, позволено</ref>, если он рассчитан на использование в интернациональной среде. Стандартный набор ASCII всегда работает на ура<ref>''(Прим. перев.)'' Не кодировка, а именно набор символов — латиница, пунктуация и несколько служебных символов. Кодировка по умолчанию для файлов с иходными кодами, начиная с Python 3.0, всегда UTF-8 — дабы существовала возможность использовать национальные символы в строковых литералах и, в редких случаях — комментариях.</ref>. == Структуры данных == Эта глава описывает подробнее некоторые вещи, которые вы уже изучили, а также раскрывает некоторые новые темы. === Подробнее о списках === У типа данных список также имеются не описанные ранее методы. Ниже приведены все методы объекта типа список: ;<code>list.append(''x'')</code>:Добавить элемент к концу списка; эквивалент <code>list[len(list):] = [x]</code> ;<code>list.extend(''L'')</code>:Расширить список за счёт добавления всех элементов переданного списка; эквивалентно <code>list[len(list):] = L</code>. ;<code>list.insert(''i'', ''x'')</code>:Вставить элемент в указанную позицию. Первый аргумент — это индекс того элемента, перед которым требуется выполнить операцию вставки, поэтому вызов <code>list.insert(0, x)</code> вставляет элемент в начало списка, а <code>list.insert(len(list), x)</code> эквивалентно <code>list.append(x)</code>. ;<code>list.remove(''x'')</code>:Удалить первый найденный элемент из списка, значение которого — <code>x</code>. Если элемент не найден, генерируется ошибка. ;<code>list.pop([''i''])</code>:Удалить элемент, находящийся на указанной позиции в списке, и вернуть его. Если индекс не указан, <code>list.pop()</code> удаляет и возвращает последний элемент списка. (Квадратные скобки вокруг <code>i</code> в сигнатуре метода означают, что параметр необязателен, а не необходимость набора квадратных скобок в этой позиции. Вы часто будете встречать такую нотацию в [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке]].) ;<code>list.index(''x'')</code>:Вернуть индекс первого найденного в списке элемента, значение которого равно <code>x</code>. Если элемент не найден, генерируется ошибка. ;<code>list.count(''x'')</code>:Вернуть значение сколько раз, <code>x</code> встречается в списке. ;<code>list.sort()</code>:Сортировать элементы списка, на месте. ;<code>list.reverse()</code>:Обратить порядок элементов списка, на месте. Пример, использующий большинство методов списка: <syntaxhighlight lang="python">>>> a = [66.25, 333, 333, 1, 1234.5] >>> print(a.count(333), a.count(66.25), a.count('x')) 2 1 0 >>> a.insert(2, -1) >>> a.append(333) >>> a [66.25, 333, -1, 333, 1, 1234.5, 333] >>> a.index(333) 1 >>> a.remove(333) >>> a [66.25, -1, 333, 1, 1234.5, 333] >>> a.reverse() >>> a [333, 1234.5, 1, 333, -1, 66.25] >>> a.sort() >>> a [-1, 1, 66.25, 333, 333, 1234.5]</syntaxhighlight> ==== Использование списка в качестве стека ==== Методы списков позволяют легко использовать список в качестве стека, где последний добавленный элемент становится первым полученным («первый вошёл — последний вышел»). Чтобы положить элемент на вершину стека, используйте метод <code>append()</code>. Для получения элемента с вершины стека — метод <code>pop()</code> без указания явного индекса. Например: <syntaxhighlight lang="python">>>> stack = [3, 4, 5] >>> stack.append(6) >>> stack.append(7) >>> stack [3, 4, 5, 6, 7] >>> stack.pop() 7 >>> stack [3, 4, 5, 6] >>> stack.pop() 6 >>> stack.pop() 5 >>> stack [3, 4]</syntaxhighlight> ==== Использование списка в качестве очереди ==== Вы можете без труда использовать список также и в качестве очереди, где первый добавленный элемент оказывается первым полученным («первый вошёл — первый вышел»). Чтобы добавить элемент в конец очереди, используйте метод <code>append()</code>, а чтобы получить элемент из начала очереди — метод <code>pop()</code> с нулём в качестве индекса. Например: <syntaxhighlight lang="python">>>> queue = ["Eric", "John", "Michael"] >>> queue.append("Terry") # Прибыл Terry >>> queue.append("Graham") # Прибыл Graham >>> queue.pop(0) 'Eric' >>> queue.pop(0) 'John' >>> queue ['Michael', 'Terry', 'Graham']</syntaxhighlight> ==== Генераторы списков<ref>''(Прим. перев.)'' ''Lists Comprehensions'', comprehension — включение, вложение, добавление (понимание, охват, интенция).</ref> ==== Использование метода списковой сборки — легкий способ создать список на основе последовательности. В большинстве случаев он применяется для создания списков, в которых каждый элемент является результатом некой операции, произведённой над каждым членом последовательности, или для создания выборок из тех элементов, которые удовлетворяют определённому условию. Любая списковая сборка состоит из выражения, за которым следует оператор <code>for</code>, а затем ноль или более операторов <code>for</code> или <code>if</code>. Результатом станет список, получившийся через вычисление выражения в контексте следующих за ним операторов <code>for</code> и/или <code>if</code>. Если в результате вычисления выражения строится кортеж, его нужно явно обернуть в скобки. В следующем примере на основе списка чисел создаётся список, где каждое число утроено: <syntaxhighlight lang="python">>>> vec = [2, 4, 6] >>> [3*x for x in vec] [6, 12, 18]</syntaxhighlight> Применим фантазию: <syntaxhighlight lang="python">>>> [[x, x**2] for x in vec] [[2, 4], [4, 16], [6, 36]]</syntaxhighlight> Здесь мы вызываем метод по очереди с каждым элементом последовательности: <syntaxhighlight lang="python">>>> freshfruit = [' banana', ' loganberry ', 'passion fruit '] >>> [weapon.strip() for weapon in freshfruit] ['banana', 'loganberry', 'passion fruit']</syntaxhighlight> Используя оператор <code>if</code>, мы можем отфильтровать поток: <syntaxhighlight lang="python">>>> [3*x for x in vec if x > 3] [12, 18] >>> [3*x for x in vec if x < 2] []</syntaxhighlight> Кортежи могут быть созданы без использования скобок, но не в этом случае: <syntaxhighlight lang="python">>>> [x, x**2 for x in vec] # ошибка - для кортежей необходимы скобки File "<stdin>", line 1, in ? [x, x**2 for x in vec] ^ SyntaxError: invalid syntax >>> [(x, x**2) for x in vec] [(2, 4), (4, 16), (6, 36)]</syntaxhighlight> Вот несколько вложенных циклов <code>for</code> и ещё кое-какое забавное поведение: <syntaxhighlight lang="python">>>> vec1 = [2, 4, 6] >>> vec2 = [4, 3, -9] >>> [x*y for x in vec1 for y in vec2] [8, 6, -18, 16, 12, -36, 24, 18, -54] >>> [x+y for x in vec1 for y in vec2] [6, 5, -7, 8, 7, -5, 10, 9, -3] >>> [vec1[i]*vec2[i] for i in range(len(vec1))] [8, 12, -54]</syntaxhighlight> Списковые сборки могут применяться в сложных выражениях и вложенных функциях<ref>''(Прим. перев.)'' в Python, как и в большинстве других языков программирования, используется европейский стандарт разделения целой и дробной части десятичных дробей точкой.</ref>: <syntaxhighlight lang="python">>>> [str(round(355/113, i)) for i in range(1, 6)] ['3.1', '3.14', '3.142', '3.1416', '3.14159']</syntaxhighlight> ==== Вложенные списковые сборки ==== Если вы в состоянии это переварить: списковые сборки могут быть вложенными. Но как любой мощный инструмент, их следует использовать с осторожностью. Представьте нижеследующий пример матрицы 3x3 в виде списка, содержащего три других списка, по одному в ряд: <syntaxhighlight lang="python">>>> mat = [ ... [1, 2, 3], ... [4, 5, 6], ... [7, 8, 9], ... ]</syntaxhighlight> Чтобы поменять строки и столбцы местами, можно использовать такую списковую сборку: <syntaxhighlight lang="python">>>> print([[row[i] for row in mat] for i in [0, 1, 2]]) [[1, 4, 7], [2, 5, 8], [3, 6, 9]]</syntaxhighlight> Применяя вложенные списковые сборки, необходимо помнить о важной вещи: : Во избежание недоразумений при конструировании вложенных списковых сборок, читайте их справа налево. Более многословная, с использованием операторов, версия примера может служить иллюстрацией: <syntaxhighlight lang="python">for i in [0, 1, 2]: for row in mat: print(row[i], end="") print()</syntaxhighlight> В реальных случаях лучше использовать встроенные функции вместо сложных выражений. В нашем случае поможет функция <code>zip()</code>: <syntaxhighlight lang="python">>>> list(zip(*mat)) [(1, 4, 7), (2, 5, 8), (3, 6, 9)]</syntaxhighlight> В разделе [[Учебник Python 3.1#Распаковка списков параметров|Распаковка списков параметров]] описано предназначение звёздочки в этих строках. Другой пример использования вложенных списковых сборок — произведение матрицы a на матрицу b: <syntaxhighlight lang="python">c=[[sum(x*y for x,y in zip(i,j)) for j in zip(*b)] for i in a]</syntaxhighlight> Это можно сделать эффективнее и прозрачнее, но на данном примере видна мощь инструмента. Получение единичной матрицы порядка n: <syntaxhighlight lang="python">a=[[0]*i+[1]+[0]*(n-i-1) for i in range(n)]</syntaxhighlight> === Оператор <code>del</code> === Существует способ удалить элемент, указывая его индекс, а не его значение: оператор <code>del</code>. В отличие от метода <code>pop()</code>, он не возвращает значения. Оператор <code>del</code> может также использоваться для удаления срезов из списка или полной очистки списка (что мы делали ранее через присваивание пустого списка срезу). Например: <syntaxhighlight lang="python">>>> a = [-1, 1, 66.25, 333, 333, 1234.5] >>> del a[0] >>> a [1, 66.25, 333, 333, 1234.5] >>> del a[2:4] >>> a [1, 66.25, 1234.5] >>> del a[:] >>> a []</syntaxhighlight> <code>del</code> может быть также использован для удаления переменных полностью: <syntaxhighlight lang="python">>>> del a</syntaxhighlight> Ссылка на имя <code>a</code> в дальнейшем вызовет ошибку (по крайней мере до тех пор, пока с ним не будет связано другое значение). Позже мы с вами узнаем другие способы использования <code>del</code>. === Кортежи и последовательности === Мы видели, что списки и строки поддерживают много привычных свойств, таких как индексирование и операция получения срезов. Существует два подвида типов данных ''последовательность'' (<tt>sequence</tt>) (см. [[Справочник по библиотеке Python 3.1#Последовательности|Справочник по библиотеке — Последовательности]]), и поскольку Python — развивающийся язык, со временем могут быть добавлены другие последовательные типы данных. Итак, существует также и другой, достойный рассмотрения, стандартный последовательный тип данных: ''кортеж'' (<tt>tuple</tt>). Кортеж состоит из некоторого числа значений разделённых запятыми, например: <syntaxhighlight lang="python">>>> t = 12345, 54321, 'hello!' >>> t[0] 12345 >>> t (12345, 54321, 'hello!') >>> # Кортежи могут быть вложенными: ... u = t, (1, 2, 3, 4, 5) >>> u ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))</syntaxhighlight> Как видите, кортежи на выводе всегда заключены в скобки, таким образом вложенные кортежи интерпретируются корректно; они могут быть введены и с обрамляющими скобками и без, тем не менее в любом случае скобки чаще всего необходимы (если кортеж — часть более крупного выражения). Кортежи можно использовать в различных целях. Например: <code>(x, y)</code> пары координат, записи о рабочих из базы данных, и так далее. Кортежи, как и строки, неизменяемы: невозможно присвоить что-либо индивидуальным элементам кортежа (однако, вы можете симулировать большинство схожих эффектов за счёт операций срезов и конкатенации). Также можно создать кортежи, содержащие изменяемые объекты, такие как списки. Определённая проблема состоит в конструировании кортежей, состоящих из нуля или одного элемента: в синтаксисе языка есть дополнительные хитрости, позволяющие достигнуть этого. Пустые кортежи формируются за счёт пустой пары скобок; кортеж с одним элементом конструируется за счёт запятой, следующей за первым и единственным значением (его не обязательно заключать в скобки). Необычно, но эффективно. Например: <syntaxhighlight lang="python">>>> empty = () >>> singleton = 'hello', # <-- обратите внимание на замыкающую запятую >>> len(empty) 0 >>> len(singleton) 1 >>> singleton ('hello',)</syntaxhighlight> Выражение <code>t = 12345, 54321, 'hello!'</code> является примером ''упаковки кортежей'' (<tt>tuple packing</tt>): значения <code>12345</code>, <code>54321</code> и <code>'hello!'</code> упаковываются в кортеж вместе. Обратная операция также возможна: <syntaxhighlight lang="python">>>> x, y, z = t</syntaxhighlight> Такое действие называется, довольно удачно, ''распаковкой последовательности'' (<tt>sequence unpacking</tt>). Для распаковки на левой стороне требуется список переменных с количеством элементов равным длине последовательности. Обратите внимание, что множественное присваивание на самом деле является лишь комбинацией упаковки кортежа и распаковки последовательности. Здесь есть некоторая асимметрия: упаковка нескольких значений всегда создаёт кортеж, а распаковка работает для любой последовательности. === Множества === Python имеет также тип данных ''множество'' (<tt>set</tt>). Множество — это неупорядоченная коллекция без дублирующихся элементов. Основные способы использования — проверка на вхождение и устранение дублирующихся элементов. Объекты этого типа поддерживают обычные математические операции над множествами, такие как объединение, пересечение, разность и симметрическая разность. Для создания множеств могут быть использованы фигурные скобки или функция <tt>set()</tt>. ''Заметьте:'' Для создания пустого множества нужно использовать <code>set()</code>, а не <code>{}</code>: в последнем случае создаётся пустой ''словарь'' (<tt>dictionary</tt>) — тип данных, который мы обсудим в следующем разделе. Продемонстрируем работу с множествами на небольшом примере<ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">>>> корзина = {'яблоко', 'апельсин', 'яблоко', 'груша', 'апельсин', 'банан'}<br/> >>> ''вывести''(корзина)<br/> {'апельсин', 'банан', 'яблоко', 'груша'}<br/> >>> список_фруктов = ['яблоко', 'апельсин', 'яблоко', 'груша', 'апельсин', 'банан']<br/> >>> фрукты = ''множество''(список_фруктов)&nbsp;&nbsp;&nbsp;&nbsp;# создать множество на основе данных из списка (заметьте исчезновение дубликатов -перев.)<br/> >>> фрукты<br/> {'апельсин', 'груша', 'яблоко', 'банан'}<br/> >>> фрукты = {'апельсин', 'яблоко'}&nbsp;&nbsp;&nbsp;&nbsp;# синтаксис {} эквивалентен [] у списков<br/> >>> фрукты<br/> {'апельсин', 'яблоко'}<br/> >>> 'апельсин' '''среди''' фрукты&nbsp;&nbsp;&nbsp;&nbsp;# быстрая проверка вхождения<br/> Истина<br/> >>> 'росичка' '''среди''' фрукты<br/> Ложь</code><br /><br /></ref>: <syntaxhighlight lang="python">>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'} >>> print(basket) {'orange', 'banana', 'pear', 'apple'} >>> fruit_list = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> fruit = set(fruit_list) # создать множество на основе данных из списка (заметьте исчезновение дубликатов -перев.) >>> fruit {'orange', 'pear', 'apple', 'banana'} >>> fruit = {'orange', 'apple'} # синтаксис {} эквивалентен [] у списков >>> fruit {'orange', 'apple'} >>> 'orange' in fruit # быстрая проверка на вхождение True >>> 'crabgrass' in fruit False</syntaxhighlight> <syntaxhighlight lang="python">>>> # Демонстрация операций со множествами на примере букв из двух слов ... >>> a = set('abracadabra') >>> b = set('alacazam') >>> a # уникальные буквы в a {'a', 'r', 'b', 'c', 'd'} >>> a - b # буквы в a но не в b {'r', 'd', 'b'} >>> a | b # все буквы, которые встречаются в a или в b {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'} >>> a & b # буквы, которые есть и в a и в b {'a', 'c'} >>> a ^ b # буквы в a или в b, но не в обоих {'r', 'd', 'b', 'm', 'z', 'l'}</syntaxhighlight> Как и у списков, у множеств существует синтаксис сборок: <syntaxhighlight lang="python">>>> a = {x for x in 'abracadabra' if x not in 'abc'} >>> a {'r', 'd'}</syntaxhighlight> === Словари === Другой полезный встроенный в Python тип данных — это ''словарь'' (<tt>dictionary</tt>) (см. [[Справочник по библиотеке Python 3.1#Связывающие типы|Справочник по библиотеке — Связывающие типы]]). Словари иногда встречаются в других языках в виде «ассоциативных записей» или «ассоциативных массивов». В отличие от последовательностей, которые индексируются по диапазону чисел, словари индексируются по ''ключам'' (<tt>keys</tt>), которые, в свою очередь, могут быть любого неизменяемого типа; строки и числа всегда могут быть ключами. Кортежи могут быть ключами только если они составлены из строк, чисел или кортежей; если кортеж содержит какой-либо изменяемый объект, явно или неявно, то он не может быть использован в качестве ключа. Вы не можете использовать списки в роли ключей, поскольку списки могут быть изменены на месте присваиванием по индексу, присваиванием по срезу или такими методами как <code>append()</code> и <code>extend()</code>. Лучше всего воспринимать словарь как неупорядоченный набор пар ''ключ: значение'' с требованием, чтобы ключи были уникальны (в пределах одного словаря). Пара скобок создает пустой словарь: <code>{}</code>. Указывая разделённый запятыми список пар ''ключ: значение'' внутри скобок, вы задаёте содержимое словаря; в таком же формате словарь можно вывести. Главные операции над словарём — это сохранение значения с каким-либо ключом и извлечение значения по указанному ключу. Также возможно удалить пару ''ключ: значение'' используя оператор <code>del</code>. Если вы сохраняете значение используя ключ, который уже встречается в словаре — старое значение, ассоциированное с этим ключом, стирается. Извлечение значения по несуществующему ключу вызывает ошибку. Выполнение конструкции <code>list(d.keys())</code> с объектом словаря возвращает список всех ключей, использующихся в словаре, в случайном порядке (если вы хотите отсортировать его, к списку ключей можно применить функцию <code>sorted()</code>). Чтобы проверить, содержит ли словарь определённый ключ, используйте ключевое слово <code>in</code>. Вот небольшой пример использования словарей: <syntaxhighlight lang="python">>>> tel = {'jack': 4098, 'sape': 4139} >>> tel['guido'] = 4127 >>> tel {'sape': 4139, 'guido': 4127, 'jack': 4098} >>> tel['jack'] 4098 >>> del tel['sape'] >>> tel['irv'] = 4127 >>> tel {'guido': 4127, 'irv': 4127, 'jack': 4098} >>> list(tel.keys()) ['irv', 'guido', 'jack'] >>> sorted(tel.keys()) ['guido', 'irv', 'jack'] >>> 'guido' in tel True >>> 'jack' not in tel False</syntaxhighlight> Конструктор <code>dict()</code> строит словарь непосредственно на основе пар ключей и значений, где каждая пара представлена в виде кортежа. Когда пары могут быть сформированы шаблоном, ''списковые сборки'' помогут описать список пар более компактно. <syntaxhighlight lang="python">>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}</syntaxhighlight> В дополнение ко всему этому, для создания словарей из произвольных выражений для ключей и значений, могут быть использованы словарные сборки: <syntaxhighlight lang="python">>>> {x: x**2 for x in (2, 4, 6)} {2: 4, 4: 16, 6: 36}</syntaxhighlight> Позже в учебнике мы изучим выражения-генераторы (<tt>Generator Expressions</tt>), которые даже лучше подходят для снабжения конструктора <code>dict()</code> парами ключ-значение. Если ключи являются простыми строками, иногда легче описать пары используя именованные параметры: <syntaxhighlight lang="python">>>> dict(sape=4139, guido=4127, jack=4098) {'sape': 4139, 'jack': 4098, 'guido': 4127}</syntaxhighlight> === Организация циклов === При организации перебора элементов из словаря ключ и соответствующее ему значение могут быть получены одновременно посредством метода <code>items()</code>. <syntaxhighlight lang="python">>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items(): ... print(k, v) ... gallahad the pure robin the brave</syntaxhighlight> Функция <code>enumerate()</code> поможет пронумеровать элементы перебираемой в цикле последовательности: <syntaxhighlight lang="python">>>> for i, v in enumerate(['tic', 'tac', 'toe']): ... print(i, v) ... 0 tic 1 tac 2 toe</syntaxhighlight> Для того, чтобы организовать цикл параллельно для двух или более последовательностей, элементы можно предварительно сгруппировать функцией <code>zip()</code><ref>''(Прим. перев.):'' <br /><br /> <code style="background-color: inherit !important;">>>> вопросы = ['имя', 'задание', 'любимый цвет']<br/> >>> ответы = ['ланцелот', 'святой грааль', 'синий']<br/> >>> '''для''' вопрос, ответ '''из''' ''застегнуть''(вопросы, ответы):<br/> ... &nbsp;&nbsp;&nbsp;&nbsp;'''вывести'''('Каков(о) ваш(е) {0}? {1}.'.форматировать(вопрос, ответ))<br/> ...<br/> Каков(о) ваш(е) имя? ланцелот.<br/> Каков(о) ваш(е) задание? святой грааль.<br/> Каков(о) ваш(е) любимый цвет? синий.</code></ref>. <syntaxhighlight lang="python">>>> questions = ['name', 'quest', 'favorite color'] >>> answers = ['lancelot', 'the holy grail', 'blue'] >>> for q, a in zip(questions, answers): ... print('What is your {0}? It is {1}.'.format(q, a)) ... What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue.</syntaxhighlight> Изменить порядок следования последовательности на обратный поможет функция <code>reversed()</code>. <syntaxhighlight lang="python">>>> for i in reversed(range(1, 10, 2)): ... print(i) ... 9 7 5 3 1</syntaxhighlight> Для организации цикла по отсортированной последовательности можно применить функцию <code>sorted()</code>, которая возвращает отсортированный список, оставляя исходный без изменений. <syntaxhighlight lang="python">>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> for f in sorted(set(basket)): ... print(f) ... apple banana orange pear</syntaxhighlight> === Подробнее об условиях === Условия в операторах <code>if</code> и <code>while</code> могут содержать любые операции, а не только операции сравнения. Операции сравнения <code>in</code> и <code>not in</code> проверяют, встречается значение в последовательности или нет. Операции <code>is</code> и <code>is not</code> проверяют, не являются ли два объекта на самом деле одним и тем же (это имеет смысл лишь для изменяемых объектов, таких как списки). Все операции сравнения имеют один и тот же приоритет, меньший чем у любых операций над числами. Сравнения можно объединять в цепочки. Например, <code>a < b == c</code> проверяет, меньше ли <code>a</code> чем <code>b</code> и, сверх того, равны ли <code>b</code> и <code>c</code>. Сравнения могут быть скомбинированы с использованием булевых операций <code>and</code> и <code>or</code>, а результат сравнения (или любого другого булева выражения) можно отрицать используя <code>not</code>. Эти операции имеют меньший приоритет, чем у операций сравнения; среди них у <code>not</code> высший приоритет, а у <code>or</code> — низший, поэтому <code>A and not B or C</code> эквивалентно <code>(A and (not B)) or C</code>. Как всегда, явно заданные скобки помогут выразить желаемый порядок выполнения операций. Булевы операции <code>and</code> и <code>or</code> — это так называемые ''коротящие операции''<ref>''(Прим. перев.)'' ''short-circuit''{{ref-en}} — закоротить, обходить, идти обходными путями (для достижения цели), препятствовать</ref> (<tt>short-circuit operators</tt>): их операнды вычисляются слева направо и вычисление заканчивается как только результат становится определён (очевиден). Например, если <code>A</code> и <code>C</code> истинны, а <code>B</code> — ложно, в условии <code>A and B and C</code> выражение <code>C</code> не вычисляется. Когда ''коротящая операция'' используется не в контексте логической операции, она возвращает последний элемент, который был вычислен. Можно присвоить результат сравнения, или другого булева выражения, переменной. Например, <syntaxhighlight lang="python">>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance' >>> non_null = string1 or string2 or string3 >>> non_null 'Trondheim'</syntaxhighlight> Заметьте, что в Python (в отличие от C) присваивание не может использоваться внутри выражений. Программисты на C могут возмутиться по этому поводу, но на самом деле это позволяет избежать ряда проблем, обычного для программ на C: указания оператора присваивания (<code>=</code>) в выражении, вместо предполагавшегося сравнения (<code>==</code>). === Сравнение последовательностей и других типов === Объекты последовательностей можно сравнивать с другими объектами с тем же типом последовательности. Сравнение использует лексикографический порядок: сравниваются первые два элемента, и если они различны — результат сравнения определён; если они равны, сравниваются следующие два элемента и так далее до тех пор, пока одна из последовательностей не будет исчерпана. Если сравниваемые два элемента сами являются последовательностями одного типа, лексикографическое сравнение происходит в них рекурсивно. Если все элементы обеих последовательностей оказались равны, последовательности считаются равными. Если одна последовательность оказывается стартовой последовательностью другой, более короткая последовательность считается меньшей. Лексикографическое упорядочивание строк использует порядок в таблице Unicode для индивидуальных символов. Несколько примеров сравнений между однотипными последовательностями: <syntaxhighlight lang="python">(1, 2, 3) < (1, 2, 4) [1, 2, 3] < [1, 2, 4] "Пайтон" < "Паскаль" < "Си" < "Си++" (1, 2, 3, 4) < (1, 2, 4) (1, 2) < (1, 2, -1) (1, 2, 3) == (1.0, 2.0, 3.0) (1, 2, ('aa', 'ab'), 4) < (1, 2, ('abc', 'a'))</syntaxhighlight> Обратите внимание, что сравнение объектов различных типов операциями <code><</code> или <code>></code> позволено, если объекты имеют соответствующие методы сравнения. Например, смешанные числовые типы сравниваются в соответствии с их численными значениями, так что <code>0</code> равен <code>0.0</code> и т. д. В противном случае интерпретатор, прервав процесс сортировки, возбудит исключение <code>TypeError</code>. == Модули == Если вы выйдете из интерпретатора и зайдёте в него снова, то все определённые вами имена (функции и переменные) будут потеряны. По этой причине, если вы захотите написать несколько более длинную программу, вам лучше использовать текстовый редактор для подготовки ввода для интерпретатора и запускать последний в режиме файлового ввода. Это называется созданием сценария. Если ваша программа становится обширнее, вы можете предпочесть разделить её на несколько файлов для удобства эксплуатации. Также вы можете захотеть использовать сразу в нескольких программах некоторую полезную функцию, написанную вами, не копируя её определение каждый раз. В языке Python можно поместить требуемые определения в файл и использовать их в сценариях или в интерактивном режиме интерпретатора. Такой файл называется ''модулем'' (<tt>module</tt>). Определения из модуля могут быть импортированы в других модулях, либо в главном модуле (собрание переменных, к которым есть доступ в сценарии, который непосредственно запускается, и в интерактивном режиме). Модуль — это файл, содержащий определения и операторы Python. Именем файла является имя модуля с добавленным суффиксом <tt>.py</tt>. Внутри модуля, имя модуля (в качестве строки) доступно в виде значения глобальной переменной с именем <code>__name__</code>. Например, используя ваш любимый текстовый редактор, создайте в текущем каталоге файл с именем <tt>fibo.py</tt> со следующим содержимым: <syntaxhighlight lang="python">"""Модуль вычисления чисел Фибоначчи""" def fib(n): # вывести числа Фибоначчи вплоть до n a, b = 0, 1 while b < n: print(b, end=' ') a, b = b, a+b print() def fib2(n): # вернуть числа Фибоначчи вплоть до n result = [] a, b = 0, 1 while b < n: result.append(b) a, b = b, a+b return result</syntaxhighlight> Теперь можно войти в интерпретатор Python и импортировать этот модуль следующей командой: <syntaxhighlight lang="python">>>> import fibo</syntaxhighlight> Это действие не переводит имена определённых в модуле функций в текущую таблицу символов, а лишь имя модуля <code>fibo</code>. Используя имя модуля, вы можете получить доступ к функциям: <syntaxhighlight lang="python">>>> fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo'</syntaxhighlight> Если вы собираетесь использовать функцию часто, можно присвоить её локальному имени: <syntaxhighlight lang="python">>>> fib = fibo.fib >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377</syntaxhighlight> === Подробнее о модулях === Помимо определений функций модуль может содержать исполняемые операторы. Назначение этих операторов — инициализация модуля: они выполняются при первом импортировании модуля где-либо<ref>Фактически, определения функций — те же «исполняемые» «операторы». Выполнение помещает имя функции в ''глобальную таблицу символов''.</ref>. Каждый модуль имеет свою собственную ''таблицу символов'', которая используется в качестве глобальной всеми определёнными в модуле функциями. Таким образом, автор модуля может использовать глобальные символы в модуле, не опасаясь неожиданных совпадений с глобальными переменными пользователя. С другой стороны, если вы знаете, что делаете, можно сослаться на глобальные переменные модуля, пользуясь той же нотацией, которая применялась для ссылок на его функции: <tt>''&lt;имя_модуля>''.''&lt;имя_элемента>''</tt>. Модули могут импортировать другие модули. Не требуется указывать все операторы <code>import</code> в начале модуля (или сценария, с той же целью), но обычно так и делается. Имена из импортированного модуля добавляются в ''глобальную таблицу символов'' модуля его импортирующего. Есть вариант оператора <code>import</code>, который переносит имена из модуля прямо в таблицу символов импортирующего модуля. Например: <syntaxhighlight lang="python">>>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377</syntaxhighlight> При этом имя самого модуля, из которого переносятся имена элементов, не добавляется в ''локальную таблицу символов'' (так, в этом примере, имя <code>fibo</code> не определено) И есть даже способ импортировать все имена, которые определяет данный модуль: <syntaxhighlight lang="python">>>> from fibo import * >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377</syntaxhighlight> Импортируются все имена, кроме тех, которые начинаются на подчёркивание (<code>_</code>). В большинстве случаев программисты на Python не используют эту возможность, поскольку она внедряет в интерпретатор целый набор новых неизвестных имён и может скрыть некоторые объекты, которые вы уже определили. {{Info2|Для повышения эффективности, каждый модуль импортируется лишь единожды за сеанс работы с интерпретатором. Поэтому, если вы изменили ваши модули, вам придётся перезапустить интерпретатор. Или, если вам нужно перезагрузить конкретный модуль, можно использовать <code>imp.reload()</code> таким образом: <code>import imp; imp.reload(<имя_модуля>)</code>}} ==== Выполнение модулей в качестве сценариев ==== Когда вы запускаете модуль Python в виде <syntaxhighlight lang="python">python fibo.py <параметры></syntaxhighlight> то код в этом модуле будет исполнен в момент его импортирования, но значением <code>__name__</code> будет строка <code>"__main__"</code>. Это значит, что добавляя следующий код в конец сценария: <syntaxhighlight lang="python">if __name__ == "__main__": import sys fib(int(sys.argv[1]))</syntaxhighlight> вы можете сделать возможным запуск файла и в качестве сценария, и в качестве импортируемого модуля. Это возможно, поскольку разбирающий командную строку код выполняется только при исполнении модуля как ''основного'' (<tt>main</tt>) файла: <syntaxhighlight lang="python">$ python fibo.py 50 1 1 2 3 5 8 13 21 34</syntaxhighlight> Если модуль импортируется, код не будет выполнен: <syntaxhighlight lang="python">>>> import fibo >>></syntaxhighlight> Такой приём часто используется, чтобы предоставить удобный пользовательский интерфейс к модулю или для тестирования (выполнение модуля в качестве сценария запускает набор тестов). ==== Путь поиска модулей ==== Если импортируется модуль с именем <code>spam</code>, интерпретатор ищет файл с именем <tt>spam.py</tt> в текущем каталоге, а затем в каталогах, указанных в переменной окружения <code>PYTHONPATH</code>. У неё такой же синтаксис, как и у переменной шелла <code>PATH</code>, которая, в свою очередь, является перечислением каталогов. Когда переменная <code>PYTHONPATH</code> не установлена, или файл не найден в описанных в ней местах, поиск продолжается по пути по умолчанию, зависящему от указанного при установке; на Unix это обычно <tt>.:/usr/local/lib/python</tt>. В действительности поиск модулей производится в списке каталогов в переменной <code>sys.path</code>, которая обычно содержит: каталог, в котором находится сценарий на входе (или текущий каталог), <code>PYTHONPATH</code> и умолчанием для каталога, указанного при установке. Это позволяет программам на Python (если программист знает, что делает) изменять или подменять путь поиска модулей. Заметьте: поскольку каталог, содержащий запускаемый вами сценарий, также находится в пути поиска, важно, чтобы в нем не было сценариев с именем стандартного модуля. Иначе, когда этот модуль будет импортироваться, Python будет пытаться загрузить в виде модуля сам сценарий, что в большинстве случаев вызовет ошибку. Для более подробной информации обратитесь к разделу [[Учебник Python 3.1#Стандартные модули|Стандартные модули]]. ==== «Скомпилированные» файлы Python ==== Интерпретатор Python применяет один важный приём для ускорения запуска программы: если в каталоге, где располагается файл с некоторым модулем <tt>spam.py</tt>, находится также файл <tt>spam.pyc</tt>, предполагается, что это уже скомпилированная в байт-код («<tt>byte-compiled</tt>») версия модуля <code>spam</code>. В файле <tt>spam.pyc</tt> зафиксировано время изменения файла <tt>spam.py</tt> версии, использовавшейся для создания <tt>spam.pyc</tt>. Если версии не совпадают — файл <tt>.pyc</tt> игнорируется. В обычном случае, вам не нужно ничего делать для создания файла <tt>spam.pyc</tt>. Каждый раз, когда <tt>spam.py</tt> успешно компилируется, предпринимается попытка записать скомпилированную версию в <tt>spam.pyc</tt>. Не считается ошибкой, если попытка неудачна: если по какой-либо причине файл не записан полностью, результирующий файл <tt>spam.pyc</tt> будет считаться некорректным и по этой причине в дальнейшем игнорироваться. Содержимое файла <tt>spam.pyc</tt> платформо-независимо, благодаря чему каталог модулей Python может использоваться параллельно машинами с различной архитектурой. Несколько советов экспертам: * Когда интерпретатор Python запускается с флагом <tt>'''-O'''</tt>, в файлах <tt>.pyo</tt> сохраняется сгенерированный оптимизированный код. На данный момент оптимизатор помогает не сильно — он лишь удаляет операторы <code>assert</code>. В случае использования <tt>'''-O'''</tt> оптимизируется весь ''байт-код'' (<tt>bytecode</tt>); файлы <tt>.pyc</tt> игнорируются, а файлы <tt>.py</tt> компилируются в оптимизированный байт-код. * Передача двух флагов <tt>'''-O'''</tt> интерпретатору Python (<tt>'''-OO'''</tt>) принуждает компилятор байт-кода выполнять оптимизации, в редких случаях результат выполнения которых оказывается некачественно функционирующей программой. На данный момент из байт-кода удаляются только строки <code>__doc__</code>, в результате получаются более компактные файлы <tt>.pyo</tt>. Поскольку некоторые программы могут рассчитывать на их (строк) доступность, следует использовать эту возможность только в том случае, если вы знаете что делаете. * Программа сама по себе не работает хоть сколь-нибудь быстрее, будучи прочитанной из файла <tt>.pyc</tt> или <tt>.pyo</tt>, чем если бы она была прочитана из файла <tt>.py</tt>. Единственный процесс, оказывающийся более быстрым при использовании файлов <tt>.pyc</tt> или <tt>.pyo</tt> — это скорость их подгрузки. * Если сценарий запущен из командной строки, его байт-код никогда не будет записан в файл <tt>.pyc</tt> или <tt>.pyo</tt>. Таким образом, время запуска сценария может быть уменьшено за счёт перемещения большей части его кода в модули или использования небольшого загрузочного сценария, импортирующего этот модуль. Кроме того, можно указывать файл <tt>.pyc</tt> или <tt>.pyo</tt> прямо в командной строке. * Можно иметь в наличии файл с именем <tt>spam.pyc</tt> (или <tt>spam.pyo</tt>, когда используется <tt>'''-O'''</tt>), не имея файла <tt>spam.py</tt> для того же модуля. Таким образом можно распространять библиотеки кода Python в том виде, из которого трудно восстановить исходный код. * Модуль <tt>[[Справочник по библиотеке Python 3.1#compileall|compileall]]</tt> может создать файлы <tt>.pyc</tt> (или файлы <tt>.pyo</tt>, когда используется <tt>'''-O'''</tt>) для всех модулей в каталоге. === Стандартные модули === Python поставляется с библиотекой стандартных модулей, описанной в отдельном документе, [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке Python]] (далее — «Справочнику по библиотеке»). Некоторые модули встроены в интерпретатор. Они обеспечивают доступ к операциям, не входящим в ядро языка, и встроены для большей эффективности и предоставления доступа к основным средствам операционной системы, таким как ''системные вызовы'' (<tt>system calls</tt>). Набор таких модулей — выбор настройки, зависимый от используемой платформы. Например, модуль <code>winreg</code> предоставляется только на системах с Windows. Один конкретный модуль заслуживает большего внимания: модуль <tt>[[Справочник по библиотеке Python 3.1#sys|sys]]</tt>, встроенный в каждую версию интерпретатора Python. Переменные <code>sys.ps1</code> и <code>sys.ps2</code> определяют строки, использующиеся в качестве основного и вспомогательного приглашений: <syntaxhighlight lang="python">>>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>> sys.ps1 = "Вводите: " Вводите: print('Ох!') Ох! Вводите: </syntaxhighlight> Эти две переменные определены только для интерактивного режима интерпретатора. Переменная <code>sys.path</code> представляет собой список строк, определяющий путь поиска модулей интерпретатора. Она инициализируется значением пути по умолчанию, взятым из переменной окружения <tt>PYTHONPATH</tt>, или встроенным значением по умолчанию, если <tt>PYTHONPATH</tt> не установлен. Вы можете изменить её значение, используя стандартные операции со списками: <syntaxhighlight lang="python">>>> import sys >>> sys.path.append('/ufs/guido/lib/python')</syntaxhighlight> === Функция <code>dir()</code> === Встроенная функция <code>dir()</code> используется для получения имён, определённых в модуле. Она возвращает отсортированный список строк: <syntaxhighlight lang="python">>>> import fibo, sys >>> dir(fibo) ['__name__', 'fib', 'fib2'] >>> dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'callstats', 'copyright', 'displayhook', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions']</syntaxhighlight> Будучи использованной без аргументов, функция <code>dir()</code> возвращает список имён, определённых в данный момент. <syntaxhighlight lang="python">>>> a = [1, 2, 3, 4, 5] >>> import fibo >>> fib = fibo.fib >>> dir() ['__builtins__', '__doc__', '__file__', '__name__', 'a', 'fib', 'fibo', 'sys']</syntaxhighlight> Обратите внимание, что список состоит из имён всех типов: переменных, модулей, функций и т. д. В возвращаемом функцией <code>dir()</code> списке не содержится встроенных функций и переменных. Если вы хотите получить ''их'' список, то они определены в стандартном модуле <code>builtins</code>: <syntaxhighlight lang="python">>>> import builtins >>> dir(builtins) ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'Buffer Error', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Excep tion', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError ', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImp lemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecatio nWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', ' UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueE rror', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__' , '__import__', '__name__', 'abs', 'all', 'any', 'basestring', 'bin', 'bool', 'b uffer', 'bytes', 'chr', 'chr8', 'classmethod', 'cmp', 'compile', 'complex', 'cop yright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'ex ec', 'exit', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'h ash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', ' len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'o bject', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr ', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'st r', 'str8', 'sum', 'super', 'trunc', 'tuple', 'type', 'vars', 'zip']</syntaxhighlight> === Пакеты === Пакеты — способ структурирования ''пространств имён'' (<tt>namespaces</tt>) модулей Python за счёт использования имён модулей, разделённых точками («<tt>dotted module names</tt>»). Например, имя модуля <code>A.B</code> означает — подмодуль<ref>''(Прим. перев.)'' ''подмодуль'' (<tt>submodule</tt>), ''зд.'' — модуль, находящийся в пакете. ''подпакет'' (<tt>subpackage</tt>), ''зд.'' — пакет, расположенный в пакете.</ref> с именем <code>B</code> в пакете с именем <code>A</code>. Так же как использование модулей позволяет авторам различных модулей не заботиться о пересекающихся именах среди глобальных переменных, использование именования через точку позволяет авторам многомодульных пакетов (таких как <tt>NumPy</tt> или <tt>Python Imaging Library</tt>) не заботиться о конфликтах имён модулей. Допустим, вы собираетесь разработать набор модулей (''пакет'', <tt>package</tt>) для унифицированной работы со звуковыми файлами и звуковыми данными. Существует множество форматов звуковых файлов (обычно их можно распознать по расширению, например: <tt>.wav</tt>, <tt>.aiff</tt>, <tt>.au</tt>). Таким образом, вам может понадобиться создать и поддерживать разрастающуюся коллекцию модулей для конвертирования между различными форматами файлов. Также вам наверняка захочется иметь побольше операций для обработки звуковых данных (таких как смешивание, добавление эха, применение функции эквалайзера, создание искусственного стерео-эффекта), поэтому в дополнение к этому вы будете писать нескончаемый поток модулей для исполнения этих операций. Вот возможная структура вашего пакета (выраженная в терминологии иерархической файловой системы): <pre style="color:#00008b;">sound/ Пакет верхнего уровня __init__.py Инициализация пакета работы со звуком (sound) formats/ Подпакет для конвертирования форматов файлов __init__.py wavread.py (чтение wav) wavwrite.py (запись wav) aiffread.py (чтение aiff) aiffwrite.py (запись aiff) auread.py (чтение au) auwrite.py (запись au) ... effects/ Подпакет для звуковых эффектов __init__.py echo.py ( эхо ) surround.py ( окружение ) reverse.py ( обращение ) ... filters/ Подпакет для фильтров __init__.py equalizer.py ( эквалайзер ) vocoder.py ( вокодер ) karaoke.py ( караоке ) ...</pre> При импорте пакета Python ищет подкаталог пакета в каталогах, перечисленных в <code>sys.path</code>. Файлы <tt>__init__.py</tt> необходимы для того, чтобы Python трактовал эти каталоги как содержащие пакеты. Это сделано во избежание нечаянного сокрытия правомерных модулей, встречающихся в дальнейшем по пути поиска, каталогами с часто используемыми именами, таким как «<code>string</code>». В наипростейшем случае файл <tt>__init__.py</tt> может быть пустым, но в более сложных может содержать код инициализации пакета или устанавливать значение описанной ниже переменной <code>__all__</code>. Пользователи пакета могут импортировать из него конкретные модули, например: <syntaxhighlight lang="python">import sound.effects.echo</syntaxhighlight> Таким образом подгружается подмодуль <code>sound.effects.echo</code>. Ссылаться на него нужно используя его полное имя: <syntaxhighlight lang="python">sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)</syntaxhighlight> Другой способ импортирования подмодуля: <syntaxhighlight lang="python">from sound.effects import echo</syntaxhighlight> Так тоже подгружается подмодуль <code>echo</code>, но теперь он доступен без префикса пакета, поэтому может использоваться следующим образом: <syntaxhighlight lang="python">echo.echofilter(input, output, delay=0.7, atten=4)</syntaxhighlight> И еще один вариант — прямое импортирование желаемой функции или переменной: <syntaxhighlight lang="python">from sound.effects.echo import echofilter</syntaxhighlight> Опять же, таким образом подгружается подмодуль <code>echo</code>, но теперь его функция <code>echofilter()</code> может быть вызвана непосредственно: <syntaxhighlight lang="python">echofilter(input, output, delay=0.7, atten=4)</syntaxhighlight> Заметьте, что при использовании выражения <code>from ''пакет'' import ''элемент''</code>, ''элементом'' может быть подмодуль (или подпакет) пакета или любое другое имя, определённое в пакете — например, функция, класс или переменная. Оператор <code>import</code> сначала проверяет, определён ли элемент в пакете; если нет — он трактует его как модуль и пытается загрузить. Если не удается его найти, порождается исключение <code>ImportError</code>. Напротив, при использовании синтаксиса в стиле <code>import ''элемент''.''подэлемент''.''подэлемент''</code>, все элементы кроме последнего должны быть пакетами; последний элемент может быть модулем или пакетом, но не может быть классом, функцией или переменной, определёнными в предыдущем элементе. ==== Импорт <code>*</code> из пакета ==== Что происходит, когда пользователь пишет <code>from sound.effects import *</code> ? В идеале, мы бы надеялись, что таким образом код выходит в файловую систему и находит какие подмодули существуют в пакете, импортируя их все. К сожалению, такой метод не очень хорошо работает на платформах Windows, поскольку у файловой системы не всегда есть корректная информация о регистре имён файлов. На этих платформах нет гарантированного способа узнать, нужно ли импортировать файл <tt>ECHO.PY</tt> в качестве модуля <code>echo</code>, <code>Echo</code> или <code>ECHO</code>. (Например, у Windows 95 есть назойливая привычка показывать имена всех файлов с заглавной буквы.) Ограничение DOS на имя файла в формате 8+3 добавляет забавную проблему, связанную с длинными именами модулей. Единственный выход для автора пакета — предоставить его подробное содержание. Оператор <code>import</code> использует следующее соглашение: если в коде файла <tt>__init__.py</tt> текущего пакета определён список <code>__all__</code>, то он полагается списком имён модулей, которые нужно импортировать в случае <code>from ''пакет'' import *</code>. На совести автора поддержка этого списка в соответствующем состоянии в каждой новой версии пакета. Впрочем, авторы пакета могут его не поддерживать вообще, если не видят смысла в импортировании <code>*</code> из их пакета. Например, файл <code>sounds/effects/__init__.py</code> может содержать следующий код: <syntaxhighlight lang="python">__all__ = ["echo", "surround", "reverse"]</syntaxhighlight> Это будет значить, что выражение <code>from sound.effects import *</code> импортирует три именованных подмодуля из пакета <code>sound</code>. Если список <code>__all__</code> не определён, оператор <code>from Sound.Effects import *</code> не импортирует все подмодули пакета <code>sound.effects</code> в текущее пространство имён: он лишь убеждается, что импортирован пакет <code>sound.effects</code> (возможно, выполняя код инициализации из <tt>__init__.py</tt>), а затем импортирует все определённые в пакете имена. В этот список попадают любые имена, определённые (и загруженные явно подмодулями) в <tt>__init__.py</tt>. В него также попадают все явно загруженные предшествующими операторами <code>import</code> подмодули. Рассмотрим следующий код: <syntaxhighlight lang="python">import sound.effects.echo import sound.effects.surround from sound.effects import *</syntaxhighlight> В этом примере модули <code>echo</code> и <code>surround</code> импортируются в текущее пространство имён, поскольку они определены в пакете <code>sound.effects</code> на тот момент, когда исполняется оператор <code>from ... import</code>. (И это также работает если определён <code>__all__</code>.) Обратите внимание, что в общем случае импортирование <code>*</code> из модуля не приветствуется, поскольку в результате часто получается плохо-читаемый код. Однако, вполне нормально использовать его в интерактивных сессиях, чтобы меньше печатать, а определённые модули разработаны для экспорта только тех имён, которые следуют определённым шаблонам. Помните: в использовании <code>from ''пакет'' import ''определённый_подмодуль''</code> нет ничего плохого. На самом деле — это рекомендованная запись, до тех пор пока при импортировании модуля не нужно использовать подмодули с одинаковым именем из разных пакетов. ==== Ссылки внутри пакета ==== Когда пакеты структурированы в подпакеты (например, в случае пакета <code>sound</code>), для того, чтобы сослаться на пакеты-потомки вы можете использовать абсолютное импортирование (<tt>absolute imports</tt>). Например, если модуль <code>sound.filters.vocoder</code> нуждается в модуле <code>echo</code> из пакета <code>sound.effects</code>, он должен использовать <code>from sound.effects import echo</code>. Вы можете также использовать ''относительное импортирование'' (<tt>relative imports</tt>), применяя следующую форму оператора <code>import</code>: <code>from ''модуль'' import ''имя''</code> . При таком способе импортирования для описания текущего и родительского пакетов используется символ точки. Например, для модуля <code>surround</code> вы можете написать: <syntaxhighlight lang="python">from . import echo from .. import formats from ..filters import equalizer</syntaxhighlight> Обратите внимание, что относительное импортирование основано на имени текущего модуля. Поскольку имя главного модуля всегда «<code>__main__</code>», модули, предназначенные для использования в качестве главных модулей приложения на Python, должны всегда использовать ''абсолютное импортирование'' (<tt>absolute imports</tt>). ==== Пакеты в нескольких каталогах ==== Пакеты поддерживают ещё один специальный аттрибут: <code>__path__</code>. Перед исполнением файла <tt>__init__.py</tt> этого пакета, он инициализируется списком, содержащим имя каталога, в котором этот файл находится. Изменив переменную, можно повлиять на ход поиска модулей и подпакетов, содержащихся в пакете. Хотя эта возможность нужна не так часто, она может быть использована для расширения набора модулей, находящихся в пакете. == Ввод и вывод == Ознакомить пользователя с выводом программы можно различными способами — данные могут быть выведены в читаемом виде или записаны в файл для последующего использования. Часть возможностей будет обсуждена в этой главе. === Удобное форматирование вывода === На данный момент мы выяснили два способа вывода значений: ''операторные выражения'' (<tt>expression statements</tt>) и функция <code>print()</code>. (Третий способ — использование метода <code>write()</code> объектов файлов; на файл стандартного вывода можно сослаться как на <code>sys.stdout</code>. Более подробную информацию по этому пункту смотрите в [[Справочник по библиотеке Python 3.1|Справочнике по библиотеке]].) Часто возникает желание иметь больший контроль над форматированием вывода, чем обычная печать значений разделённых пробелами. Есть два способа форматирования вашего вывода. Первый способ — выполнять самостоятельно всю работу над строками: используя срезы строк и конкатенацию вы можете создать любой шаблон, какой пожелаете. Стандартный модуль <code>string</code> содержит много полезных операций для выравнивания строк по определённой ширине колонки (скоро мы их кратко рассмотрим). Второй способ — использование метода <code>str.format()</code>. Модуль <code>string</code> содержит класс <code>Template</code>, который предоставляет ещё один способ подстановки значений в строки. Остаётся, конечно, один вопрос: каким образом конвертировать значения в строки? К счастью, в Python есть два способа для преобразования любого значения в строку — это функции <code>repr()</code> и <code>str()</code>. Предназначение функции <code>str()</code> — возврат значений в довольно-таки читабельной форме; в отличие от <code>repr()</code>, чьё назначение — генерирование форм<ref>(''Прим. перев.'') ''representation'' {{ref-en}} — представление, образ, форма</ref>, которые могут быть прочитаны интерпретатором (или вызовут ошибку <code>SyntaxError</code>, если эквивалентного синтаксиса не существует). Для тех объектов, у которых нет формы для человеческого прочтения функция <code>str()</code> возвратит такое же значение, как и <code>repr()</code>. У многих значений, таких как числа или структуры, вроде списков и словарей, одинаковая форма для обеих функций. Строки и числа с плавающей точкой, в частности, имеют по две разных формы. Несколько примеров: <syntaxhighlight lang="python">>>> s = 'Привет, мир.' >>> str(s) 'Привет, мир.' >>> repr(s) "'Привет, мир.'" >>> str(0.1) '0.1' >>> repr(0.1) '0.10000000000000001' >>> x = 10 * 3.25 >>> y = 200 * 200 >>> s = 'Значение x - ' + repr(x) + ', а y - ' + repr(y) + '...' >>> print(s) Значение x - 32.5, а y - 40000... >>> # Функция repr(), применённая к строке, добавляет кавычки и обратные слэши: ... hello = 'привет, мир\n' >>> hellos = repr(hello) >>> print(hellos) 'привет, мир\n' >>> # Параметром функции repr() может быть объект Python: ... repr((x, y, ('фарш', 'яйца'))) "(32.5, 40000, ('фарш', 'яйца'))"</syntaxhighlight> Вот два способа вывести таблицу квадратов и кубов: <syntaxhighlight lang="python">>>> for x in range(1, 11): ... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ') ... # Обратите внимание на использование end в предыдущей строке ... print(repr(x*x*x).rjust(4)) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 >>> for x in range(1, 11): ... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000</syntaxhighlight> (Обратите внимание, что в первом примере единичные пробелы между колонками добавлены функцией <code>print()</code>: она всегда вставляет пробелы между своими параметрами) Этот пример демонстрирует работу метода строковых объектов <code>rjust()</code>, выравнивающего строку по правому краю в поле переданной ширины, отступая пробелами слева. Имеются также похожие методы <code>ljust()</code> и <code>center()</code>. Эти методы не выводят ничего, они лишь возвращают новую строку. Если строка на входе чересчур длинная, то они не усекают её, что обычно является меньшим из зол. (Для усечения можно добавить операцию среза, например: <code>x.ljust(n)[:n]</code>.) Есть другой метод — <code>zfill()</code>, который заполняет нулями пространство слева от числовой строки. Он распознаёт знаки плюс и минус: <syntaxhighlight lang="python">>>> '12'.zfill(5) '00012' >>> '-3.14'.zfill(7) '-003.14' >>> '3.14159265359'.zfill(5) '3.14159265359'</syntaxhighlight> Основной способ применения метода <code>str.format()</code> выглядит так<ref>''(Прим. перев.)'' We are the knights who say «Ni!» (''Мы — те рыцари, что говорят «Ни!»'') — цитата из [http://www.mwscomp.com/movies/grail/grail-13.htm сцены 13-й] фильма Монти Пайтон и Святой Грааль (Monty Python and Holy Grail)</ref>: <syntaxhighlight lang="python">>>> print('Мы — те {0}, что говорят "{1}!"'.format('рыцари', 'Ни')) Мы — те рыцари, что говорят "Ни!"</syntaxhighlight> Скобки с символами внутри (их называют ''полями форматирования'' (<tt>format fields</tt>)) заменяются на объекты, переданные методу <code>format</code>. Номер в скобках обозначает позицию объекта в списке параметров, переданных методу <code>format</code>. <syntaxhighlight lang="python">>>> print('{0} и {1}'.format('фарш', 'яйца')) фарш и яйца >>> print('{1} и {0}'.format('фарш', 'яйца')) яйца и фарш</syntaxhighlight> Если в методе <code>format</code> используются именованные параметры, можно ссылаться на их значения, используя имя соответствующего аргумента<ref>''(Прим. перев.)'' <tt>вывести('Этот {пища} — {прилагательное}.'.format(пища='фарш', прилагательное='непередаваемо ужасен'))</tt></ref>. <syntaxhighlight lang="python">>>> print('Этот {food} — {adjective}.'.format( ... food='фарш', adjective='непередаваемо ужасен')) Этот фарш — непередаваемо ужасен.</syntaxhighlight> Позиционные и именованные параметры можно произвольно совмещать<ref>''(Прим. перев.)'' <tt>вывести('История о {0}, {1}, и {другой}.'.format('Билл', 'Манфред', другой='Георг'))</tt></ref>: <syntaxhighlight lang="python">>>> print('История о {0}е, {1}е, и {other}е.'.format('Билл', 'Манфред', other='Георг')) История о Билле, Манфреде, и Георге.</syntaxhighlight> После имени поля может следовать необязательный спецификатор формата ‘<code>:</code>’. С его помощью можно управлять форматированием значения. Следующий пример оставляет у числа Пи только три цифры после десятичного разделителя<ref>''(Прим. перев.)'' В качестве десятичного разделителя в Python используется точка, в соответствии со стандартами большинства стран.</ref>. <syntaxhighlight lang="python">>>> import math >>> print('Значение ПИ — примерно {0:.3f}.'.format(math.pi)) Значение ПИ — примерно 3.142.</syntaxhighlight> После спецификатора ‘<code>:</code>’ можно указать число — минимальную ширину поля, выраженную в количестве символов. Это удобно использовать для создания красивых таблиц: <syntaxhighlight lang="python">>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678} >>> for name, phone in table.items(): ... print('{0:10} ==> {1:10d}'.format(name, phone)) ... Jack ==> 4098 Dcab ==> 7678 Sjoerd ==> 4127</syntaxhighlight> Если ваша строка с форматами очень длинна, а вы не хотите разбивать её на подстроки, было бы неплохо если бы вы могли ссылаться на переменные, предназначенные для форматирования, не по позиции, а по имени. Это можно сделать, просто передав словарь и используя квадратные скобки ‘<tt>[]</tt>’ для доступа к ключам. <syntaxhighlight lang="python">>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; ' 'Dcab: {0[Dcab]:d}'.format(table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678</syntaxhighlight> Тоже самое можно сделать, передав словарь именованных параметров, используя нотацию «<code>**</code>»: <syntaxhighlight lang="python">>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678</syntaxhighlight> В частности, такой приём удобно использовать в сочетании со встроенной функцией <code>vars()</code>, которая возвращает словарь с локальными переменными. Подробное описание форматирования строк с применением метода <code>str.format()</code> описано в разделе [[Справочник по библиотеке Python 3.1#Синтаксис строк форматирования|Синтаксис строк форматирования]]. ==== Форматирование строк в старом стиле ==== Для форматирования строк можно использовать и операцию <code>%</code>. Она интерпретирует левый операнд как строку форматирования в стиле <code>sprintf</code>, которую следует применить к правому операнду, и возвращает строку, получившуюся в результате этого преобразования. Например: <syntaxhighlight lang="python">>>> import math >>> print 'Значение ПИ — примерно %5.3f.' % math.pi Значение ПИ — примерно 3.142.</syntaxhighlight> Поскольку метод <code>str.format()</code> довольно нов, большая часть исходных кодов Python всё ещё использует операцию <code>%</code>. Однако, со временем, форматирование строк будет удалено из языка, поэтому в большинстве случаев следует использовать <code>str.format()</code>. Больше информации можно найти в разделе [[Справочник по библиотеке Python 3.1#Операции форматирования строк в старом стиле|Операции форматирования строк в старом стиле]]. === Запись и чтение файлов === Функция <code>open()</code> возвращает объект файла и в большинстве случаев используется с двумя аргументами: <code>open(''имя_файла'', ''режим'')</code>. <syntaxhighlight lang="python">>>> f = open('/tmp/workfile', 'w')</syntaxhighlight> Первый параметр — строка, содержащая имя файла. Второй — другая строка, содержащая несколько символов, описывающих способ использования файла. Значение параметра ''режим'' может быть символом <code>'r'</code>, если файл будет открыт только для чтения, <code>'w'</code> — открыт только для записи (существующий файл с таким же именем будет стёрт) и <code>'a'</code> — файл открыт для добавления: любые данные, записанные в файл автоматически добавляются в конец. <code>'r+'</code> открывает файл и для чтения, и для записи. Параметр ''режим'' необязателен: если он опущен — предполагается, что он равен <code>'r'</code>. В обычном случае файлы открываются в ''текстовом режиме'' (<tt>text mode</tt>) — это значит что вы читаете из файла и записываете в файл строки в определённой кодировке (по умолчанию используется <tt>UTF-8</tt>). Если добавить к режиму файла символ ‘<code>b</code>’, файл открывается в ''двоичном режиме'' (<tt>binary mode</tt>): теперь данные считываются и записываются в виде двоичных объектов. Этот режим следует использовать для всех файлов, которые не содержат текст. При использовании текстового режима, все окончания строк, по умолчанию, специфичные для платформы (<code>\n</code> в Unix, <code>\r\n</code> в Windows) усекаются до символа <code>\n</code>, при чтении из файла, и конвертируются обратно из <code>\n</code> в вид, специфичный для платформы, при записи в файл. Эти закулисные изменения в файловых данных корректно работают в случае текстовых файлов, но испортят двоичные данные в файлах вроде <code>JPEG</code> или <code>EXE</code>. Внимательно следите за тем, чтобы использовать двоичный режим при чтении и записи таких файлов. ==== Методы объектов-файлов ==== В примерах ниже подразумевается, что заранее создан файловый объект с именем <code>f</code>. Чтобы прочитать содержимое файла, вызовите <code>f.read(''размер'')</code> — функция читает некоторое количество данных и возвращает их в виде строки или байтового объекта. <code>''размер''</code> — необязательный числовой параметр. Если <code>''размер''</code> опущен или отрицателен, будет прочитано и возвращено всё содержимое файла; если файл по величине в два раза больше оперативной памяти вашего компьютера, то решение этой проблемы остаётся на вашей совести. В противном случае, будет прочитано и возвращено максимум <code>''размер''</code> байт. Если был достигнут конец файла, <code>f.read()</code> вернёт пустую строку (<code>''</code>). <syntaxhighlight lang="python">>>> f.read() 'Это всё содержимое файла.\n' >>> f.read() ''</syntaxhighlight> <code>f.readline()</code> читает одну строку из файла; символ новой строки (<code>\n</code>) остаётся в конце прочитанной строки и отсутствует при чтении последней строки файла только если файл не оканчивается пустой строкой. За счёт этого возвращаемое значение становится недвусмысленным: если <code>f.readline()</code> возвращает пустую строку — достигнут конец файла, в то же время незаполненная строка, представленная посредством <code>'\n'</code>, содержит лишь символ новой строки.<ref>''(Прим. перев.)'' В источнике, в большинстве случаев, разделяется понятие ''строки'' как типа данных и ''строки'' как строки текста (ср., ''строчка'') применением слов ''string'' и ''line'' соответственно. В русском языке это различие передать сложно, тем не менее я старался по возможности избежать двусмысленностей.</ref> <syntaxhighlight lang="python">>>> f.readline() 'Это первая строка файла.\n' >>> f.readline() 'Вторая строка файла\n' >>> f.readline() ''</syntaxhighlight> <code>f.readlines()</code> возвращает список, содержащий все строки с данными, обнаруженные в файле. Если передан необязательный параметр <code>подсказка_размера</code>, функция читает из файла указанное количество байт, плюс некоторое количество байт сверх того, достаточное для завершения строки, и формирует список строк из результата. Функция часто используется для более эффективного (файл не загружается в память полностью) построчного чтения больших файлов. Возвращены будут только полные (завершённые) строки. <syntaxhighlight lang="python">>>> f.readlines() ['Это первая строка файла.\n', 'Вторая строка файла\n']</syntaxhighlight> Альтернативный способ построчного чтения — организация цикла по файловому объекту. Он быстр, рационально использует память и имеет простой код в результате: <syntaxhighlight lang="python">>>> for line in f: print(line, end='') Это первая строка файла. Вторая строка файла</syntaxhighlight> Альтернативный способ проще, но не предоставляет тонкого контроля над происходящим. Поскольку оба этих способа работают с буферизацией строк по-разному, их не следует смешивать. <code>f.write(''строка'')</code> записывает содержимое ''строки'' в файл и возвращает количество записанных байтов. <syntaxhighlight lang="python">>>> f.write('This is a test\n') 15</syntaxhighlight> Чтобы записать в файл нечто отличное от строки, предварительно это нечто нужно в строку сконвертировать<ref>''(Прим. перев.)'' Возможно, подразумевается [[w:ru:Ответ на главный вопрос жизни, вселенной и всего такого|ответ на главный вопрос жизни, вселенной и всего такого]]</ref>: <syntaxhighlight lang="python">>>> value = ('ответ', 42) >>> s = str(value) >>> f.write(s) 18</syntaxhighlight> <code>f.tell()</code> возвращает целое, представляющее собой текущую позицию в файле <code>f</code>, измеренную в байтах от начала файла. Чтобы изменить позицию объекта-файла, используйте <code>f.seek(''смещение'', ''откуда'')</code>. Позиция вычисляется прибавлением смещения к точке отсчёта; точка отсчёта выбирается из параметра <code>''откуда''</code>. Значение <code>0</code> параметра <code>''откуда''</code> отмеряет смещение от начала файла, значение <code>1</code> применяет текущую позицию в файле, а значение <code>2</code> в качестве точки отсчёта использует конец файла. Параметр <code>''откуда''</code> может быть опущен и по умолчанию устанавливается в <code>0</code>, используя начало файла в качестве точки отсчёта. <syntaxhighlight lang="python">>>> f = open('/tmp/workfile', 'rb+') >>> f.write(b'0123456789abcdef') 16 >>> f.seek(5) # Перейти к шестому байту в файле 5 >>> f.read(1) b'5' >>> f.seek(-3, 2) # Перейти к третьему байту с конца 13 >>> f.read(1) b'd'</syntaxhighlight> При работе с текстовыми файлами (открытыми без символа <code>b</code> в строке режима), выполнять позиционирование (<code>seek</code>) позволяется только от начала файла (за исключением прокрутки в конец файла с использованием <code>seek(0, 2)</code>). Когда вы закончили все действия над файлом, вызовите <code>f.close()</code> чтобы закрыть его и освободить все системные ресурсы, использованные при открытии этого файла. Все попытки использовать объект-файл после вызова <code>f.close()</code> приведут к возникновению исключения. <syntaxhighlight lang="python">>>> f.close() >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: I/O operation on closed file</syntaxhighlight> Считается хорошей манерой использовать ключевое слово <code>with</code> при работе с файловыми объектами. Преимущество этого способа в том, что файл всегда корректно закрывается после выполнения блока, либо если при выполнении было порождено исключение. Кроме того, получающийся код намного короче, чем эквивалентная форма с блоками <tt><code>try</code>-<code>finally</code></tt>: <syntaxhighlight lang="python">>>> with open('/tmp/workfile', 'r') as f: ... read_data = f.read() >>> f.closed True</syntaxhighlight> У объектов-файлов есть ещё несколько дополнительных методов, таких как <code>isatty()</code> и <code>truncate()</code>, которые используются не так часто; обратитесь к [[Справочник по библиотеке Python 3.1|Справочнику по библиотеке]] для более полного обзора по файловым объектам. ==== Модуль <code>pickle</code> ==== Строки могут с лёгкостью быть записаны в файл и прочитаны из файла. В случае чисел нужно применить несколько больше усилий: метод <code>read()</code> возвращает только строки, которые придётся передать функции вроде <code>int()</code>, которая принимает строку вида <code>'123'</code> и возвращает её числовое значение: <code>123</code>. Однако если вы намереваетесь сохранить более сложные типы данных, такие как списки, словари или экземпляры классов, всё становится несколько запутаннее. Вместо того чтобы принуждать программиста постоянно писать и отлаживать код для замысловатых типов данных, Python предоставляет стандартный модуль под названием <code>pickle</code>. Это замечательный модуль, который может принять любой объект Python (даже некоторые формы кода на Python!) и конвертировать его в строковое представление: этот процесс называется ''консервацией'' (<tt>pickling</tt>). Восстановление объекта из его строкового представления называется ''расконсервацией'' (<tt>unpickling</tt>): строка, описывающая объект, может быть сохранена в файл, добавлена к некоторым данным, или отослана через соединение по сети на удаленный компьютер.<ref>''(Прим. перев.)'' ''Консервирование'' в Python можно рассматривать как частный случай [[w:ru:Сериализация|сериализации]]; ещё про ''консервирование'' можно почитать [http://www.ibm.com/developerworks/ru/library/l-pypers/index.html здесь].</ref> Если у вас есть некоторый объект <code>x</code> и объект файла <code>f</code>, открытый на запись в двоичном режиме (binary mode, с параметром 'wb'), простейший способ ''законсервировать'' объект требует одной-единственной строки кода: <syntaxhighlight lang="python">pickle.dump(x, f)</syntaxhighlight> Чтобы снова расконсервировать объект, при условии что <code>f</code> — объект файла, открытого для чтения (так же в двоичном режиме, с параметром 'rb'): <syntaxhighlight lang="python">x = pickle.load(f)</syntaxhighlight> (Существуют варианты выполнения этих операций, применяемые при ''расконсервации'' нескольких объектов или когда вам требуется записать ''консервированные'' данные в файл; обратитесь к документации по модулю [[Справочник по библиотеке Python 3.1#pickle|pickle]] из [[Справочник по библиотеке Python 3.1|Справочника по библиотеке]].) [[Справочник по библиотеке Python 3.1#pickle|pickle]] — стандартный способ для создания объектов Python, которые могут быть повторно использованы другими программами или будущими версиями этой же программы; для них есть технический термин — ''устойчивый объект'' (<tt>persistent object</tt>). Поскольку [[Справочник по библиотеке Python 3.1#pickle|pickle]] используется часто, многие авторы расширений для Python заботятся о том, чтобы новые типы данных, такие как матрицы, могли быть корректно ''законсервированы'' и ''расконсервированы''. == Ошибки и исключения == До этого момента сообщения об ошибках лишь упоминались, но если вы пробовали примеры на практике — возможно, вы уже видели некоторые. Существует (как минимум) два различимых вида ошибок: ''синтаксические ошибки'' (<tt>syntax errors</tt>) и ''исключения'' (<tt>exceptions</tt>). === Синтаксические ошибки === Синтаксические ошибки, также известные как ошибки разбора кода (''парсинга'', <tt>parsing</tt>) — вероятно, наиболее привычный вид жалоб компилятора, попадающихся вам при изучении Python: <syntaxhighlight lang="python">>>> while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^ SyntaxError: invalid syntax</syntaxhighlight> Парсер<ref>''(Прим. перев.)'' ''Parser'' {{ref-en}} — программа синтаксического анализа, синтаксический анализатор; программа грамматического разбора</ref> повторно выводит ошибочную строку и отображает небольшую «стрелку», указывающую на самую первую позицию в строке, где была обнаружена ошибка. Причина ошибки (или по крайней мере место обнаружения) находится в символе<ref>''(Прим. перев.)'' ''Token'' {{ref-en}} — некоторая смысловая единица выражения: оператор, ключевое слово, значение переменной, …</ref>, предшествующем указанному: в приведённом примере ошибка обнаружена на месте вызова функции <code>print()</code>, поскольку перед ним пропущено двоеточие (<code>':'</code>). Также здесь выводятся имя файла и номер строки, благодаря этому вы знаете в каком месте искать, если ввод был сделан из сценария. === Исключения === Даже если выражение или оператор синтаксически верны, они могут вызвать ошибку при попытке их исполнения. Ошибки, обнаруженные при исполнении, называются ''исключениями'' (<tt>exceptions</tt>). Они не фатальны: позже вы научитесь перехватывать их в программах на Python. Большинство исключений, правда, как правило, не обрабатываются программами и приводят к сообщениям об ошибке, таким как следующие: <syntaxhighlight lang="python">>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in ? ZeroDivisionError: int division or modulo by zero >>> 4 + spam*3 Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: coercing to Unicode: need string or buffer, int found</syntaxhighlight> Последняя строка сообщения об ошибке описывает произошедшее. Исключения представлены различными типами и тип исключения выводится в качестве части сообщения: в примере это типы <code>ZeroDivisionError</code>, <code>NameError</code> и <code>TypeError</code>. Часть строки, описывающая тип исключения — это имя произошедшего встроенного исключения. Такое утверждение верно для всех встроенных исключений, но не обязано быть истинным для исключений, определённых пользователем (однако, само соглашение — довольно полезное). Имена стандартных исключений — это встроенные идентификаторы (не ключевые слова). Оставшаяся часть строки описывает детали произошедшего на основе типа исключения, которое было его причиной. Предшествующая часть сообщения об ошибке показывает контекст, где произошло исключение, в форме стека вызовов. В общем случае она содержит стек, состоящий из списка строк исходного кода; тем не менее, в неё не войдут строки, прочитанные из стандартного ввода. В разделе [[Справочник по библиотеке Python 3.1#Встроенные исключения|Встроенные исключения]] [[Справочник по библиотеке Python 3.1|Справочника по библиотеке]] вы найдёте список встроенных исключений и их значений. === Обработка исключений === Существует возможность написать код, который будет перехватывать избранные исключения. Посмотрите на представленный пример, в котором пользователю предлагают вводить число до тех пор, пока оно не окажется корректным целым. Тем не менее, пользователь может прервать программу (используя сочетание клавиш <tt>Control-C</tt> или какое-либо другое, поддерживаемое операционной системой); заметьте — о вызванном пользователем прерывании сигнализирует исключение <code>KeyboardInterrupt</code>. <syntaxhighlight lang="python">>>> while True: ... try: ... x = int(input("Введите, пожалуйста, число: ")) ... break ... except ValueError: ... print("Ой! Это некорректное число. Попробуйте ещё раз...") ...</syntaxhighlight> Оператор <code>try</code> работает следующим образом: * В начале исполняется ''блок <code>try</code>'' (операторы между ключевыми словами <code>try</code> и <code>except</code>). * Если при этом не появляется исключений, ''блок <code>except</code>'' не выполняется и оператор <code>try</code> заканчивает работу. * Если во время выполнения блока <code>try</code> было возбуждено какое-либо исключение, оставшаяся часть блока не выполняется. Затем, если тип этого исключения совпадает с исключением, указанным после ключевого слова <code>except</code>, выполняется блок <code>except</code>, а по его завершению выполнение продолжается сразу после оператора <code>try-except</code>. * Если порождается исключение, не совпадающее по типу с указанным в блоке <code>except</code> — оно передаётся внешним операторам <code>try</code>; если ни одного обработчика не найдено, исключение считается ''необработанным'' (<tt>unhandled exception</tt>), и выполнение полностью останавливается и выводится сообщение, схожее с показанным выше. Оператор <code>try</code> может иметь более одного блока <code>except</code> — для описания обработчиков различных исключений. При этом будет выполнен максимум один обработчик. Обработчики ловят только те исключения, которые возникают внутри соответствующего блока <code>try</code>, но не те, которые возникают в других обработчиках этого же самого оператора <code>try-except</code>. Блок <code>except</code> может указывать несколько исключений в виде заключённого в скобки кортежа, например: <syntaxhighlight lang="python">... except (RuntimeError, TypeError, NameError): ... pass</syntaxhighlight> В последнем блоке <code>except</code> можно не указывать имени (или имён) исключений. Тогда он будет действовать как обработчик группы исключений. Используйте эту возможность с особой осторожностью, поскольку таким образом он может с лёгкостью перехватить и фактическую ошибку программиста! Также такой обработчик может быть использован для вывода сообщения об ошибке и порождения исключения заново (позволяя при этом обработать исключение коду, вызвавшему обработчик): <syntaxhighlight lang="python">import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except IOError as err: print("I/O error: {0}".format(err)) except ValueError: print("Не могу преобразовать данные в целое.") except: print("Неожиданная ошибка:", sys.exc_info()[0]) raise</syntaxhighlight> У оператора <code>try-except</code> есть необязательный ''блок <code>else</code>'', который, если присутствует, должен размещаться после всех блоков <code>except</code>. Его полезно использовать при наличии кода, который должен быть выполнен, если блок <code>try</code> не породил исключений. Например: <syntaxhighlight lang="python">for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print('не могу открыть', arg) else: print(arg, 'содержит', len(f.readlines()), 'строк') f.close()</syntaxhighlight> Использование блока <code>else</code> предпочтительнее, чем добавление дополнительного кода к блоку <code>try</code>, поскольку исключает неожиданный перехват исключения, которое появилось не по причине выполнения кода, защищенного оператором <code>try-except</code>. При появлении исключения, оно может иметь ассоциированное значение, также известное как ''аргумент'' (<tt>argument</tt>) исключения. Присутствие и тип аргумента зависят от типа самого исключения. В блоке <code>except</code> можно указать переменную, следующую за именем исключения. Переменная связывается с экземпляром исключения, аргументы которого хранятся в <code>instance.args</code>. Для удобства, экземпляр исключения определяет метод <code>__str__()</code>, так что вывод аргументов может быть произведён явно, без необходимости отсылки к <code>.args</code>. Таким образом, вы также можете создать/взять экземпляр исключения перед его порождением и добавить к нему атрибуты по желанию. <syntaxhighlight lang="python">>>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print(type(inst)) # экземпляр исключения ... print(inst.args) # аргументы хранятся в .args ... print(inst) # __str__ позволяет вывести args явно, ... # но может быть переопределён в подклассах исключения ... x, y = inst # распаковка args ... print 'x =', x ... print 'y =', y ... <class 'Exception'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs</syntaxhighlight> Если у исключения есть аргументы, они выводится в качестве последней («детальной») части сообщения о необработанном исключении. Обработчики исключений перехватывают не только исключения, появившиеся прямо в блоке <code>try</code>, но также и возбужденные внутри функций, которые были в блоке <code>try</code> вызваны (даже неявно). Например: <syntaxhighlight lang="python">>>> def this_fails(): ... x = 1/0 ... >>> try: ... this_fails() ... except ZeroDivisionError as err: ... print('Перехват ошибки времени исполнения:', err) ... Перехват ошибки времени исполнения: integer division or modulo by zero</syntaxhighlight> === Порождение исключений === Оператор <code>raise</code> позволяет программисту принудительно породить исключение. Например: <syntaxhighlight lang="python">>>> raise NameError('ПриветТам') Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: ПриветТам</syntaxhighlight> Единственный аргумент оператора <code>raise</code> определяет исключение, которое нужно возбудить. Им может быть либо экземпляр исключения, либо класс исключения (класс, дочерний к классу <code>Exception</code>). Если вам нужно определить, было ли возбуждено исключение, не перехватывая его — упрощённая форма оператора <code>raise</code> позволит возбудить исключение заново: <syntaxhighlight lang="python">>>> try: ... raise NameError('ПриветТам') ... except NameError: ... print('Исключение пролетело мимо!') ... raise ... Исключение пролетело мимо! Traceback (most recent call last): File "<stdin>", line 2, in ? NameError: ПриветТам</syntaxhighlight> === Исключения, определённые пользователем === В программах можно определять свои собственные исключения — посредством создания нового класса исключения. В общем случае, исключения должны быть унаследованы от класса <code>Exception</code>: явно или неявно. Например: <syntaxhighlight lang="python">>>> class MyError(Exception): ... def __init__(self, value): ... self.value = value ... def __str__(self): ... return repr(self.value) ... >>> try: ... raise MyError(2*2) ... except MyError as e: ... print('Поймано моё исключение со значением:', e.value) ... Поймано моё исключение со значением: 4 >>> raise MyError('ой!') Traceback (most recent call last): File "<stdin>", line 1, in ? __main__.MyError: 'ой!'</syntaxhighlight> В этом примере был перегружен конструктор по умолчанию <code>__init__()</code> класса <code>Exception</code>. Новое поведение отличается лишь созданием нового атрибута <code>value</code> и заменяет поведение по умолчанию, при котором создаётся атрибут <code>args</code>. Классы исключений могут определять любые действия, которые могут делать все другие классы. Однако, обычно их внутренняя структура довольно проста, и предоставляет лишь некоторые атрибуты, позволяющие обработчикам исключений выяснить информацию об ошибке подробно. При создании модуля, который может породить различные ошибки, обычной практикой будет создание базового класса для исключений, определённых в этом модуле, и подклассов для различных ошибочных состояний: <syntaxhighlight lang="python">class Error(Exception): """Базовый класс для всех исключений в этом модуле.""" pass class InputError(Error): """Исключение порождается при ошибках при вводе. Атрибуты: expression -- выражение на вводе, в котором обнаружена ошибка message -- описание ошибки """ def __init__(self, expression, message): self.expression = expression self.message = message class TransitionError(Error): """Порождается, когда операция пытается выполнить неразрешённый переход из одного состояния в другое. Attributes: previous -- состояние в начале перехода next -- новое состояние, попытка принять которое была принята message -- описание, по какой причине такой переход невозможен """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message</syntaxhighlight> Большинство исключений имеет имя, заканчивающееся на «<code>Error</code>», подобно стандартным исключениям. Много стандартных модулей определяют собственные исключения, сообщающие об ошибках, которые могут появиться в определяющих их модулях. Больше информации о классах представлено в главе 1.10, [[Учебник Python 3.1#Классы|Классы]] === Определение действий при подчистке === У оператора <code>try</code> есть другой необязательный блок, предназначенный для операций подчистки, которые нужно выполнить независимо от условий: <syntaxhighlight lang="python">>>> try: ... raise KeyboardInterrupt ... finally: ... print('Прощай, мир!') ... Прощай, мир! Traceback (most recent call last): File "<stdin>", line 2, in ? KeyboardInterrupt</syntaxhighlight> ''Блок <code>finally</code>'' исполняется всегда, когда интерпретатор покидает оператор <code>try</code>, независимо — были исключения или нет. Если в блоке <code>try</code> появилось исключение, которое не было обработано в блоке <code>except</code> (или появилось в самих блоках <code>except</code> или <code>else</code>) — оно порождается заново после выполнения блока <code>finally</code>. Также блок <code>finally</code> исполняется «по пути наружу», если какой-либо другой блок оператора <code>try</code> был покинут за счёт одного из операторов: <code>break</code>, <code>continue</code> или <code>return</code>. Более сложный пример: <syntaxhighlight lang="python">>>> def divide(x, y): ... try: ... result = x / y ... except ZeroDivisionError: ... print("деление на ноль!") ... else: ... print("результат: ", result) ... finally: ... print("выполнение блока finally") ... >>> divide(2, 1) результат: 2 выполнение блока finally >>> divide(2, 0) деление на ноль! выполнение блока finally >>> divide("2", "1") выполнение блока finally Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str'</syntaxhighlight> Как видите, блок <code>finally</code> выполняется при любом событии. Ошибка <code>TypeError</code> порождается при делении двух строк и не перехватывается блоком <code>except</code>, и поэтому порождается заново сразу после выполнения блока <code>finally</code>. В приложениях реального мира, блок <code>finally</code> применяется для освобождения внешних ресурсов (таких как файлы или сетевые соединения), независимо от того, было ли их использование удачным. === Предопределённые действия по подчистке === Некоторые объекты определяют стандартные действия при подчистке, применяемые если объект больше не нужен, независимо от того, удачна была операция использования объекта или нет. Посмотрите на следующий пример, в которым мы пытаемся открыть файл и вывести его содержимое на экран. <syntaxhighlight lang="python">for line in open("myfile.txt"): print(line)</syntaxhighlight> Проблема этого кода в том, что он оставляет файл открытым на неопределённое количество времени после выполнения данной части кода. В простых сценариях это не является проблемой, но может стать ей в больших приложениях. Оператор <code>with</code> позволяет использовать объекты (такие как, например, файлы) таким образом, чтобы вы всегда могли быть уверены в том, что ресурсы будут сразу и корректно очищены. <syntaxhighlight lang="python">with open("myfile.txt") as f: for line in f: print(line)</syntaxhighlight> После выполнения оператора, файл ''<code>f</code>'' всегда закрывается, даже если при прочтении строк обнаружилась проблема. В документации к объектам, которые поддерживают предопределённые действия по подчистке, таким как файлы, эта их способность будет явно указана. == Классы == За счёт механизма классов Python в язык с минимальным использованием нового синтаксиса и семантики добавляется возможность создания классов. Это смесь классовых механизмов, заимствованных из C++ и Modula-3. Как и в случае модулей, классы в Python не устанавливают абсолютного барьера между определением и программистом, рассчитывая больше на аккуратность и вежливость последнего — чтобы он не «врывался в определения». Наиболее важные возможности классов, тем не менее, содержат в себе всю возможную мощь: механизм наследования классов поддерживает несколько предков для класса, производный класс может переопределять любые методы своего предка или предков, а любой его метод может вызвать метод предка с таким же именем. Объекты могут содержать произвольное количество закрытых (<tt>private</tt>) данных. В терминологии C++, члены класса (включая данные-члены), обычно, открыты (<tt>public</tt>) (исключая [[Учебник Python 3.1#Приватные переменные|Приватные переменные]], описанные ниже), а все функции-члены — виртуальны. Нет специальных конструкторов и деструкторов. Как в Modula-3, нет краткой ссылки на члены объекта из его методов: функция-метод определяется с явным первым аргументом, описывающим объект, который неявно передаётся при вызове. Как в Smalltalk, классы сами по себе являются объектами, хотя и в более широком смысле: в Python все типы данных — объекты. Таким образом обеспечивается семантика для импортирования и переименования. В отличие от C++ и Modula-3 встроенные типы могут использоваться в качестве предков для расширения возможностей пользователем. Кроме того, как в C++, но не как в Modula-3, большинство встроенных операторов со специальным синтаксисом (арифметические операторы, индексирование и т. д.) могут быть переопределены для экземпляров классов. === Пара слов о терминологии === Обходя стороной поддерживаемую всем миром терминологию, применимую к разговорам о классах, в нашем случае я буду говорить в терминах C++ и Smalltalk. (Предпочёл бы использовать термины языка Modula-3, поскольку Python ближе к ней по объектно-ориентированной семантике, чем к C++, но предполагаю, что немногие читатели слышали о нём.) Объекты обладают индивидуальностью, и с одним объектом может быть связано несколько имён (в нескольких областях видимости). Такая практика в других языках известна как ''совмещение имён'' (<tt>aliasing</tt>). На первый взгляд, совмещение малозаметно в Python, и его можно без последствий игнорировать при работе с основными неизменяемыми типами (числами, строками, кортежами). Тем не менее, совмещение имён влияет на семантику программного кода Python, работающего с изменяемыми объектами: списками, словарями и большинством типов, описывающих сущности вне программы (файлы, окна и т. п.). Обычно такая практика считается полезной, поскольку псевдонимы работают подобно указателям и вероятно даже превосходят их возможности. Например, передача объекта — дешевая операция, поскольку по реализации передаётся только указатель. Если функция изменяет переданный в качестве аргумента объект, это будет заметно и в месте вызова. За счёт этого пропадает необходимость в двух различных механизмах передачи аргументов. === Области видимости и пространства имён в Python === Прежде чем заняться классами необходимо получить представление о правилах областей видимости в Python. Определения классов проделывают над пространствами имён некоторые ловкие трюки. Чтобы полностью понимать происходящее, нужно знать о принципах работы областей видимости и пространств имён. Эти знания не помешают любому профессиональному программисту на Python. Давайте начнём с нескольких определений. ''Пространство имён'' (<tt>namespace</tt>) — это набор связей имён с объектами<ref>''(Прим. перев.) A namespace is a mapping from names to objects {{ref-en}} — ''(букв.)'' пространство имён суть отображение имён на объекты''</ref>. В настоящий момент большинство пространств имён реализованы в виде словарей Python, но не стоит заострять на этом внимание (если только по поводу производительности): возможно, в будущем реализация изменится. Примеры пространств имён: набор встроенных имён (функции вроде <code>abs()</code> и имён встроенных исключений); глобальные имена в модуле; локальные имена при вызове функции. Важная вещь, которую необходимо знать о пространствах имён — это то, что нет абсолютно никакой связи между именами в разных пространствах имён: например, два разных модуля могут без проблем определять функцию «<code>maximize</code>», так как пользователи модулей будут использовать имена модулей в качестве префиксов. Кстати, слово ''атрибут'' (<tt>attribute</tt>) я применяю к любому имени, следующему за точкой. Например, в выражении <code>z.real</code>, <code>real</code> — это атрибут объекта <code>z</code>. Строго говоря, ссылки на имена в модуле являются ссылками на атрибуты: в выражении <code>''имя_модуля''.''имя_функции''</code> под ''имя_модуля'' скрывается объект модуля, а под ''имя_функции'' — его атрибут. В таком случае обнаруживается прямая связь между атрибутами модуля и глобальными именами, определёнными в модуле: они разделяют между собой одно и тоже пространство имён<ref>Исключая одну тонкость. У объектов модулей есть скрытый, только для чтения, атрибут под именем <code>__dict__</code>, возвращающий словарь, использовавшийся для формирования пространства имён модуля; имя <code>__dict__</code> является атрибутом, но не глобальным именем. Очевидно, что всё это нарушает абстракцию реализации пространства имён и его использование следует ограничить вещами вроде посмертных отладчиков</ref>. Запись в атрибуты может быть запрещена (''атрибут только для чтения'', <tt>read-only attribute</tt>) или разрешена (''перезаписываемый атрибут'', <tt>writable attribute</tt>). В последнем случае присваивание атрибуту является возможным. Атрибуты модуля перезаписываемы: вы можете написать «<code>modname.the_answer = 42</code>»<ref>''(Прим. перев.)'' Снова [[w:ru:Ответ на главный вопрос жизни, вселенной и всего такого|ответ на главный вопрос жизни, вселенной и всего такого]]</ref>. Перезаписываемые атрибуты могут также быть удалены оператором <code>del</code>. Например, код «<code>del modname.the_answer</code>» удалит атрибут <code>the_answer</code> из объекта с именем <code>modname</code>. Пространства имён создаются в различные моменты и имеют разное время жизни. Пространство имён, содержащее встроенные имена создаётся при запуске интерпретатора и не удаляется никогда. Глобальное пространство имён модуля создаётся при вычитке определения модуля. Обычно, пространства имён модулей также «живут» до выхода из интерпретатора. Выражения, выполняемые верхне-уровневым порождением интерпретатора, прочитанные из файла сценария или интерактивно, рассматриваются как часть модуля под названием <code>__main__</code>, поэтому у них есть своё собственное глобальное пространство имён. (Встроенные имена по факту также живут в модуле, он называется <code>builtins</code>). Локальное пространство имён функции создаётся при её вызове и удаляется когда функция возвращает значение либо порождает исключение, внутри неё не перехваченное. (На самом деле, лучшим способом объяснить, что происходит на самом деле, было бы «забывание»). Конечно же, рекурсивные порождения имеют свои пространства имён каждое. ''Область видимости'' (<tt>scope</tt>) — это текстовая область в программе на Python, из которой прямым образом доступно пространство имён. «Прямым образом доступно» подразумевает, что явная ссылка на имя вынуждает интерпретатор искать это имя в пространстве имён. Несмотря на то, что области видимости определяются статически, используются они динамически. В любой момент во время выполнения существует как минимум три вложенных области видимости, чьи пространства имён доступны прямым образом: самая внутренняя<ref>''(Прим. перев.)'' ''Innermost scope'', ''outermost scope'' {{ref-en}} — самая внутренняя и самая внешняя области видимости</ref> область видимости (по ней поиск осуществляется в первую очередь) содержит локальные имена; пространства имён всех объемлющих [данный код] функций, поиск по которым начинается с ближайшей объемлющей [код] области видимости; область видимости среднего уровня, по ней следующей проходит поиск и она содержит глобальные имена текущего модуля; и самая внешняя область видимости (заключительный поиск) — это пространство имён, содержащее встроенные имена. Если имя определено глобально, тогда все ссылки и присваивания уходят прямо в область видимости среднего уровня, содержащую глобальные имена модуля. Чтобы сменить привязку у всех переменных, найденных вне самой внутренней области видимости, можно использовать оператор <code>nonlocal</code>; если такая переменная не объявлена как <code>nonlocal</code>, то она используется только для чтения (попытка записать значение в такую переменную создаст новую локальную переменную в самой внутренней области видимости, оставляя идентично названную вовне переменную без изменений). Обычно локальная область видимости ссылается на локальные имена текущей (на уровне текста) функции. Вне функций локальная область видимости ссылается на то же пространство имён, что и глобальная область видимости: пространство имён модуля. Определения классов помещают в локальную область видимости ещё одно пространство имён. Важно осознавать, что области видимости ограничиваются на текстовом уровне: глобальная область видимости функции, определённая в модуле, является пространством имён этого модуля, независимо от того, откуда или по какому псевдониму была эта функция вызвана. С другой стороны, фактический поиск имён осуществляется динамически, во время выполнения. Как бы то ни было, язык развивается в сторону статического разрешения имён (во время компиляции), так что не стоит полагаться на динамическое разрешение имён. (Фактически, локальные переменные уже определены статично.) Особая хитрость в Python состоит в том, что — при условии, что в данной области не включены операторы <code>global</code> или <code>nonlocal</code> — присваивания именам всегда уходят в самую внутреннюю область видимости. Присваивания не копируют данных, а лишь связывают имена с объектами. Тоже самое верно и для удалений: оператор «<code>del x</code>» удаляет связь <code>x</code> из пространства имён, на которое ссылается локальная область видимости. В действительности, все операции, вводящие новые имена, используют локальную область видимости: в частности, операторы импорта и описаний функций связывают имя модуля или функции в локальной области видимости соответственно. (Для того, чтобы указать определённой переменной, что она должна быть расположена в глобальной области видимости, может использоваться оператор <code>global</code>.) Оператор <code>global</code> можно использовать для того, чтобы объявить определённые переменные как привязанные к глобальной области видимости и указывает, что их переназначения должны происходить в ней; оператор <code>nonlocal</code> помечает переменные как привязанные к окружающей их области видимости и указывает, что их переназначения должны происходить в ней. === Пример по областям видимости и пространствам имён === Приведём пример, показывающий, каким образом можно ссылаться на разные области видимости и пространства имён и как <code>global</code> и <code>nonlocal</code> влияют на привязку переменной. <syntaxhighlight lang="python">def scope_test(): def do_local(): spam = "локальный спам" def do_nonlocal(): nonlocal spam spam = "нелокальный спам" def do_global(): global spam spam = "глобальный спам" spam = "тестовый спам" do_local() print("После локального присваивания:", spam) do_nonlocal() print("После нелокального присваивания:", spam) do_global() print("После глобального присваивания:", spam) scope_test() print("В глобальной области видимости:", spam)</syntaxhighlight> Вывод кода из примера таков: <syntaxhighlight lang="text">После локального присваивания: тестовый спам После нелокального присваивания: нелокальный спам После глобального присваивания: нелокальный спам В глобальной области видимости: глобальный спам</syntaxhighlight> Заметьте, что локальное присваивание (работающее по умолчанию) не заменяет глобальную привязку на связывание из <code>scope_test</code>. Нелокальное присваивание заменило глобальную привязку на связывание из <code>scope_test</code>, а глобальное присваивание заменило привязку на связывание на уровне модуля. Можно увидеть, что до глобального присваивания у переменной <code>spam</code> не было предшествующих связываний. === Первый взгляд на классы === В описании классов представлено немного нового синтаксиса, три новых типа объектов<ref>''(Прим. перев.)'' ''Class Objects'', ''Instance Objects'', ''Method Objects'' {{ref-en}} — объекты классов, объекты экземпляров, объекты методов; по тексту перевода, хоть и могут восприниматься непривычно, используются термины «объекты-классы», «объекты-экземпляры» и «объекты-методы» — ввиду того, что словосочетание «объект класса» может обозначать и принадлежность объекта классу</ref> и некоторое количество новой семантики. ==== Синтаксис определения класса ==== Простейшая форма определения класса выглядит так: <syntaxhighlight lang="python">class ИмяКласса: <оператор-1> . . . <оператор-N> </syntaxhighlight> Определения классов, как и определения функций (операторы <code>def</code>), должны быть исполнены для того, чтобы определить действие. (Вы можете, предположим, поместить определение класса в ветку оператора <code>if</code> или внутрь функции.) На практике, внутри определения класса обычно помещаются определения функций, но позволено использовать и другие операторы — и иногда с пользой — как мы увидим позже. Определения функций внутри класса имеют особенную форму списка аргументов, в связи с соглашениями по вызову методов — опять же, это будет рассмотрено ниже. При вводе определения класса создаётся новое пространство имён, которое и используется в качестве локальной области видимости. Таким образом, все присваивания локальным переменным происходят в этом новом пространстве имён. В частности, определения функций связываются здесь с именами новых функций. При успешном окончании парсинга определения класса (по достижении конца определения), создаётся ''объект-класс'' (<tt>class object</tt>). По существу, это обёртка вокруг содержимого пространства имён, созданного во время определения класса; подробнее объекты классов мы изучим в следующем разделе. Оригинальная локальная область видимости (та, которая действовала в последний момент перед вводом определения класса) восстанавливается, а объект-класс тут же связывается в ней с именем класса, указанном в заголовке определения класса (в примере — ''<code>ИмяКласса</code>''). ==== Объекты-классы ==== Объекты-классы поддерживают два вида операций: ссылки на атрибуты и создание экземпляра. ''Ссылки на атрибуты'' (<tt>Attribute references</tt>) используют стандартный синтаксис, использующийся для всех ссылок на атрибуты в Python: <code>''объект''.''имя''</code>. Корректными именами атрибутов являются все имена, которые находились в пространстве имён класса при создании объекта-класса. Таким образом, если определение класса выглядело так: <syntaxhighlight lang="python">class MyClass: """Простой пример класса""" i = 12345 def f(self): return 'привет мир'</syntaxhighlight> то <code>MyClass.i</code> и <code>MyClass.f</code> являются корректными ссылками на атрибуты, возвращающими целое и ''объект-функцию'' (<tt>function object</tt>) соответственно. Атрибутам класса можно присваивать значение, так что вы можете изменить значение <code>MyClass.i</code> через присваивание. <code>__doc__</code> также является корректным атрибутом, возвращающим строку документации, принадлежащей классу: <code>"Простой пример класса"</code>. Создание экземпляра класса использует синтаксис вызова функции. Просто представьте, что объект-класс — это непараметризированная функция, которая возвращает новый экземпляр класса. Например (предполагая класс, приведённый выше): <syntaxhighlight lang="python">x = MyClass()</syntaxhighlight> создаёт новый экземпляр класса и присваивает этот объект локальной переменной <code>x</code>. Операция ''создания экземпляра'' (<tt>instantiation</tt>) создаёт объект данного класса. Большая часть классов предпочитает создавать экземпляры, имеющие определённое начальное состояние. Для этого класс может определять специальный метод под именем <code>__init__()</code>, например так: <syntaxhighlight lang="python">def __init__(self): self.data = []</syntaxhighlight> Когда в классе определён метод <code>__init__()</code>, при создании экземпляра автоматически вызывается <code>__init__()</code> нового, только что созданного объекта. Так, в этом примере, новый инициализированный экземпляр может быть получен за счёт выполнения кода: <syntaxhighlight lang="python">x = MyClass()</syntaxhighlight> Конечно же, для большей гибкости, метод <code>__init__()</code> может иметь параметры. В этом случае аргументы, переданные оператору создания экземпляра класса, передаются методу <code>__init__()</code>. Например, <syntaxhighlight lang="python">>>> class Complex: ... def __init__(self, realpart, imagpart): ... self.r = realpart ... self.i = imagpart ... >>> x = Complex(3.0, -4.5) >>> x.r, x.i (3.0, -4.5)</syntaxhighlight> ==== Объекты-экземпляры ==== Теперь, что же мы можем делать с объектами-экземплярами? Единственные операции, доступные объектам-экземплярам — это ссылки на атрибуты. Есть два типа корректных имён атрибутов — это атрибуты-данные и методы. ''Атрибуты-данные'' (<tt>data attributes</tt>) аналогичны «переменным экземпляров» в Smalltalk и «членам-данным» в C++. Атрибуты-данные не нужно описывать: как и переменные, они начинают существование в момент первого присваивания. Например, если <code>x</code> — экземпляр созданного выше <code>MyClass</code>, следующий отрывок кода выведет значение <code>16</code>, не вызвав ошибок: <syntaxhighlight lang="python">x.counter = 1 while x.counter < 10: x.counter = x.counter * 2 print(x.counter) del x.counter</syntaxhighlight> Другой тип ссылок на атрибуты экземпляра — это ''метод'' (<tt>method</tt>). Метод — это функция, «принадлежащая» объекту. (В Python термин не уникален для экземпляров класса: другие объекты также могут иметь методы. Например, объекты-списки имеют методы <code>append</code>, <code>insert</code>, <code>remove</code>, <code>sort</code> и т. п. Тем не менее, ниже под термином «метод» мы будем понимать только методы объектов-экземпляров классов, пока отдельно не будет указано иное.) Корректные имена методов объектов-экземпляров зависят от их класса. По определению, все атрибуты класса, являющиеся объектами-функциями, описывают соответствующие методы его экземпляров. Так, в нашем примере, <code>x.f</code> является корректной ссылкой на метод, а <code>x.i</code> ей не является, поскольку не является и <code>MyClass.i</code>. Но при этом <code>x.f</code> — это не то же самое, что <code>MyClass.f</code>: это объект-метод, а не объект-функция. ==== Объекты-методы ==== Обычно, метод вызывают сразу после его связывания [с функцией]: <syntaxhighlight lang="python">x.f()</syntaxhighlight> На примере <code>MyClass</code> такой код возвратит строку <code>'привет мир'</code>. Однако, не обязательно вызывать метод так уж сразу: <code>x.f</code> — это объект-метод, он может быть отложен и вызван когда-либо позже. Например: <syntaxhighlight lang="python">xf = x.f while True: print(xf())</syntaxhighlight> будет печатать <code>'привет мир'</code> до конца времён. Что конкретно происходит при вызове метода? Вы, возможно, заметили, что <code>x.f()</code> выше был вызван без аргументов, хотя в описании функции <code>f</code> аргумент был указан. Что же случилось с аргументом? Несомненно, Python порождает исключение когда функция, требующая присутствия аргумента, вызвана без единого — даже, если он на самом деле не используется… Теперь вы, возможно, догадались: отличительная особенность методов состоит в том, что в качестве первого аргумента функции передаётся объект. В нашем примере вызов <code>x.f()</code> полностью эквивалентен вызову <code>MyClass.f(x)</code>. В общем случае, вызов метода со списком из ''n'' аргументов эквивалентен вызову соответствующей функции со списком аргументов, созданным за счёт вставки объекта, вызвавшего метод, перед первым аргументом. Если вы всё ещё не поняли, как работают методы, взгляд на реализацию возможно прояснит происходящее. Когда атрибут экземпляра ссылается на что-либо, не являющееся атрибутом-данными, производится поиск по классу. Если имя указывает корректный атрибут класса, являющийся объектом-функцией, создаётся метод: через упаковку (указателя на) объекта-экземпляра и найденного объекта-функции в абстрактный объект, получается объект-метод. Когда объект-метод вызывается со списком аргументов, он снова распаковывается и новый список аргументов конструируется из объекта-экземпляра и оригинального списка аргументов, и затем уже с новым списком аргументов вызывается объект-функция. === Различные замечания === Атрибуты-данные переопределяют атрибуты-методы с тем же именем; для того, что обезопасить себя от случайных конфликтов имён, которые могут привести к трудно-обнаруживаемым ошибкам в больших программах, разумно использовать какое-нибудь соглашение, которое могло бы уменьшить шансы возникновения конфликтов. Возможные соглашения включают в себя: написание имён методов строчными буквами, предварение имени атрибутов-данных некоторой короткой уникальной строкой (предположим, лишь символом подчёркивания («<code>_</code>»)), или использование глаголов для именования методов и существительных для именования данных. Методы могут ссылаться на атрибуты-данные также как и обычные пользователи («клиенты») объекта. Другими словами, классы не подходят для разработки чистых абстрактных типов данных. Фактически же в Python нет ничего, вынуждающего вас скрывать данные: сокрытие основано на соглашении между программистами. (С другой стороны, реализация Python, написанная на C, может полностью скрывать детали разработки и, если нужно, контролировать доступ к объекту, это можно делать в расширениях для Python, написанных на C.) Клиенты должны использовать атрибуты-данные с осторожностью, так как иначе они могут нарушить инварианты, подразумеваемые методами класса при использовании атрибутов-данных. Заметьте, что обычно клиенты могут добавлять собственные атрибуты-данные к объектам-экземплярам, не нарушая работы методов, если не происходит конфликтов имён. Опять же, соглашение об именовании может избавить вас от головной боли и в этих случаях. ''(Прим. перев.)'' Автором здесь не упомянут механизм свойств (<tt>property</tt>). Свойство синтаксически является атрибутом-данным, но за кулисами с ним могут быть связаны отдельные методы для чтения, записи и удаления. Документация к функции-декоратору <code>property</code> хорошо проясняет суть дела: <syntaxhighlight lang="python">>>> print(property.__doc__) property(fget=None, fset=None, fdel=None, doc=None) -> property attribute fget - функция для чтения, fset - для записи, fdel - для удаления атрибута. Типичный пример использования для управляемого атрибута x: class C(object): def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "Я - свойство 'x'.") Декораторы упрощают определение новых свойств и изменение существующих: class C(object): @property def x(self): return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x </syntaxhighlight> ''(Конец прим.)'' У методов нет краткой записи для ссылок изнутри на атрибуты-данные (и другие методы!). Я нахожу, что это и вправду повышает читабельность методов: нет шанса спутать локальные переменные и переменные экземпляров при просмотре тела метода. Обычно, первый аргумент метода называется <code>self</code>. Это не более чем соглашение: имя <code>self</code> не имеет абсолютно никакого специального смысла для языка Python. (Однако, обратите внимание, что если вы не следуете соглашениям, ваш код может стать менее читабелен для других программистов; и также, потенциально, программа навигации по классам может опираться на такие соглашения.) Любой объект-функция, являющийся атрибутом класса, определяет метод для экземпляров этого класса. Не так важно, чтобы текст определения функции был заключен в определение класса: присваивание объекта-функции локальной переменной класса также работает неплохо. Например: <syntaxhighlight lang="python"># Функция, определённая вне класса def f1(self, x, y): return min(x, x+y) class C: f = f1 def g(self): return 'привет мир' h = g</syntaxhighlight> Теперь <code>f</code>, <code>g</code> и <code>h</code> — все являются атрибутами класса <code>C</code>, ссылающимися на объекты-функции, и следовательно, все они являются методами экземпляров <code>C</code> — <code>h</code> становится полностью эквивалентен <code>g</code>. Заметьте, что такая практика обычно лишь запутывает читателя программы. Методы могут вызывать другие методы за счёт использования атрибутов-методов аргумента <code>self</code>: <syntaxhighlight lang="python">class Bag: def __init__(self): self.data = [] def add(self, x): self.data.append(x) def addtwice(self, x): self.add(x) self.add(x)</syntaxhighlight> Методы могут ссылаться на глобальные имена таким же образом, как и обычные функции. Глобальная область видимости, связанная с методом — это модуль, содержащий определение класса. (Сам класс никогда не используется в качестве глобальной области видимости!) В то время, как одни редко находят причины для использования глобальных данных в методах, существует множество разумных причин использовать глобальную область видимости: для примера, функции и модули, импортированные в глобальную область видимости, могут использоваться в методах так же, как в функциях и классах, в ней определённых. Обычно класс, содержащий метод, сам определён в этой глобальной области видимости, и в следующем разделе мы найдём пару хороших причин, почему методу может быть необходимо ссылаться на собственный класс! === Наследование === Конечно же, не поддерживай «класс» наследование, не стоило бы называть его «классом». Синтаксис производного класса выглядит так: <syntaxhighlight lang="python">class ИмяПроизводногоКласса(ИмяБазовогоКласса): <оператор-1> . . . <оператор-N></syntaxhighlight> Имя ''<code>ИмяБазовогоКласса</code>'' должно быть определено в области видимости, содержащей определение производного класса. Вместо имени базового класса также позволяется использовать другие выражения. Это может быть полезно, например, когда базовый класс определён в другом модуле: <syntaxhighlight lang="python">class ИмяПроизводногоКласса(имямодуля.ИмяБазовогоКласса):</syntaxhighlight> Использование определения производного класса проходит таким же образом, как и базового. Базовый класс полностью сохраняется по завершению конструирования объекта-класса. Такой метод используется для разрешения ссылок на атрибуты<ref>''(Прим. перев.)'' ''Resolving attribute references'' {ref-en} — разрешение (поиск значений) ссылок на атрибуты</ref>: если запрошенный атрибут не был найден в самом классе, поиск продолжается в базовом классе. Правило применяется рекурсивно, если базовый класс сам является производным от некоторого другого класса. В создании экземпляров производных классов нет ничего особенного: <code>ИмяПроизводногоКласса()</code> создаёт новый экземпляр класса. Ссылки на методы разрешаются следующим образом: производится поиск соответствующего атрибута класса (спускаясь вниз по цепочке базовых классов, если необходимо) и ссылка на метод считается корректной, если она порождает объект-функцию. Производные классы могут перегружать методы своих базовых классов. Поскольку у методов нет особых привилегий при вызове других методов того же объекта, метод базового класса, вызывающий другой метод, определённый в этом же классе, может вызвать перегруженный метод производного класса. (Для программистов на C++: все методы в Python фактически виртуальны.) При перегрузке метода в производном классе возможна не только замена действия метода базового класса с тем же именем, но и его расширение. Существует простой способ вызвать метод базового класса прямым образом: просто вызовите «<code>ИмяБазовогоКласса.имяметода(self, аргументы)</code>». Такой способ будет неожиданно полезным и для клиентов. (Обратите внимание, что он работает только если базовый класс определён и импортирован прямо в глобальную область видимости.) В языке Python есть функции, которые работают с наследованием: * Используйте <code>isinstance()</code> чтобы проверить тип объекта: <code>isinstance(obj, int)</code> возвратит <code>True</code> только если <code>obj.__class__</code> является <code>int</code> или некоторым классом, наследованным от <code>int</code>. * Используйте <code>issubclass()</code> чтобы проверить наследственность класса: <code>issubclass(bool, int)</code> возвратит <code>True</code>, поскольку класс <code>bool</code> является наследником (<tt>subclass</tt>) <code>int</code>. Однако, <code>issubclass(float, int)</code> возвратит <code>False</code>, поскольку класс <code>float</code> не является наследником <code>int</code>. ==== Множественное наследование ==== Python также поддерживает форму ''множественного наследования'' (<tt>multiple inheritance</tt>). Определение класса с несколькими базовыми классами будет выглядеть так: <syntaxhighlight lang="python">class ИмяПроизводногоКласса(Базовый1, Базовый2, Базовый3): <оператор-1> . . . <оператор-N></syntaxhighlight> В простейших случаях и для большинства задач, вы можете представлять себе поиск атрибутов, наследованных от родительского класса в виде «сперва вглубь», затем «слева-направо». Таким образом, если атрибут не найден в ''<code>ИмяПроизводногоКласса</code>'', его поиск выполняется в ''<code>Базовом1</code>'', затем (рекурсивно) в базовых классах ''<code>Базового1</code>'' и только если он там не найден, поиск перейдёт в ''<code>Базовый2</code>'' и так далее. На самом деле всё немного сложнее. Порядок разрешения методов<ref>''(Прим. перев.)'' другими словами — поиска корректной привязки для метода</ref> (<tt>method resolution order</tt>) меняется динамически, чтобы обеспечить возможность сотрудничающих вызовов <code>super()</code>. Этот способ известен в некоторых других языках с поддержкой множественного наследования как «вызов-следующего-метода» («<tt>call-next-method</tt>») и имеет больше возможностей, чем вызов родительского метода в языках с единичным наследованием. Динамическое упорядочивание (<tt>dynamic ordering</tt>) имеет важность, поскольку все вариации множественного наследования проявляют в себе эффект ромбовых отношений (когда как минимум один родительский класс может быть доступен различными путями из низшего в иерархии класса). Например, все классы наследуются от <code>object</code>, так что множественное наследование в любом виде предоставляет более одного пути для того, чтобы достичь <code>object</code>. Чтобы защитить базовые классы от двойных и более запросов, динамический алгоритм «выпрямляет» (<tt>linearizes</tt>) порядок поиска таким образом, что тот сохраняет указанный слева-направо порядок для каждого класса, который вызывает каждый родительский класс только единожды и является монотонным (значит, класс можно сделать наследником, не взаимодействуя с порядком предшествования его родителей). Обобщённые вместе, эти свойства позволяют разрабатывать надёжные и расширяемые классы, используя множественное наследование. С подробностями можно ознакомиться по этой ссылке: http://www.python.org/download/releases/2.3/mro/ ([[Python — Порядок разрешения методов|перевод]]). === Приватные переменные === В Python имеется ограниченная поддержка идентификаторов, приватных для класса. Любой идентификатор в форме <code>__spam</code> (как минимум два предшествующих символа подчёркивания, как максимум один завершающий) заменяется дословно на <code>_classname__spam</code>, где <code>classname</code> — текущее имя класса, лишённое предшествующих символов подчёркивания. Это ''искажение'' (<tt>mangling</tt>) производится без оглядки на синтаксическую позицию идентификатора, поэтому может использоваться для определения переменных, приватных для класса экземпляров, переменных класса, методов, переменных в глобальной области видимости (<tt>globals</tt>), и даже переменных, использующихся в экземплярах, приватных для этого класса на основе экземпляров ''других'' классов. Имя может быть обрезано, если его длина превышает 255 символов. Вне классов, или когда имя состоит из одних символов подчёркивания, искажения не происходит. Предназначение искажения имён состоит в том, чтобы дать классам лёгкую возможность определить «приватные» переменные экземпляров и методы, не беспокоясь о переменных экземпляров, определённых в производных классах, и о забивании кодом вне класса переменных экземпляров. Обратите внимание, что правила искажения имён разработаны, в основном, чтобы исключить неприятные случайности — решительная душа всё ещё может получить доступ или изменить переменные, предполагавшиеся приватными. В некотором особом окружении, таком как отладчик, это может оказаться полезным — и это единственная причина, по которой лазейка не закрыта. (Внимание: наследование класса с таким же именем как и у базового делает возможным использование приватных переменных базового класса.) Заметьте, что код, переданный в <code>exec()</code> или <code>eval()</code>, не предполагает в качестве текущего имени класса имя класса, порождающего вызов — так же, как и в случае эффекта с оператором <code>global</code> — эффекта, который также ограничен для всего побайтно-компилирующегося кода. И, такое же ограничение применимо для функций <code>getattr()</code>, <code>setattr()</code> и <code>delattr()</code>, и также для прямой ссылки на <code>__dict__</code>. === Всякая всячина === Иногда бывает полезен тип данных, похожий на <code>record</code> из языка Pascal или <code>struct</code> из языка C, например, для хранения нескольких поименованных элементов данных. Для этой цели подойдет даже пустое определение класса<ref>''(Прим. перев.)'':<syntaxhighlight lang="python">class Рабочий: pass джон = Рабочий() # Создать пустую запись о рабочем # Заполнить поля записи джон.имя = 'Джон До' джон.отдел = 'компьютерная лаборатория' джон.зарплата = 1000</syntaxhighlight></ref>: <syntaxhighlight lang="python">class Employee: pass john = Employee() # Создать пустую запись о рабочем # Заполнить поля записи john.name = 'John Doe' john.dept = 'computer lab' john.salary = 1000</syntaxhighlight> Фрагменту кода на Python, требующему на входе некоторого абстрактного типа данных, можно дать экземпляр, эмулирующий методы этого типа данных. Например, если имеется функция, умеющая форматировать данные из файлового объекта, то можно определить класс с методами <code>read()</code> и <code>readline()</code> (работающие с данными, скажем, из строкового буфера) и передать ей экземпляр этого класса в качестве аргумента. Объекты-методы экземпляров также имеют атрибуты: <code>m.__self__</code> — исходный объект-экземпляр с методом <code>m()</code>, а <code>m.__func__</code> — объект-функция, соответствующий методу. === Исключения — тоже классы === Исключения, определённые пользователем, могут быть также отождествлены с классами. При использовании этого механизма становится возможным создавать расширяемые иерархии исключений. Оператор <code>raise</code> имеет следующие (синтаксически) правильные формы: <syntaxhighlight lang="python">raise Класс raise Экземпляр</syntaxhighlight> В первой форме, ''<code>Класс</code>'' должен быть экземпляром типа или класса, производного от него. Первая форма является краткой записью следующего кода: <syntaxhighlight lang="python">raise Class()</syntaxhighlight> Класс в блоке <code>except</code> является сопоставимым с исключением, если является этим же классом или самим по себе базовым классом (никаких других способов обхода — описанный в блоке <code>except</code> производный класс не сопоставим с базовым). Например, следующий код выведет B, C, D в этом порядке: <syntaxhighlight lang="python">class B(Exception): pass class C(B): pass class D(C): pass for c in [B, C, D]: try: raise c() except D: print("D") except C: print("C") except B: print("B")</syntaxhighlight> Обратите внимание, что если бы блоки <code>except</code> шли в обратном порядке (начиная с «<code>except B</code>»), код вывел бы B, B, B — сработал бы первый совпадающий блок <code>except</code>. При выводе сообщения об ошибке о необработанном исключении, выводится класс исключения, затем двоеточие и пробел, и наконец экземпляр, приведённый к строке за счёт встроенной функции <code>str()</code>. === Итераторы === К этому моменту вы, возможно, заметили, что используя оператор <code>for</code> можно организовать цикл по большинству объектов-контейнеров: <syntaxhighlight lang="python">for element in [1, 2, 3]: print(element) for element in (1, 2, 3): print(element) for key in {'один':1, 'два':2}: print(key) for char in "123": print(char) for line in open("myfile.txt"): print(line)</syntaxhighlight> Такой стиль доступа к элементам прост, лаконичен и удобен. Использованием ''итераторов'' (<tt>iterators</tt>) пропитан язык Python, и это его выделяет среди других. Негласно, оператор <code>for</code> вызывает метод <code>iter()</code> объекта-контейнера. Функция возвращает объект итератора, который определяет метод <code>__next__()</code>, который по очереди получает доступ к элементам в контейнере, по одному за раз. Если больше не остаётся элементов, метод <code>__next__()</code> порождает исключение <code>StopIteration</code>, которое сообщает оператору <code>for</code> о необходимости завершения прохода. Вы можете вызывать метод <code>__next__()</code> посредством встроенной функции <code>next()</code>; следующий пример показывает, как это работает: <syntaxhighlight lang="python">>>> s = 'абв' >>> it = iter(s) >>> it <iterator object at 0x00A1DB50> >>> next(it) 'а' >>> next(it) 'б' >>> next(it) 'в' >>> next(it) Traceback (most recent call last): File "<stdin>", line 1, in ? next(it) StopIteration</syntaxhighlight> Ознакомившись с механизмами, скрытыми за протоколом итераторов, легко добавить возможность итерирования к вашим классам. Определите метод <code>__iter__()</code>, который возвращает объект с методом <code>next()</code>. Если класс определяет и метод <code>next()</code>, тогда <code>__iter__()</code> может просто возвращать <code>self</code>. <syntaxhighlight lang="python">class Reverse: "Итератор по последовательности в обратном направлении" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def __next__(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index] >>> for char in Reverse('спам'): ... print(char) ... м а п с</syntaxhighlight> === Генераторы === ''Генераторы'' (<tt>generators</tt>) — простой и мощный инструмент для создания итераторов. Они записываются как обычная функция, но где бы им ни было необходимо вернуть данные, используется оператор <code>yield</code>. Каждый раз, когда над ним вызывается <code>__next__()</code>, генератор возвращается к месту, где он был оставлен (он запоминает все значения данных, а также какой оператор был выполнен последним). Пример показывает, что создание генераторов может быть тривиально простым: <syntaxhighlight lang="python">def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] >>> for char in reverse('гольф'): ... print(char) ... ф ь л о г</syntaxhighlight> Всё, что можно сделать с использованием генераторов, может быть сделано с использованием основанных на итераторах классов, как описано в предыдущем разделе. Благодаря автоматическому созданию методов <code>__iter__()</code> и <code>next()</code> генераторы так компактны. Другая важная особенность состоит в том, что между вызовами сохраняются локальные переменные и ''состояние выполнения'' (<tt>execution state</tt>). Это позволяет конструкциям функций быть проще, а получению переменных экземпляров быть намного легче, нежели с использованием <code>self.index</code> и <code>self.data</code>. В дополнение к автоматическому созданию методов и сохранению состояния, когда генераторы заканчивают своё действие, они автоматически порождают исключение <code>StopIteration</code>. В комбинации, эти особенности позволяют легко создавать итераторы не прилагая усилий больших, чем нужно для написания обычной функции. === Выражения-генераторы === Некоторые простые генераторы могут быть сжато закодированы в выражении с использованием синтаксиса, схожего со ''списковыми сборками'', но с круглыми скобками вместо квадратных. Выражения-генераторы разработаны в основном для случаев, когда генератор тут же используется в качестве аргумента функции. Выражения с генераторами более компактные, но менее гибкие чем полные определения генераторов и обычно используют память экономнее, чем эквивалентные ''списковые сборки''. Примеры<ref>''(Прим. перев.)'':<br /> <br /> <code>>>> ''сумма''(i*i '''для''' i '''в''' ''диапазон''(10)) # сумма квадратов<br/> 285<br/> <br/> >>> вектор_а = [10, 20, 30]<br/> >>> вектор_б = [7, 5, 3]<br/> >>> ''сумма''(x*y '''для''' x,y '''в''' ''зип''(вектор_а, вектор_б)) # скалярное произведение<br/> 260<br/> <br/> >>> '''из''' матем '''импорт''' пи, ''синус''<br/> >>> таблица_синусов = {x: ''синус''(x*пи/180)) '''для''' x '''в''' ''диапазон''(0, 91)}<br/> <br/> >>> уникальные_слова = ''набор''(слово&nbsp;&nbsp;'''для''' строка '''в''' страница&nbsp;&nbsp;'''для''' слово '''в''' строка.''разбить''())<br/> <br/> >>> выпускники = ''макс''((студент.ср_балл, студент.имя) '''для''' студент '''в''' окончившие)<br/> <br/> >>> данные = 'гольф'<br/> >>> ''список''(данные[i] '''для''' i '''в''' ''диапазон''(''длина''(данные)-1, -1, -1))<br/> ['ф', 'ь', 'л', 'о', 'г']</code></ref>: <syntaxhighlight lang="python">>>> sum(i*i for i in range(10)) # сумма квадратов 285 >>> xvec = [10, 20, 30] >>> yvec = [7, 5, 3] >>> sum(x*y for x,y in zip(xvec, yvec)) # скалярное произведение 260 >>> from math import sin, radians >>> sine_table = {x: sin(radians(x)) for x in range(0, 91)} >>> unique_words = set(word for line in page for word in line.split()) >>> valedictorian = max((student.gpa, student.name) for student in graduates) >>> data = 'golf' >>> list(data[i] for i in range(len(data)-1, -1, -1)) ['f', 'l', 'o', 'g']</syntaxhighlight> == Краткий обзор стандартной библиотеки == === Взаимодействие с операционной системой === Модуль <tt>os</tt> предоставляет десятки функций для взаимодействия с операционной системой. <syntaxhighlight lang="python">>>> import os >>> os.getcwd() # возвращает путь к текущему каталогу 'C:\\Python31' >>> os.system('dir *.txt') # выполнить указанную команду ОС ...список текстовых файлов, выведенных командой... 0 >>> os.chdir('/server/accesslogs') # сменить текущий каталог </syntaxhighlight> Лучше всего применять <code>import os</code> вместо <code>from os import *</code>. Это предохранит встроенную функцию <code>open()</code> от замещения функцией <code>os.open()</code>, имеющей несколько иное назначение. В интерактивном режиме встроенные функции <code>dir()</code> и <code>help()</code> помогут разобраться с большими модулями вроде <tt>os</tt>: <syntaxhighlight lang="python">>>> import os >>> dir(os) ...список всех атрибутов модуля... >>> help(os) ...страница руководства по модулю на основе строк документации... </syntaxhighlight> Для управления файлами и каталогами удобный высокоуровневый интерфейс предоставляет модуль <tt>shutil</tt>: <syntaxhighlight lang="python">>>> import shutil >>> shutil.copyfile('data.db', 'archive.db') # копировать файл >>> shutil.move('/build/executables', 'installdir') # переместить каталог </syntaxhighlight> === Wildcard-шаблоны для имён файлов === Модуль <tt>glob</tt> предоставляет функцию для получения списка файлов на основе заданного шаблона: <syntaxhighlight lang="python">>>> import glob >>> glob.glob('*.py') ['primes.py', 'random.py', 'quote.py'] </syntaxhighlight> === Аргументы командной строки === Сценарии общего назначения часто нуждаются в аргументах командной строки. Эти аргументы хранятся в атрибуте <tt>argv</tt> модуля <tt>sys</tt> в виде списка. Например, при запуске <code>python demo.py one two three</code> в командной строке шелла для сценария <tt>demo.py</tt>: <syntaxhighlight lang="python">import sys print(sys.argv) </syntaxhighlight> будет выведено <code>['demo.py', 'one', 'two', 'three']</code>. Модуль <tt>getopt</tt> обрабатывает <code>sys.argv</code>, используя соглашения функции <code>getopt()</code> системы Unix. Более мощную и гибкую обработку аргументов командной строки осуществляет модуль <tt>optparse</tt>. === Стандартный вывод. Завершение сценария === Модуль <tt>sys</tt> имеет атрибуты <code>stdin</code>, <code>stdout</code> и <code>stderr</code> (для стандартного ввода, вывода и вывода ошибок соответственно). Последний может быть полезен для вывода предупреждений и сообщений об ошибках когда стандартный вывод перенаправлен<ref>''(Прим. перев.)'' разумеется, если стандартный вывод ошибок перенаправлен не был</ref>: <syntaxhighlight lang="python">>>> sys.stderr.write('Внимание! Файл журнала не найден.\n') Внимание! Файл журнала не найден. 34 </syntaxhighlight> Для завершения сценария можно использовать <code>sys.exit()</code>. === Сравнение строк по шаблонам === Модуль <tt>re</tt> предоставляет инструментарий для работы с регулярными выражениями для нетривиальной обработки текста. С помощью регулярных выражений можно создавать выразительные и оптимизированные решения для поиска и обработки строк. <syntaxhighlight lang="python">>>> import re >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') ['foot', 'fell', 'fastest'] >>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat') 'cat in the hat' </syntaxhighlight> Когда требуются более простые возможности, методы строковых объектов предпочтительнее, так как их легче читать и отлаживать: <syntaxhighlight lang="python">>>> 'чай для двоих'.replace('для', 'на') 'чай на двоих' </syntaxhighlight> === Математические функции === Модуль <tt>math</tt> предоставляет доступ к библиотеке языка C для функций над числами с плавающей запятой: <syntaxhighlight lang="python">>>> import math >>> math.cos(math.pi / 4) 0.70710678118654757 >>> math.log(1024, 2) 10.0 </syntaxhighlight> С помощью модуля <tt>random</tt> можно делать случайный выбор: <syntaxhighlight lang="python">>>> import random >>> random.choice(['яблоко', 'груша', 'банан']) 'яблоко' >>> random.sample(range(100), 10) # выборка без повторений [30, 83, 16, 4, 8, 81, 41, 50, 18, 33] >>> random.random() # случайное число с плавающей запятой 0.17970987693706186 >>> random.randrange(6) # случайное целое из диапазона range(6) 4 >>> random.sample([1, 2, 3, 4, 5], 3) # случайные три элемента из списка [4, 1, 5] </syntaxhighlight> Проект SciPy <http://scipy.org> имеет много других модулей для численных расчётов. === Протоколы интернет === В стандартной библиотеке имеется целый набор модулей для различных сервисов и протоколов интернет. Наиболее употребимыми можно считать <code>urllib.request</code> для получения данных по заданному адресу (URL) и <code>smtplib</code> для отправки сообщений электронной почты: <syntaxhighlight lang="python">>>> from urllib.request import urlopen >>> for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'): ... if 'EST' in line or 'EDT' in line: # временные зоны ... print(line) <BR>Nov. 25, 09:43:32 PM EST >>> import smtplib >>> server = smtplib.SMTP('localhost') >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org', ... """To: jcaesar@example.org ... From: soothsayer@example.org ... ... Beware the Ides of March. ... """) >>> server.quit() </syntaxhighlight> Заметьте, что второй пример требует почтового сервера на той же машине. === Дата и время === Модуль <code>datetime</code> предлагает классы для работы с датами и временем как в простых, так и сложных случаях. Кроме поддержки календарной арифметики, реализация обращает особенное внимание на эффективность вычисления составных частей для вывода и дальнейших манипуляций. Модуль также предлагает объекты с поддержкой временных зон. <syntaxhighlight lang="python"># даты можно легко составлять и выводить в требуемом формате >>> from datetime import date >>> now = date.today() >>> now datetime.date(2009, 2, 3) >>> now.strftime("%d.%m.%Y") '03.02.2009' # даты поддерживают календарную арифметику >>> birthday = date(1964, 7, 31) >>> age = now - birthday >>> age.days 16258 </syntaxhighlight> === Сжатие данных и архивы === Наиболее распространённые форматы сжатия и архивации напрямую поддерживаются модулями стандартной библиотеки: <tt>zlib</tt>, <tt>gzip</tt>, <tt>bz2</tt>, <tt>zipfile</tt> и <tt>tarfile</tt>. <syntaxhighlight lang="python">>>> import zlib >>> s = "Закрой замок на замок, чтобы замок не замок" >>> len(bytes(s, "utf-8")) 78 >>> t = zlib.compress(s) >>> len(t) 54 >>> print(str(zlib.decompress(t), "utf-8")) Закрой замок на замок, чтобы замок не замок >>> zlib.crc32(s) 2392363341 </syntaxhighlight> === Измерение производительности === Некоторым пользователям Python интересно знать относительную производительность различных подходов к решению одной и той же проблемы. Python предлагает инструмент для немедленного ответа на эти вопросы. Например, очень заманчиво использовать присваивание кортежей вместо традиционного подхода к замене значений переменных местами. Модуль <code>timeit</code> быстро продемонстрирует незначительное превосходство кортежей: <syntaxhighlight lang="python">>>> from timeit import Timer >>> Timer('a, b = b, a', 'a=1; b=2').timeit() 0.15707302093505859 >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit() 0.19421601295471191 </syntaxhighlight> В отличие от высокого разрешения модуля <code>timeit</code>, модули <code>profile</code> и <code>pstats</code> предлагают возможность обнаружить критические по времени участки в больших фрагментах кода. === Контроль качества === Один из подходов к разработке высококачественного программного обеспечения заключается в написании тестов для каждой функции при её разработке и регулярном запуске этих тестов во время всего процесса разработки. Модуль <code>doctest</code> имеет средства для просмотра модуля и проверки результатов тестов, заложенных в строках документации. Написание теста для функции заключается в копировании и вставке типичного вызова функции и ее результатов в строку документации. Это улучшает документацию, предоставляя пользователю реальный пример, а модуль <code>doctest</code> проверяет, что код соответствует документации. <syntaxhighlight lang="python">def average(values): """Вычисляет среднее арифметическое списка чисел. >>> print(average([20, 30, 70])) 40.0 """ return sum(values) / len(values) import doctest doctest.testmod() # автоматически проверяет тесты в документации </syntaxhighlight> Модуль <code>unittest</code> не менее прост в использовании чем <code>doctest</code>, но позволяет создавать более полный набор тестов, располагающийся в отдельном файле: <syntaxhighlight lang="python">import unittest class TestStatisticalFunctions(unittest.TestCase): def test_average(self): self.assertEqual(average([20, 30, 70]), 40.0) self.assertEqual(round(average([1, 5, 7]), 1), 4.3) self.assertRaises(ZeroDivisionError, average, []) self.assertRaises(TypeError, average, 20, 30, 70) unittest.main() # Вызов из командной строки выполняет проверку всех тестов этого модуля </syntaxhighlight> === «Батарейки в комплекте» === Python руководствуется философией «батарейки в комплекте». Это можно проследить по сложным и устойчивым к ошибкам возможностям его пакетов побольше. Примеры: * Модули <code>xmlrpc.client</code> и <code>xmlrpc.server</code> делают реализацию удалённых вызовов почти тривиальной задачей. Несмотря на названия, знания об обработке XML не требуются. * Пакет <code>email</code> — это библиотека для работы с сообщениями электронной почты, включая MIME и другие основанные на {{RFC|2822}} документы-сообщения. В отличие от <code>smtplib</code> и <code>poplib</code>, которые занимаются непосредственно отправкой и приёмом сообщений, пакет <code>email</code> является полным набором инструментов для построения и декодирования сообщений сложной структуры (включая вложения) и для реализации интернетного кодирования и протокола заголовков. * Пакеты <code>xml.dom</code> и <code>xml.sax</code> предоставляют ошибко-устойчивую поддержку парсинга XML — этого популярного формата для обмена данными. Аналогично, модуль <code>csv</code> поддерживает чтение и запись в распространённом формате баз данных. Вместе эти модули серьёзно облегчают обмен данными между приложениями на Python и другими приложениями. * Интернационализация поддерживается благодаря ряду модулей, включая <code>gettext</code>, <code>locale</code> и пакет <code>codecs</code>. == Второй краткий обзор стандартной библиотеки == === Форматирование вывода === Модуль <code>reprlib</code> предоставляет версию функции <code>repr()</code>, настроенную на сокращённый вывод больших и многократно вложенных контейнеров: <syntaxhighlight lang="python">>>> import reprlib >>> reprlib.repr(set('supercalifragilisticexpialidocious')) "set(['a', 'c', 'd', 'e', 'f', 'g', ...])" </syntaxhighlight> Модуль <code>pprint</code> предлагает более утончённый контроль над выводом встроенных и определённых пользователем объектов способом, подходящим для интерпретатора. Когда результат не умещается на строке, умный <code>pprint</code> добавляет по необходимости разбивку на строки и отступы, помогающие выделить структуру данных: <syntaxhighlight lang="python">>>> import pprint >>> t = [[[['чёрный', 'бирюзовый'], 'белый', ['зелёный', 'красный']], [['пурпурный', 'жёлтый'], 'голубой']]] >>> pprint.pprint(t, width=30) [[[['чёрный', 'бирюзовый'], 'белый', ['зелёный', 'красный']], [['пурпурный', 'жёлтый'], 'голубой']]] </syntaxhighlight> Модуль <code>textwrap</code> форматирует абзацы текста под определённую ширину: <syntaxhighlight lang="python">>>> import textwrap >>> doc = """Метод wrap() аналогичен fill(), но он возвращает список строк, а не одну большую строку с признаками концов строк.""" >>> print(textwrap.fill(doc, width=40)) Метод wrap() аналогичен fill(), но он возвращает список строк, а не одну большую строку с признаками концов строк. </syntaxhighlight> Модуль <code>locale</code> дает доступ к базе данных форматов различных культурных сред. Например, параметр <code>grouping</code> функции <code>format</code> этого модуля позволяет использовать группировку цифр принятыми в данной культурной среде разделителями: <syntaxhighlight lang="python">>>> import locale >>> locale.setlocale(locale.LC_ALL, 'en_US.UTF8') 'en_US.UTF8' >>> conv = locale.localeconv() # получить отображение соглашений >>> x = 1234567.8 >>> locale.format("%d", x, grouping=True) '1,234,567' >>> locale.format("%s%.*f", (conv['currency_symbol'], conv['frac_digits'], x), grouping=True) '$1,234,567.80' </syntaxhighlight> === Работа с шаблонами === Модуль <code>string</code> включает в себя гибкий класс <code>Template</code>, реализующий шаблоны с простым синтаксисом, доступным для редактирования конечными пользователями. Использование этого класса позволит пользователям настраивать приложения без изменений в них самих. Формат использует имена полей для подстановки, записываемых как знак доллара (<code>$</code>) с последующим идентификатором, состоящим, как и имена в программах на Python, из букв, цифр и подчёркиваний<ref>(''Прим. перев.'') вопреки ожиданиям, имена полей нельзя писать кириллицей.</ref>. Фигурные скобки вокруг идентификатора позволяют использовать алфавитно-цифровые символы сразу после поля подстановки, без дополнительных пробелов. Собственно знак доллара необходимо записывать сдвоенно: <code>$$</code>. <syntaxhighlight lang="python">>>> from string import Template >>> t = Template('${village}folk send $$10 to $cause.') >>> t.substitute(village='Nottingham', cause='the ditch fund') 'Nottinghamfolk send $10 to the ditch fund.' </syntaxhighlight> Метод <code>substitute()</code> возбуждает <code>KeyError</code> в случае, когда значение для поля отсутствует в переданных параметрах. Для приложений вроде массовой персонализированной рассылки, часть данных может отсутствовать. В таком случае лучше использовать метод <code>safe_substitute()</code>: он оставит разметку полей подстановки в случае отсутствия данных.<ref>(''Прим. перев.'') разумеется, ещё лучше позаботиться, чтобы у полей были удачные значения по умолчанию.</ref> <syntaxhighlight lang="python">>>> t = Template('Return the $item to $owner.') >>> d = dict(item='unladen swallow') >>> t.substitute(d) Traceback (most recent call last): . . . KeyError: 'owner' >>> t.safe_substitute(d) 'Return the unladen swallow to $owner.'</syntaxhighlight> Производные от <code>Template</code> классы могут переопределить разделитель. Например, утилита переименования файлов просмотрщика фотографий может использовать знаки процента в разметке полей подстановки: текущая дата, номер изображения по порядку, формат файла: <syntaxhighlight lang="python">>>> import time, os.path >>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg'] >>> class BatchRename(Template): ... delimiter = '%' >>> fmt = input('Введите стиль переименования (%d - дата, %n - номер п/п, %f - формат): ') Введите стиль переименования (%d - дата, %n - номер п/п, %f - формат): Ashley_%n%f >>> t = BatchRename(fmt) >>> date = time.strftime('%d%b%y') >>> for i, filename in enumerate(photofiles): ... base, ext = os.path.splitext(filename) ... newname = t.substitute(d=date, n=i, f=ext) ... print('{0} --> {1}'.format(filename, newname)) img_1074.jpg --> Ashley_0.jpg img_1076.jpg --> Ashley_1.jpg img_1077.jpg --> Ashley_2.jpg</syntaxhighlight> Другое приложение для использования шаблонов — отделение логики от деталей реализации различных выходных форматов. Это даёт возможность строить шаблоны для XML-файлов, текстовых отчётов и веб-отчётов на HTML. === Работа с записями двоичных данных === Модуль <code>struct</code> предлагает функции <code>pack()</code> и <code>unpack()</code> для работы с форматами двоичных записей переменной длины. Следующий пример показывает как можно получить заголовочную информацию из ZIP-файла без использования модуля <code>zipfile</code>. Коды <code>"H"</code> и <code>"I"</code> представляют двух- и четырехбайтовых беззнаковых числа соответственно. Код <code>"<"</code> обозначает, что числа стандартного размера и байты записаны в порядке «сначала младший» (little-endian): <syntaxhighlight lang="python">import struct data = open('myfile.zip', 'rb').read() start = 0 for i in range(3): # показать первые три заголовка start += 14 fields = struct.unpack('<IIIHH', data[start:start+16]) crc32, comp_size, uncomp_size, filenamesize, extra_size = fields start += 16 filename = data[start:start+filenamesize] start += filenamesize extra = data[start:start+extra_size] print(filename, hex(crc32), comp_size, uncomp_size) start += extra_size + comp_size # пропустить до следующего заголовка </syntaxhighlight> === Многопоточность === Потоки (threads) могут использоваться для разделения задач, которые могут выполняться по времени независимо друг от друга. Разделение на потоки может применяться для улучшения времени отклика приложений, ведущих диалог с пользователем пока другие задачи выполняются в фоновом режиме. Похожая ситуация с произведением ввода-вывода одновременно с вычислениями в другом потоке. Следующий пример показывает, как высокоуровневый модуль <code>threading</code> может выполнять фоновые задачи, продолжая выполнение основной программы: <syntaxhighlight lang="python">import threading, zipfile class AsyncZip(threading.Thread): def __init__(self, infile, outfile): threading.Thread.__init__(self) self.infile = infile self.outfile = outfile def run(self): f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) f.write(self.infile) f.close() print('Завершён фоновый zip для:', self.infile) background = AsyncZip('mydata.txt', 'myarchive.zip') background.start() print('Главная программа на переднем плане.') background.join() # Ждём завершения фоновой задачи print('Главная программа дождалась завершения фоновой задачи.') </syntaxhighlight> Основной трудностью многопоточных приложений является координирование потоков, разделяющих общие данные или другие ресурсы. В помощь этому модуль <code>threading</code> предлагает целый ряд простых средств: замки́, события, переменные условий, семафоры и другие. Несмотря на достаточную мощь представленных средств, даже небольшие погрешности в дизайне многопоточного приложения могут вызвать трудноповторимые проблемы. Таким образом, рекомендуемым подходом к координированию задач является централизация доступа к некоторому ресурсу в одном потоке и использование модуля <code>queue</code> для направления запросов из других потоков. Приложения, использующие Queue-объекты для межпотоковой связи и координирования, легче проектировать, сопровождать исходный код, они более надёжны. === Запись в журнал === Модуль <code>logging</code> предлагает богатую возможностями и гибкую систему ведения журнала. В простейшем случае сообщения отправляются на стандартный вывод ошибок — <code>sys.stderr</code>: <syntaxhighlight lang="python">import logging logging.debug('Отладочная информация') logging.info('Для информации') logging.warning('Предупреждение: файл %s не найден', 'server.conf') logging.error('Произошла ошибка!') logging.critical('Критическая ошибка - выход')</syntaxhighlight> Результат выполнения этого примера: <syntaxhighlight lang="text">WARNING:root:Предупреждение: файл server.conf не найден ERROR:root:Произошла ошибка! CRITICAL:root:Критическая ошибка - выход </syntaxhighlight> Без дополнительной настройки информационные и отладочные сообщения подавляются, а вывод направляется в <code>sys.stderr</code>. Другие варианты вывода: отправка сообщений по электронной почте, дейтаграммами, сокеты, на HTTP сервер. Другие фильтры могут выбирать различные варианты доставки в зависимости от приоритета: <tt>DEBUG</tt>, <tt>INFO</tt>, <tt>WARNING</tt>, <tt>ERROR</tt> или <tt>CRITICAL</tt>. Система записи в журнал может быть сконфигурирована напрямую из Python. Конфигурация также может быть загружена из конфигурационного файла и не требовать изменений в коде приложения. === Слабые ссылки === Python имеет автоматическое управление памятью: подсчёт ссылок для большинства объектов и сборка мусора для удаления циклов. Память освобождается сразу после того, как была удалена последняя ссылка на объект. Этот подход отлично работает для большинства приложений, но иногда возникает необходимость вести учёт объектов только когда они используются где-нибудь ещё. К сожалению, само слежение за объектами уже создает ссылку и тем самым объекты остаются в памяти. Модуль <code>weakref</code> (от англ. weak reference — слабая ссылка) даёт средство для учёта объектов без создания ссылок на них. Когда объект больше не нужен, он автоматически удаляется из таблицы слабых ссылок и производится обратный вызов <code>weakref</code>-объектов. Типичное применение модуля — кэширование объектов, которые затратно воспроизвести снова. <syntaxhighlight lang="python">>>> import weakref, gc >>> class A: ... def __init__(self, value): ... self.value = value ... def __repr__(self): ... return str(self.value) ... >>> a = A(10) # создаёт ссылку >>> d = weakref.WeakValueDictionary() # словарь, использующий слабые ссылки >>> d['primary'] = a # не создаёт ссылки >>> d['primary'] # достать объект, если он все ещё "жив" 10 >>> del a # удалить одну ссылку >>> gc.collect() # произвести сборку мусора 0 >>> d['primary'] # запись была автоматически удалена Traceback (most recent call last): File "<stdin>", line 1, in <module> d['primary'] File "C:/python31/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' </syntaxhighlight> === Работа со списками === В Python список может заменить многие структуры данных. Однако иногда необходимы альтернативные реализации, которые имеют другое компромиссное решение в отношении производительности. Модуль <code>array</code> (массив) предоставляет объект <code>array</code>, отличающийся от списка лишь возможностью более компактно хранить однородные данные. Следующий пример показывает массив чисел, хранимый в виде двухбайтных беззнаковых чисел (типокод «<code>H</code>»), а не в обычном списке, где каждый элемент типа <code>int</code> обычно занимает 16 байт: <syntaxhighlight lang="python">>>> from array import array >>> a = array('H', [4000, 10, 700, 22222]) >>> sum(a) 26932 >>> a[1:3] array('H', [10, 700])</syntaxhighlight> Модуль <code>collections</code> (коллекции) среди прочего предоставляет объект <code>deque</code> (дек, двухсторонняя очередь). Объекты этого типа имеют более быстрые операции вставки (append) и извлечения (pop) слева, но более медленный поиск внутренних элементов. Эти объекты хорошо подходят для реализации очередей и деревьев поиска в ширину: <syntaxhighlight lang="python">>>> from collections import deque >>> d = deque(["задача1", "задача2", "задача3"]) >>> d.append("task4") >>> print("Обрабатывается", d.popleft()) Обрабатывается задача1 unsearched = deque([starting_node]) def breadth_first_search(unsearched): node = unsearched.popleft() for m in gen_moves(node): if is_goal(m): return m unsearched.append(m) </syntaxhighlight> В дополнение к альтернативным реализациям списков библиотека также предлагает средства вроде модуля <code>bisect</code> с функциями для манипуляции отсортированными списками: <syntaxhighlight lang="python">>>> import bisect >>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')] >>> bisect.insort(scores, (300, 'ruby')) # вставка значения в отсортированный список >>> scores [(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')] </syntaxhighlight> Модуль <code>heapq</code> имеет функции для реализации кучи, основанной на обычных списках. Элемент с наименьшим значением всегда находится в позиции с индексом 0. Это свойство может с успехом быть задействовано в приложениях, где особенно частый доступ необходим к наименьшему элементу, но полную сортировку проводить накладно. <syntaxhighlight lang="python">>>> from heapq import heapify, heappop, heappush >>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] >>> heapify(data) # сделать из списка кучу >>> heappush(data, -5) # добавить новый элемент >>> [heappop(data) for i in range(3)] # извлечь три наименьших значения [-5, 0, 1] </syntaxhighlight> === Десятичная арифметика чисел с плавающей запятой === Модуль <code>decimal</code> предоставляет тип данных <code>Decimal</code> для десятичной арифметики с плавающей запятой. В сравнении со встроенной двоичной арифметикой, новый класс особенно полезен в финансовых приложениях и других случаях, требующих точного десятичного представления, управления точностью, округлением c соблюдением законодательных и нормативных требований, отслеживания количества значащих цифр или для приложений, от которых ожидается совпадение с результатами, проделанными «вручную». Например, вычисление 5%-ного налога на 70 копеечный телефонный счет даёт различные результаты при использовании десятичной и двоичной арифметик. Разница становится значащей при округлении до ближайшей копейки: <syntaxhighlight lang="python">>>> from decimal import * >>> Decimal('0.70') * Decimal('1.05') Decimal("0.7350") >>> .70 * 1.05 0.73499999999999999 </syntaxhighlight> == Что дальше? == Чтение этого учебника, возможно, усилило ваш интерес к применению Python, и вы жаждете использовать этот язык для решения конкретных задач. Где можно пополнить знания о Python? Этот учебник является частью набора документации Python. В этом наборе есть и другие документы. ---- '''Сноски:''' <references /> 271qn6cc1zofvsrbfjb9tpuic6smdv0 Рецепт:Азъяшыд 104 30101 270415 253131 2026-10-27T06:58:50Z Jcb 79968 270415 wikitext text/x-wiki ''Основная статья с рецептами категории:'' [https://ru.wikibooks.org/wiki/Категория:Борщи Борщи] {{Рецепт |Категория = Борщи |Кухня = Финно-угорская кухня, русская кухня |Порций = 4 |Время = |Сложность = 2 |Энергетическая ценность = |Изображение = Лапеня.jpg }} '''Азъяшыд''' (''щи борщевые'', ''«древнерусский» борщ'' Новгородской Руси) как национальное фино-угорское блюдо (сохранившееся со времён Древней Руси особенно у коми и коми-пермяков) готовят из борщевика сибирского или обыкновенного (европейского), специально обработанного для этой цели. = Ингредиенты = <div class="mw-collapsible"> [[Файл:HeracleumSphondylium1.jpg|thumb|left|Борщевик обыкновенный]] Пропорции произвольны: * 1 л рубленого подготовленного борщевика * 1 стакан рубленой зелени (крапивы, лебеды) * 0,5 кг мяса * 2-3 луковицы или 1-1,5 стакана рубленой колбы (черемши) * 30-40 г ячневой крупы (2 ст. ложки) </div> = Приготовление = <div class="mw-collapsible"> Борщевик рубят, как капусту, а затем бланшируют или запаривают кипятком (иногда 2-3 мин. отваривают) и, слив воду, слегка солят и сохраняют в кадках, где он приобретает характерный грибной вкус.<br> Летом в азъяшыд добавляют немного свежей крапивы, лебеды и чертополоха, придающих блюду «наваристость» и нежность.<br> Обязательным компонентом азъяшыд служит ячневая крупа, чтобы придать им национальный колорит. Далее готовят как [[Рецепт:Щи|щи]].<br> Заправляют азъяшыд луком, а на Урале и в Зауралье – колбой (черемшой). Забеливают, как и щи, сметаной.<br> Вычегодские и сысольские коми в прошлом традиционно использовали в азъяшыд солонину, ижемские коми – оленину, коми-пермяки и колвинские вогулы (манси) – лесную дичь (рябчиков, куропаток), зауральские манси – рыбу (таймень). </div> == Литература == <div class="mw-collapsible"> * {{книга |автор= |часть= |заглавие= <b>''Большая энциклопедия кулинарного искусства.''</b> Все рецепты В.В. Похлёбкина |ответственный= |место= М. |издательство= Центрполиграф |год= 2001, 2010. — {{ISBN|5-227-01135-4}}, {{ISBN|978-5-9524-4897-1}}}} </div> == Ссылки == k1f0pfethbgc6dgcyx9bge50zo0hc8x Как исправить неправильную кодировку 0 31229 270430 254946 2026-10-27T07:12:15Z Jcb 79968 270430 wikitext text/x-wiki В современном мире с проблемой неправильной кодировки встречаются достаточно редко. Кодировкой «по умолчанию» считается UTF-8, которая поддерживает почти все известные системы письма. Если кто-то использует другие кодировки, принято явно указывать, какая кодировка используется. Также многие современные программы, такие как почтовые клиенты, имеют средства для распознания используемой кодировки. Однако есть ещё ситуации, когда можно увидеть появление кракозябр вместо осмысленного текста: * Использование устаревшего ПО, не поддерживающего Юникод; * ID3v1-теги у MP3-файлов; * Работа с приложениями для командной строки Windows и PowerShell в других эмуляторах терминала, например MinGW — в первых по историческим причинам используются кодировки времён DOS — в частности CP866 для русского языка, а последние как правило собираются с поддержкой UTF-8. * Есть возможность получить неадекватные символы при использовании неправильных шрифтов при печати на принтере или фотонаборном автомате, неверно настроенной локали программы (когда вместо кодовой страницы CP1251 используется CP1252). * При использовании UTF-8 всё равно остаётся риск получить кракозябры при выводе текста по HTTP: если кодировка нигде не указана, {{RFC|2616}} даёт значение по умолчанию — ISO-8859-1<ref>{{RFC|2616}} — Hypertext Transfer Protocol — HTTP/1.1<!-- Заголовок добавлен ботом --></ref>. Нередко бывает, что перекодировка осуществляется в правильном направлении, но сам перекодировщик работает не совсем корректно. Например, некоторые программы-перекодировщики преобразуют только базовые русские буквы, а все остальные символы оставляют на месте. В итоге при перекодировке KOI8-R&nbsp;→&nbsp;Windows-1251 буква '''ё''' превращается в '''Ј''' (сербская буква), значок градуса (°) превращается в '''њ''' и т.&nbsp;д. (такие тексты в изобилии встречаются в Интернете, достаточно поискать слова «всЈ» или «њС»). Другой вариант искажений связан с тем, что в целевой кодировке могут отсутствовать символы, имеющиеся в исходной кодировке. В этом случае отсутствующие символы могут просто выбрасываться, заменяться на символ-заменитель (часто знак вопроса — ?, иногда �) или же заменяться на похожие символы из ASCII (например, знак минуса (<code>U+2212</code>, −) может заменяться на простой дефис (<code>U+002D</code>, -), буква '''š''' может заменяться на '''s''' и т.&nbsp;д. В&nbsp;случае простого текста такие потери информации неизбежны, однако, если преобразованию подвергается файл HTML или XML, то корректным преобразованием будет замена отсутствующих в целевой кодировке символов на соответствующие мнемоники HTML: например, знак минуса должен заменяться на <code>&amp;minus;</code> или <code>&amp;#8722;</code> буква '''š''' должна заменяться на <code>&amp;scaron;</code> или <code>&amp;#353;</code> и т.&nbsp;д. == История == В 1980-е и 1990-е пользователи компьютеров и с 1990 г. — пользователи русскоязычной части интернета вынуждены были мириться с существованием нескольких конкурирующих кодировок кириллицы: основная — ГОСТ, альтернативная — DOS 866 (Unix KOI8-R, Windows CP-1251, ISO 8859-5), MacCyrillic. В результате неправильной конфигурации серверов и недостаточной совместимости тексты очень часто было невозможно прочесть. Получая сообщения по электронной почте или зайдя на веб-сайт, неопытные пользователи могли наткнуться на странные необычные символы вместо букв кириллицы. == Как распознать == По этому списку можно приблизительно определить, из какой кодировки в какую произошло преобразование. Для примера использована панграмма (без кавычек): «Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства». {| class="wikitable" !Исходная кодировка!!При декодировании воспринято как!!Результат |- |colspan="2" style="text-align:center;" | При воспроизведении применяется та же кодировка, что и при создании текста. || Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства. |- |rowspan="4"| [[:w:Windows-1251|Windows-1251]] || [[:w:Windows-1252|Windows-1252]] или <br />[[:w:ISO 8859-1|ISO 8859-1]]<ref name="w1252">Кодовая таблица ISO 8859-1 отличается лишь отсутствием ряда изображённых символов. В системе Microsoft Windows вместо кодовой страницы ISO 8859-1 применяется её расширение Windows-1252.</ref> || <nowiki>Øèðîêàÿ ýëåêòðèôèêàöèÿ þæíûõ ãóáåðíèé äàñò ìîùíûé òîë÷îê ïîäú¸ìó ñåëüñêîãî õîçÿéñòâà.</nowiki> |- | [[:w:КОИ-8|KOI8-R]] || <nowiki>ьХПНЙЮЪ ЩКЕЙРПХТХЙЮЖХЪ ЧФМШУ ЦСАЕПМХИ ДЮЯР ЛНЫМШИ РНКВНЙ ОНДЗ╦ЛС ЯЕКЭЯЙНЦН УНГЪИЯРБЮ.</nowiki> |- | [[:w:ISO 8859-5|ISO 8859-5]] || <nowiki>иш№юърџ §ыхъђ№шєшърішџ ўцэћѕ уѓсх№эшщ фрёђ ьюљэћщ ђюыїюъ яюфњИьѓ ёхыќёъюую ѕючџщёђтр.</nowiki> |- | [[:w:Альтернативная кодировка|CP 866]] || <nowiki>╪шЁюър ¤ыхъЄЁшЇшърЎш ■цэ√ї уєсхЁэшщ фрёЄ ью∙э√щ Єюыўюъ яюф·╕ьє ёхы№ёъюую їюч щёЄтр.</nowiki> |- |rowspan="5"| [[:w:КОИ-8|KOI8-R]] || [[:w:Windows-1252|Windows-1252]] или <br />[[:w:ISO 8859-1|ISO 8859-1]]<ref name="w1252"/> || <nowiki>ûÉÒÏËÁÑ ÜÌÅËÔÒÉÆÉËÁÃÉÑ ÀÖÎÙÈ ÇÕÂÅÒÎÉÊ ÄÁÓÔ ÍÏÝÎÙÊ ÔÏÌÞÏË ÐÏÄߣÍÕ ÓÅÌØÓËÏÇÏ ÈÏÚÑÊÓÔ×Á.</nowiki> |- | [[:w:Windows-1251|Windows-1251]] || <nowiki>ыЙТПЛБС ЬМЕЛФТЙЖЙЛБГЙС АЦОЩИ ЗХВЕТОЙК ДБУФ НПЭОЩК ФПМЮПЛ РПДЯЈНХ УЕМШУЛПЗП ИПЪСКУФЧБ.</nowiki> |- | [[:w:ISO 8859-5|ISO 8859-5]] || <nowiki>ћЩвЯЫСб мЬХЫдвЩЦЩЫСУЩб РжЮйШ ЧеТХвЮЩЪ ФСгд ЭЯнЮйЪ дЯЬоЯЫ аЯФпЃЭе гХЬигЫЯЧЯ ШЯкбЪгдзС.</nowiki> |- | [[:w:Альтернативная кодировка|CP 866]] || <nowiki>√╔╥╧╦┴╤ ▄╠┼╦╘╥╔╞╔╦┴├╔╤ └╓╬┘╚ ╟╒┬┼╥╬╔╩ ─┴╙╘ ═╧▌╬┘╩ ╘╧╠▐╧╦ ╨╧─▀г═╒ ╙┼╠╪╙╦╧╟╧ ╚╧┌╤╩╙╘╫┴.</nowiki> |- | [[:w:КОИ-7|КОИ-7]] || <nowiki>{IROKAQ \LEKTRIFIKACIQ @VNYH GUBERNIJ DAST MO]NYJ TOL^OK POD_#MU SELXSKOGO HOZQJSTWA.</nowiki> |- |rowspan="4"| [[:w:ISO 8859-5|ISO 8859-5]] || [[:w:Windows-1252|Windows-1252]] или <br />[[:w:ISO 8859-1|ISO 8859-1]]<ref name="w1252"/> || <nowiki>ÈØàÞÚÐï íÛÕÚâàØäØÚÐæØï îÖÝëå ÓãÑÕàÝØÙ ÔÐáâ ÜÞéÝëÙ âÞÛçÞÚ ßÞÔêñÜã áÕÛìáÚÞÓÞ åÞ×ïÙáâÒÐ.</nowiki> |- | [[:w:Windows-1251|Windows-1251]] || <nowiki>ИШаЮЪРп нЫХЪваШдШЪРжШп оЦЭле УгСХаЭШЩ ФРбв ЬЮйЭлЩ вЮЫзЮЪ ЯЮФксЬг бХЫмбЪЮУЮ еЮЧпЩбвТР.</nowiki> |- | [[:w:КОИ-8|KOI8-R]] || <nowiki>хьЮчзпО МшузБЮьДьзпФьО НжщКЕ сЦяуЮщьы тпАБ эчИщКы БчшГчз ъчтЙЯэЦ АушЛАзчсч ЕчвОыАБрп.</nowiki> |- | [[:w:Альтернативная кодировка|CP 866]] || <nowiki>╚╪р▐┌╨я э█╒┌тр╪ф╪┌╨ц╪я ю╓▌ых ╙у╤╒р▌╪┘ ╘╨ст ▄▐щ▌ы┘ т▐█ч▐┌ ▀▐╘ъё▄у с╒█ьс┌▐╙▐ х▐╫я┘ст╥╨.</nowiki> |- |rowspan="5"| [[:w:Альтернативная кодировка|CP 866]] || [[:w:Windows-1252|Windows-1252]]<ref name="w1252"/> || <nowiki>˜¨à®ª ï í«¥ªâà¨ä¨ª æ¨ï ëå £ã¡¥à­¨© ¤ áâ ¬®é­ë© ⮫箪 ¯®¤êñ¬ã ᥫì᪮£® å®§ï©áâ¢&nbsp;.</nowiki> |- | [[:w:Windows-1251|Windows-1251]] || <nowiki>�Ёа®Є п н«ҐЄваЁдЁЄ жЁп о¦­ле ЈгЎҐа­Ё© ¤ бв ¬®й­л© в®«з®Є Ї®¤кс¬г ᥫмбЄ®Ј® е®§п©бвў&nbsp;.</nowiki> |- | [[:w:КОИ-8|KOI8-R]] || <nowiki>≤╗Ю╝╙═О М╚╔╙БЮ╗Д╗╙═Ф╗О Н╕╜КЕ ёЦ║╔Ю╜╗╘ ╓═АБ ╛╝И╜К╘ Б╝╚Г╝╙ ╞╝╓ЙЯ╛Ц А╔╚ЛА╙╝ё╝ Е╝╖О╘АБ╒═.</nowiki> |- | [[:w:ISO 8859-5|ISO 8859-5]] || <nowiki>�ЈрЎЊ я эЋЅЊтрЈфЈЊ цЈя юІ­ых ЃуЁЅр­ЈЉ Є ст ЌЎщ­ыЉ тЎЋчЎЊ ЏЎЄъёЌу сЅЋьсЊЎЃЎ хЎЇяЉстЂ&nbsp;.</nowiki> |- | [[:w:CP437|CP 437]] || <nowiki>ÿ¿α«¬á∩ φ½Ñ¬Γα¿Σ¿¬áµ¿∩ δσ úπíÑα¡¿⌐ ñáßΓ ¼«Θ¡δ⌐ Γ«½τ«¬ »«ñΩ±¼π ßѽ∞߬«ú« σ«º∩⌐ßΓóá.</nowiki> |- |rowspan="5"| [[:w:UTF-8|UTF-8]]<ref> Варианты ''декодирования'' в UTF-8 не приводятся, так как бо́льшая часть русского текста, записанного в 8-битной кодовой странице, будет сочтена ошибочной (не имеющей представления).</ref> | [[:w:Windows-1252|Windows-1252]]<ref name="w1252"/> || <nowiki>Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства.</nowiki> |- | [[:w:Windows-1251|Windows-1251]] || <nowiki>Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства.</nowiki> |- | [[:w:КОИ-8|KOI8-R]] || <nowiki>п╗п╦я─п╬п╨п╟я▐ я█п╩п╣п╨я┌я─п╦я└п╦п╨п╟я├п╦я▐ я▌п╤п╫я▀я┘ пЁя┐п╠п╣я─п╫п╦п╧ п╢п╟я│я┌ п╪п╬я┴п╫я▀п╧ я┌п╬п╩я┤п╬п╨ п©п╬п╢я┼я▒п╪я┐ я│п╣п╩я▄я│п╨п╬пЁп╬ я┘п╬п╥я▐п╧я│я┌п╡п╟.</nowiki> |- | [[:w:ISO 8859-5|ISO 8859-5]] || <nowiki>аЈаИб�аОаКаАб� б�аЛаЕаКб�б�аИб�аИаКаАб�аИб� б�аЖаНб�б� аГб�аБаЕб�аНаИаЙ аДаАб�б� аМаОб�аНб�аЙ б�аОаЛб�аОаК аПаОаДб�б�аМб� б�аЕаЛб�б�аКаОаГаО б�аОаЗб�аЙб�б�аВаА.</nowiki> |- | [[:w:Альтернативная кодировка|CP 866]] || <nowiki>╨и╨╕╤А╨╛╨║╨░╤П ╤Н╨╗╨╡╨║╤В╤А╨╕╤Д╨╕╨║╨░╤Ж╨╕╤П ╤О╨╢╨╜╤Л╤Е ╨│╤Г╨▒╨╡╤А╨╜╨╕╨╣ ╨┤╨░╤Б╤В ╨╝╨╛╤Й╨╜╤Л╨╣ ╤В╨╛╨╗╤З╨╛╨║ ╨┐╨╛╨┤╤К╤С╨╝╤Г ╤Б╨╡╨╗╤М╤Б╨║╨╛╨│╨╛ ╤Е╨╛╨╖╤П╨╣╤Б╤В╨▓╨░.</nowiki> |- |rowspan="1"| [[:w:UTF-16|UTF-16]] | [[:w:Альтернативная кодировка|CP 866]] || <nowiki>(♦8♦@♦>♦:♦0♦O♦ M♦;♦5♦:♦B♦@♦8♦D♦8♦:♦0♦F♦8♦O♦ N♦6♦=♦K♦E♦ 3♦C♦1♦5♦@♦=♦8♦9♦ 4♦0♦A♦B♦ <♦>♦I♦=♦K♦9♦ B♦>♦;♦G♦>♦:♦ ?♦>♦4♦J♦Q♦<♦C♦ A♦5♦;♦L♦A♦:♦>♦3♦>♦ E♦>♦7♦O♦9♦A♦B♦2♦0♦. </nowiki> |} == Перекодировка текстовых файлов == Перекодировка с целью восстановления исходного текста не всегда возможна. Например, уже при двукратной перекодировке, произошедшей, к примеру, при передаче сообщения через несколько неверно настроенных почтовых серверов, может произойти необратимая потеря информации, так как определённые различные символы исходного текста при определённых условиях могут замениться на другие, но одинаковые неправильные символы, и восстановить такое сообщение невозможно, даже если знать, какие перекодировки и в каком порядке были произведены. === Через командную строку=== Для восстановления текста (и для перекодировки) в POSIX-совместимых системах можно использовать утилиту iconv, например: <syntaxhighlight lang="bash"> iconv -c -f cp1251 -t cp1252 source.txt > target.txt </syntaxhighlight> Утилита iconv также полезна при запуске в эмуляторах терминала, работающих под UTF-8 (например, mingw), программ, рассчитанных на работу в командной строке WINDOWS, если они выводят сообщения на русском. <syntaxhighlight lang="bash"> ping example.com | iconv -f cp1251 </syntaxhighlight> === С помощью браузера === Можно открыть текстовый файл с неизвестной кодировкой с помощью любого популярного браузера, в котором доступно ручное указание кодировки (обычно: ''Вид — кодировка — …'' в верхнем меню, либо в контекстном меню). Позже, когда методом перебора удастся получить читаемый текст, его можно скопировать в текстовой редактор и сохранить в нужной кодировке. === Специализированные утилиты === Существует множество утилит, позволяющих ручное (с выбором пары кодировок) или автоматическое (вплоть до нескольких уровней глубины) перекодирование текста, например, для Windows: TotalRecode или «Штирлиц». === Онлайн-сервисы === Среди онлайн-сервисов можно выделить декодер Артемия Лебедева, который пытается распознавать текст даже после многократной перекодировки. == См. также == * [[Vim#Как открыть файл в нужной кодировке]] == Примечания == {{примечания}} [[Категория:Информационные технологии]] [[Категория:Учебники без шаблона]] pgkjwqs95apsuou29ld8h0gca2unuh8 Средства индивидуальной защиты (обзорная лекция)/Общая информация 0 35569 270421 269342 2026-10-27T07:04:55Z Jcb 79968 270421 wikitext text/x-wiki == Международная организация труда == По мнению специалистов [[:w:Международная организация труда |МОТ]] эффект от использования СИЗ зависит и от их качества, '''''и от того, насколько правильно они выбираются и применяются на практике'''''<ref name="МОТ-4" /><ref name="ILO-4" />. Поэтому во многих развитых странах разработаны не только минимальные требования к техническим характеристикам СИЗ, которые должны выполняться изготовителями и поставщиками, а выполнение должно проверяться при сертификации, но и требования к работодателю, чётко определяющие его действия при использовании индивидуальной защиты; выполнение таких требований (программ индивидуальной защиты<ref name="МОТ-4" />, например при [[:w:Программа защиты от шума|защите от шума]] и от [[:w:Законодательное регулирование выбора и организации применения респираторов|воздушных загрязнений]]) должно проверяется государственными и [[:w:ru:Профессиональный союз|профсоюзными]] инспекторами. В развитых странах требования к СИЗ, и к их выбору и использованию, могут разрабатываться (в большей или меньшей степени) на основе результатов [[:w:Научное исследование|научных исследований]]. В разработке участвуют квалифицированные специалисты. Часть из них тесно связана и/или непосредственно работает в коммерческих организациях, торгующих СИЗ, что может приводить к потенциальному [[:w:Конфликт интересов |конфликту интересов]]. В других странах, не имеющих возможности проводить исследования, часто берут за основу стандарты США, ЕС и [[:w:ru:Международная организация по стандартизации |ИСО]], иногда другие иностранные стандарты. Если оригинал устарел, не соответствует современному уровню науки, или содержит ошибки - недостатки могут остаться не замеченными, и могут попадасть в национальный стандарт. Для [[:w:СИЗОД|СИЗ органов дыхания]], часть которых может использоваться в опасной для жизни атмосфере, и [[:w:Средства индивидуальной защиты органа слуха |средств защиты от шума]], который очень часто достигает опасного уровня, и вызывает [[:w:Нейросенсорная тугоухость |необратимую и неизлечимую утрату слуха]], требования к техническим свойствам средств защиты и к их выбору и использованию разработаны в наиболее полной степени, и имеются во многих странах. Также СИЗ могут оказывать вредное воздействие на работника<ref name="МОТ-инструкция" />, могут мешать работать и могут сами создавать опасность для жизни и здоровья<ref name="Suruda-2003" /><ref name="Громов-1961" /><ref name="Денисов--2013" />. Использование СИЗ может создавать ошибочное ощущение безопасности<ref name="ILO-2001" />. == Международная организация по стандартизации и Европейский Союз == [[:w:Международная организация по стандартизации |ИСО]] провела большую работу по разработке стандартов, охвативших разные стороны индивидуальной защиты от воздушных загрязнений<ref name="БТП-2021" />, [[:w:Промышленный шум|шум]]а и другие. Многие из них приняты в Европейском Союзе и в РФ. Большая часть стандартов ИСО относится к техническим требованиям к СИЗ, и значительно меньшая - к их выбору и использованию; для некоторых видов СИЗ стандарты последнего типа отсутствуют. В ЕС<ref name="ЕС-директива-товар" /> с 2018 года установлены общие требования к стандартам, определяющим минимальные требования к техническим характеристикам СИЗ, к методам их испытаний, маркировке и др. ([[:w:Директива 89/686/ЕЭС|предыдущая версия]] действовала с 1989 года) Все стандарты, разработанные согласно Директиве, обязательны для выполнения, а работодатели обязаны выдавать работникам только сертифицированные СИЗ. Также принята Директива об обеспечении работников СИЗ<ref name="ЕС-директива-рабочие" />. По требованиям к проверке СИЗ, все они делятся на три категории - простой, сложной и "промежуточной" конструкции. В зависимости от сложности установлена разная степень тщательности их испытаний. == СССР и РФ == В СССР изготавливалось множество СИЗ<ref name="СИЗОД-1977-1" />. Ассортимент моделей был невелик, иностранные практически не применялись, что приводило к разным последствиям. Например, отсутствие разнообразия моделей противогазных фильтров позволяло экспериментально определить [[:w:Способы замены противогазных фильтров респираторов|срок службы]] и [[:w:b:ru:Замена_противогазных_фильтров_СИЗОД_(лекция)# расписание-СССР| указать его в каталоге для <u>'''всех'''</u> моделей фильтров]], для разных концентраций десятков распространённых газов. Потребитель мог заменять фильтры без использования ненадёжной реакции органов чувств работника на появление вредного газа в маске, во многих случаях. С другой стороны, при несоответствии резиновой полумаски респиратора лицу не по размеру, а по форме - подобрать другую модель было невозможно вообще, т.к. практически все советские респираторы-полумаски использовали полумаску ПР-7. Качество изделий проверялось на государственных заводах-изготовителях, где были соответствующие подразделения. Отдельных органов по сертификации и отдельных лабораторий не было. После 1991 года, до первой попытки вступить во [[:w:Всемирная торговая организация|Всемирную торговую организацию]], и до принятия закона "О техническом регулировании"<ref name="184-ФЗ" /> в РФ следовали тенденции, сложившейся в СССР, и использовали ранее разработанные стандарты, требования которых были обязательными для выполнения. {{anchor|СИЗ-РФ}}Приход на [[:w:ru:рынок|рынок]] иностранных компаний породил ряд проблем из-за отличий самого характера требований к СИЗ в СССР и в других странах. Например, в СССР был разработан респиратор-полумаска РПГ-67, а значительно <u>'''позднее'''</u> к конструкции этой именно '''модели''' были разработаны требования в виде государственного стандарта на отдельную модель респиратора-полумаски<ref name="РПГ-67" />. А в развитых странах, для учёта того, что множество производителей изготавливает СИЗ разных моделей одного типа, были требования не к отдельным моделям, а к типу СИЗ, то есть были "требования общего характера". В результате в РФ невозможно было испытать, сертифицировать, и соответственно - легально использовать для защиты работников иностранные СИЗ. Поэтому стали разрабатывать новые ГОСТы, "гармонизированные" с иностранными, с требованиями не к моделям СИЗ, а более общего характера, к определённым типам СИЗ, например - респираторам-полумаскам<ref name="ГОСТ-190-99" />. При разработке новых ГОСТов учли пожелания потребителей и разработчиков СИЗ<ref name="Сорокин-2007-3" />. За основу решили почему-то взять стандарты Европейского Союза, а не США или другой страны. Декларировалось, что российские поставщики смогут выйти на европейский [[:w:ru:рынок|рынок]], но это не произошло. При разработке новых стандартов, гармонизированных с европейскими, в них вносили изменения и допускали ошибки, что вызывало нарекания. После принятия закона "О техническом регулировании"<ref name="184-ФЗ" /> все стандарты, и новые, и советские, стали не обязательными для применения. Вместо этого был разработан и принят один документ по всем СИЗ - [https://miningwiki.ru/wiki/Технический_регламент_"О_безопасности_СИЗ"#Критика Технический регламент "О безопасности средств индивидуальной защиты"]. Множество недостатков документа вызвало шквал критики<ref name="ПВ-2007-СИЗ" />: в нем собрали требования к всем видам СИЗ, "надёргав" их из соответствующих ГОСТов, а требований к тому, как именно проверять, соответствует ли изделие требованиям - не было вообще. К некоторым СИЗ и требований не было, разработка Регламента велась с нарушением Закона "О техническом регулировании"<ref name="ТР-2009" />. Из-за огромного объёма документа его заполняли требованиями экономно: например, к СИЗ органа слуха от шума требований ослаблять шум - не было, требований к способности противогазных фильтров очищать воздух не было вообще, и т.п<ref name="ТР-ТС" />. Уже сам процесс разработки вызывал серьёзные критические замечания, т.к., потенциально, авторы могли учитывать коммерческие интересы отдельных поставщиков<ref name="ТР-2009" />. Отчасти отреагировав на критику, спустя примерно 8 лет (2018 г.) [[:w:Евразийская экономическая комиссия |Евразийская экономическая коллегия]] опубликовала список стандартов, выполнение которых (на добровольной основе) обеспечивает выполнение Технического регламента (который уже обязателен для выполнения). Из-за крайне широкого охвата СИЗ в [https://miningwiki.ru/wiki/%D0%A2%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D1%80%D0%B5%D0%B3%D0%BB%D0%B0%D0%BC%D0%B5%D0%BD%D1%82_%22%D0%9E_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D0%A1%D0%98%D0%97%22 Техническом регламенте], этот список получился очень объёмным - 158 страниц<ref name="ТР-ТС+" />. Для сравнения, в Европейском Союзе сами стандарты по СИЗ являются обязательными для выполнения. В 2016 г. в РФ работало около 40 аккредитованных органов по сертификации и 50 лабораторий<ref name="Преображенский-2016" />. Но выдача "липовых сертификатов" продолжает оставаться обычным делом. == Источники == {{примечания|refs= <ref name="МОТ-4">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =[https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ю.Г. Сорокин] <small>(''руководитель Департамента условий и охраны труда, Минтруд РФ'')</small>; Жан-Виктор Груа <small>(''Директор Московского бюро МОТ'')</small>|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[http://base.safework.ru/iloenc?d&nd=857400340&prevDoc=857400340&spack=010LogLength%3D0%26LogNumDoc%3D857400038%26listid%3D010000000100%26listpos%3D0%26lsz%3D7%26nd%3D857400038%26nh%3D1%26 Современное состояние индивидуальных средств защиты]. В: Том 1; Раздел [http://base.safework.ru/iloenc?d&nd=857400005&prevDoc=857000002 IV], Глава [http://base.safework.ru/iloenc?d&nd=857400038&prevDoc=857400346 31. Средства индивидуальной защиты] |автор=Роберт Ф. Херрик (автор и редактор раздела СИЗ) |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|isbn=|серия= Охрана труда}}</ref> <ref name="ILO-4">''Robert F. Herrick''. [https://iloencyclopaedia.org/part-iv-66769/personal-protection-59388/item/686-overview-and-philosophy-of-personal-protection Overview and Philosophy of Personal Protection]. In: Vol. 1; [https://iloencyclopaedia.org/part-iv-66769/personal-protection-59388 Chapter 31. Personal Protection] // [https://iloencyclopaedia.org/ Encyclopedia of Occupational Health and Safety] / Michel Hansenne ed. — 4th ed. — Geneva: International Labour Office, 1998.</ref> <ref name="МОТ-инструкция">{{Книга|ссылка=https://www.ilo.org/ru/publications/факторы-окружающей-среды-на-рабочем-месте-инструкция-международной|автор=Бюро Международной Организации Труда|заглавие=Факторы окружающей среды на рабочем месте. Инструкция МОТ|ответственный=ILO Publications, International Labour Office|год=2001|часть=3.3. Предотвращение и контроль|место=Женева|издательство=Международная Организация Труда|страницы=22—23|страниц=73|серия=Программа по безопасности труда, охране здоровья и окружающей среды - Безопасная Работа|isbn=92-2-111628-X}} [https://coht.ru/files/26_pr.pdf копия]</ref> <ref name="Suruda-2003">{{статья|автор= Anthony Suruda, William Milliken, Dale Stephenson & Richard Sesek|заглавие=Fatal Injuries in the United States Involving Respirators, 1984-1995|ссылка= https://www.researchgate.net/publication/10856558_Fatal_Injuries_in_the_United_States_Involving_Respirators_1984-1995 |язык=en |издание=Applied Occupational and Environmental Hygiene |издательство=Taylor & Francis |год=2003| volume=18|выпуск=4|pages=289-292| |doi= 10.1080/10473220301405}} ISSN 1521-0898, {{PMID|12637239}}. CDC [https://stacks.cdc.gov/view/cdc/186373/cdc_186373_DS1.pdf PDF]</ref> <ref name="Громов-1961">{{статья|заглавие=Из практики расследования причин скоропостижной смерти шахтёров|ссылка=https://cyberleninka.ru/article/n/iz-praktiki-rassledovaniy-prichin-skoropostizhnoy-smerti-shahterov|автор=Громов А.П.|издание=Гигиена и санитария|место=Москва|издательство=Медицина|год=1961|номер=1| страницы=109—112|}} ISSN 0016-9900</ref> <ref name="Денисов--2013">{{статья|автор=Денисов Э.И., Морозова Т.В.|заглавие=Средства индивидуальной защиты от вредных производственных факторов|ссылка=http://ohrana-bgd.narod.ru/vvv/vvv3.html|издание=Жизнь без опасностей. Здоровье, профилактика, долголетие|издательство=Велт|год=2013|номер=1|страницы=40—45}} ISSN 1995-5317</ref> <ref name="ЕС-директива-товар">{{Статья|ссылка=https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=celex%3A32016R0425|автор=The European Parliament and the Council of the European Union|заглавие=Regulation (EU) 2016/425 of the European Parliament and of the Council of 9 March 2016 on personal protective equipment and repealing|год=2016| серия=Council Directive 89/686/EEC (OJ L 81, 31.3.2016, pp. 51–98)|язык=en|издание=Official Journal of the European Union|тип=журнал|месяц=3|число=31|выпуск=L 81 (series L – Legislation)|автор издания= European Union |pages=L 81/51 - L 81/98| |volume=59}} ISSN 1977-0677. С 1989 по 2018 гг. действовала [[:w:ru:Директива 89/686/ЕЭС|предыдущая версия Директивы]].</ref> <ref name="ЕС-директива-рабочие">{{Статья |ссылка=https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A01989L0656-20191120 |автор=The Council of the European Communities |заглавие=Council Directive of 30 November 1989 on the minimum health and safety requirements for the use by workers of personal protective equipment at the workplace (third individual directive within the meaning of Article 16 (1) of Directive 89/391/EEC) (89/656/EEC) |год=1989 (amend. 2007) |язык=en |автор издания=European Union |место=EU |издание=Official Journal of the European Union |тип=журнал |месяц=12 |число=30 |выпуск=L 393 (series L – Legislation) |pages=L 393 / 18 - L 393 / 28 |volume=32 }} ISSN 0378-6978. old [https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=OJ:L:1989:183:FULL PDF] [https://meganorm.ru/mega_doc/dop_norm/52/gost_r_70231-2022_natsionalnyy_standart_rossiyskoy/0/direktiva_N_89_656_ees_soveta_evropeyskikh_soobshchestv_o.html?ysclid=moec7pwxxz657959550 перевод]</ref> <ref name="СИЗОД-1977-1">{{Книга|автор= И.Н. Никифоров|заглавие=Проблемы разработки и испытания средств индивидуальной защиты органов дыхания|ответственный=И.Н. Никифоров, С.Л. Каминский (ред.)|год=1977|часть= Средства индивидуальной защиты органов дыхания и задачи их совершенствования. В: Раздел 1. Перспективы создания и использования средств индивидуальной защиты органов дыхания|место=Москва|издательство=Всесоюзный центральный научно-исследовательский институт охраны труда ВЦСПС|страницы= 7-12|страниц=72|тираж=1000|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731316690&archive=&start_from=&ucat=&}}</ref> <ref name="184-ФЗ">{{Книга|ссылка=http://cntr-nrs.gosnadzor.ru/about/AKTS/О%20техническом%20регулировании%20(с%20изменениями%20на%202%20июля%202021%20года)%20(редакция,%20действующая%20с%2023%20декабря..._Текст.pdf|заглавие=Федеральный закон "О техническом регулировании" № 184-ФЗ от 27 декабря 2002 года|ответственный=В.Путин|год=2002|место=Москва|страниц=52|серия=редакция, действующая с 23 декабря 2021 года}}</ref> <ref name="РПГ-67">{{Книга|ссылка=https://ohranatruda.ru/upload/iblock/bc7/4294839027.pdf|автор=Группа Л07|заглавие=ГОСТ 12.4.004-74 Респираторы фильтрующие противогазовые РПГ-67|год=1974|место=Москва|страниц=7|серия=Межгосударственный стандарт}}</ref> <ref name="ГОСТ-190-99">{{Книга|ссылка=https://meganorm.ru/Index2/1/4294820/4294820432.htm|автор=Рабочая группа ПК 2 «Средства индивидуальной защиты органов дыхания» (в ТК 320 СИЗ)|заглавие=ГОСТ Р 12.4.190-99. ССБТ. СИЗОД. Полумаски и четвертьмаски из изолирующих материалов. Общие технические условия|ответственный=(аналог EN 140-89)|год=2000|место=Москва|издательство=Госстандарт России|страниц=24|тираж=585}} [https://meganorm.ru/Data2/1/4294820/4294820432.pdf PDF]</ref> <ref name="ILO-2001">{{Книга|ссылка=https://www.ilo.org/resource/ambient-factors-workplace|автор=Ivone Baumecker et al.|заглавие=Ambient factors in the workplace|год=2001 |часть=3.3. Prevention and control|язык=en|место=Geneva|издательство=International Labour Organization|pages=14-15|allpages=80|серия=ILO codes of practice|isbn=92-2-111628-X}} [https://www.ilo.org/fr/resource/les-facteurs-ambiants-sur-le-lieu-de-travail Les facteurs ambiants sur le lieu de travail. Recueil de directives pratiques du BIT [https://www.ilo.org/es/resource/factores-ambientales-en-el-lugar-de-trabajo Factores ambientales en el lugar de trabajo. Repertorio de recomendaciones practicas de la OIT]</ref> <ref name="БТП-2021">{{Статья|автор=[[:w:ru:Капцов, Валерий Александрович|В.А. Капцов]], В.Б. Панкова, А.В. Чиркин|заглавие=Международные стандарты по индивидуальной защите органов дыхания (обзор)|ссылка=https://elibrary.ru/item.asp?id=49432018 |год=2021|издание=Безопасность труда в промышленности|месяц=3|номер=3|страницы=70-75|автор издания=Федеральная служба по экологическому, технологическому и атомному надзору (РОСТЕХНАДЗОР); Закрытое акционерное общество «Научно-технический центр исследований проблем промышленной безопасности» (ЗАО НТЦ ПБ)|место=Москва|издательство=ЗАО "Алмаз-Пресс"}} ISSN 0409-2961</ref> <ref name="Сорокин-2007-3">{{Книга|автор=Пашнин Н.П., Сорокина Т.Ю.|заглавие=Средства индивидуальной защиты. Учебное пособие|ответственный=Президент АСИЗ [https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ю.Г. Сорокин], А.Л. Сафонов|год=2007|часть=4. Подтверждение соответствия, стандартизация и сертификация СИЗ. В: I. Общие положения по вопросам обеспечения работающих средствами индивидуальной защиты|издание=3 изд|место=Москва|издательство="Золотой телёнок", Минздравсоцразвития РФ|страницы=24, 31|страниц=288|серия=Охрана труда|isbn=978-5-88257-099-5|тираж=10 000}} ''"... Федеральной инспекцией труда проведено более 1,5 тыс. проверок соблюдения требований ст. 221 Трудового кодекса РФ по вопросам обеспечения работников средствами индивидуальной защиты, в ходе которых выявлено свыше 31,2 тыс. нарушений. ... Наиболее характерными ... нарушениями в этой сфере явилось приобретение организациями несертифицированных СИЗ."''</ref> <ref name="ТР-ТС">{{Книга|ссылка=https://www.novotest.ru/tr-ts/019-2011/tr-ts-019-2011.pdf|автор=Российская Федерация (Министерство здравоохранения и социального развития)|заглавие=Технический Регламент Таможенного Союза ТР ТС 019/2011 О безопасности средств индивидуальной защиты|ответственный=утв. Решением Комиссии Таможенного Cоюза от 9 декабря 2011 г. N 878|год=2011|место=Москва|страниц=167}}</ref> <ref name="ПВ-2007-СИЗ">{{Статья |ссылка= https://web.archive.org/web/20241104211022/https://promved.ru/articles/article.phtml?id=1248&nomer=45 |автор=Тимофеева Н.Т., Богданов С.А. |заглавие= Промышленные средства индивидуальной защиты. Нормировать необходимо их качество, а не только безопасность для человека |год=2007 |ответственный=редактор Моисей Гельман |автор издания=Экспертное некоммерческое партнерство |место=Москва |издание=Промышленные ведомости: экспертная общероссийская газета |месяц=8-9 |номер=8-9}}</ref> <ref name="ТР-2009">{{Статья|автор=А. Лянг|заглавие=Требуются публичные обсуждения|год=2009|автор издания=Общество с ограниченной ответственностью ТехНадзор|место=Екатеринбург|издание=[https://www.elibrary.ru/contents.asp?titleid=51310 Технадзор]|месяц=7|номер=7 (32)|страницы=84-85}}</ref> <ref name="ТР-ТС+">''Евразийская экономическая комиссия, председатель Т. Саркисян.'' [https://docs.eaeunion.org/ru-ru/Pages/DisplayDocument.aspx?s=e1f13d1d-5914-465c-835f-2aa3762eddda&w=9260b414-defe-45cc-88a3-eb5c73238076&l=8a412e96-924f-4b3c-8321-0d5e767e5f91&EntityID=17116 Решение № 37 Евразийской экономической комиссии "О внесении изменений в Решение Комиссии Таможенного союза от 9 декабря 2011 г. № 878"]. ''www.eurasiancommission.org''. Москва: Евразийская экономическая комиссия (6 марта 2018).</ref> <ref name="Преображенский-2016">{{статья|автор=Преображенский В.Б. (АСИЗ)|заглавие=Особенности российского рынка СИЗ |издание=Справочник специалиста по охране труда|место=Москва|издательство=МЦФР|год=2016|номер=3|страницы=68-75|}} ISSN 1727-6608</ref> }} a9m154dxz8d4w2atith9nldad8mp0k1 Средства индивидуальной защиты (обзорная лекция)/Важнейшие свойства СИЗ 0 35570 270418 270021 2026-10-27T07:02:53Z Jcb 79968 270418 wikitext text/x-wiki По сравнению со всеми другими средствами защиты, у СИЗ есть важные особенности: # '''Исключительная, уникальная универсальность'''. Например, для защиты от шума и пыли одни и те же респираторы и наушники могут использоваться и шахтёром, добывающим уголь на глубине более километра, и медицинским работником при лечении его коллег, больных силикотуберкулёзом. # '''Низкая стоимость и простота применения''' (по сравнению со [[:w:средства коллективной защиты |средствами коллективной защиты]]). Например, расходы на закупку [[:w:Респираторы ШБ Лепесток#Эффективность респиратора ШБ-1 «Лепесток»|респираторов Лепесток-200]] с высокой декларируемой эффективностью для всех работников цеха могут быть многократно меньше стоимости одной лишь электроэнергии, израсходованной двигателями обеспыливающей [[:w:Вентиляция |вентиляционной системы]] того же цеха за одну смену<ref name="ОТиСС-2016" />. Проектирование, изготовление, установка, пусконаладочные работы, и техническое обслуживание [[:w:Вентиляция |обеспыливающего вентиляционного оборудования]] требует не только затрат средств, но и достаточно высокой [[:w:Компетентность|компетентности]] исполнителей. Закупка и раздача работникам ([[:s:Требования к выбору эффективных респираторов и к организации их применения#1910.134(k)|без их обучения]]) [[:w:Респираторы ШБ Лепесток#Декларируемая эффективность |высокоэффективных респираторов]] может выполняться кем угодно, и без какой-то [[:s:Требования к выбору эффективных респираторов и к организации их применения#1910.134(k)|подготовки]] и опыта в отношении индивидуальной защиты органов дыхания (по каталогу поставщика). В РФ, в отличие от развитых стран, специалистов по охране труда обычно не учат выбору и организации применения СИЗ. # [[File:NIOSH наушники ru.jpg|thumb|right|240px|Стандартные чашки [[:w:Защитные наушники| наушников]] 65×41 мм, и уши разных размеров<ref name="Уши-1968" /> ]]'''Учёт индивидуальных особенностей рабочих'''. [[:w:Спецодежда |Спецодежду]] и [[:w:спецобувь |спецобувь]] подбирают по размеру и форме тела. В отличие от спецодежды для многих СИЗ это не очевидно. Начальники и снабженцы по личному опыту знают про подбор одежды и обуви, но вряд ли они (и даже рабочие) хорошо знают это о СИЗ. Респиратор-полумаска, соответствующая лицу по размеру, может не соответствовать ему по форме; но и при полном соответствии может неплотно прилегать к "гладкому" лицу, например, из-за отсутствия части зубов (прижимающих изнутри щеку к обтюратору маски), и [[Применение респираторов в промышленности#D. Особенности лица |по другим причинам]]. В результате между маской и лицом могут образовываться зазоры, через которые в органы дыхания будет поступать загрязнённый окружающий воздух. На выбор СИЗ органов слуха, вкладышей, влияют размер и форма слуховых каналов (Ø 3÷14 мм, поперечное сечение от эллиптического до щелевидного<ref name=Sataloff-1993>{{Книга|ссылка=https://archive.org/details/occupationalhear0000sata|автор=Joseph Sataloff, Paul L. Michael, Lawrence A. Vassalio|заглавие=Occupational Hearing Loss|год=1993|часть=Protector Types (Ear Canals and Earplugs)|язык=en|издание=2nd., rev. and expanded|место=New York, Basel, Hong Kong|издательство=Marcel Dekker, Inc|pages=418|allpages=839|серия=Occupational Safety and Health|isbn=0-8247-8814-1}}</ref>), у [[:w:Защитные наушники |наушников]] - размер ушей (см. рис.). В развитых странах [[:w:Проверка изолирующих свойств респираторов |закон требует проверять маски]] приборами, у каждого работника, а [[:w:Производственный контроль эффективности СИЗОС |аналогичные проверки противошумов]] пока выполняются ответственными [[:w:ru:Работодатель|работодателями]] добровольно<ref name="AIHA-2018" />. # [[File:Сорокин-2.jpg|thumb|220px|Чиновник [[:w:ru:Министерство труда и социальной защиты Российской Федерации|Минтруда]] и одновременно [https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры глава АСИЗ]<ref name="СИЗ-2005" />.]] '''Государственная поддержка'''. В РФ всё связанное с регулированием, разработкой, выпуском, импортом, сертификацией, продажей и использованием СИЗ находятся [[:w:ru:Лоббизм в России |под сильным влиянием]] созданной в 2001 году при поддержке [[:w:Министерство труда и социальной защиты Российской Федерации |Минтруда РФ]] "[[:w:Лоббизм_в_России#АСИЗ|Ассоциации разработчиков, изготовителей и поставщиков средств индивидуальной защиты]]". Много лет её возглавлял [https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры |Ю.Г. Сорокин]], руководитель Департамента условий и охраны труда ([[:w:ru:Министерство труда и социальной защиты Российской Федерации|Минтруда]]), и сначала он руководил [https://miningwiki.ru/wiki/Ассоциация_СИЗ АСИЗ] и Департаментом одновременно<ref name="СИЗ-2005" />. Потом к нему присоединился начальник отдела политики охраны труда Департамента В. Б. Преображенский. При проверках инспектора [[:w:Роструд|Роструд]]а (Минтруд) уделяют больше внимания выдаче СИЗ, а не улучшению условий труда<ref name="Роструд-доклад-14" /><ref name="Роструд-доклад-17" />. # '''Слишком частое использование.''' Существуют [[:w:Ранжирование методов защиты от вредных производственных факторов |разные способы защиты]] от опасных и [[:w:ru:Вредный производственный фактор |вредных производственных факторов]], но в пост-советский период сформировался сильный "перекос": в условиях крайне низкой ответственности за сбережение жизни и здоровья рабочих<ref name="ОТС-2016" /><ref name="волк" /> (для сравнения см.<ref name="Басов-1974" />) [[:w:ru:Работодатель|работодатели]] предпочитают использовать дешёвые и простые СИЗ<ref name="Беляков-06-2015" />. Например, [[:w:Социальный фонд России |Фонд социального страхования (ФСС), Социальный фонд]] разрешает [[:w:ru:работодатель|работодателям]] использовать часть страховых отчислений в фонд для профилактики страховых случаев (утраты [[:w:трудоспособность|трудоспособности]]). Обычно стоимость СИЗ гораздо меньше, чем [[:w:средства коллективной защиты |средств коллективной защиты]]. В 2021 году работодатели потратили (из средств фонда) на закупку СИЗ примерно в 240 раз больше денег, чем на улучшение условий труда<ref name="ФСС-2022" />. # '''Неопределённость, нестабильность и неизвестность фактической степени защиты рабочих'''. При использовании [[:w:средства коллективной защиты |средств коллективной защиты]] можно определить условия труда на [[:w:ru:Рабочее место|рабочем месте]], измерить воздействие [[:w:ru:Вредный производственный фактор |вредных производственных факторов]] и оценить степень их опасности. А при использовании некоторых СИЗ невозможно сказать, насколько хорошо или плохо защищён '''конкретный работник'''. Например, при проведении трудоёмких и дорогостоящих научных исследований [[:w:Производственные испытания респираторов |для определения коэффициентов защиты СИЗОД]] велика погрешность измерений т. н. "средней" концентрации вредных веществ во вдыхаемом воздухе<ref name="Капцов-2016" />. Но большинство работодателей и эти замеры провести не сможет. При использовании СИЗ органов слуха, вкладышей из пористых сжимаемых материалов, по мнению специалиста Р. Хоуи<ref name="Howie-2" />: "... Следует считать, что работник не защищён <small>''(от шума)''</small> вообще, пока [[:w:Производственный контроль эффективности СИЗОС |замеры на рабочем месте]] не покажут иное"<ref name="Howie-1" />. Большинство разнообразных методов сертификационного тестирования одежды, защищающей от химических веществ, не даёт никакого представления о степени и длительности защиты в производственных условиях на практике<ref name="ХимЗащОдежда-2017" />. Использование реакции работника на [[:w:Обоняние|появление запаха]] ядовитого газа в маске противогаза для [[:w:Способы замены противогазных фильтров респираторов |замены фильтров]] - ненадёжно, и потому запрещено во всех развитых странах. В РФ поставщики СИЗОД никаких других способов потребителям не дают. Неопределённость в отношении того, произойдёт ли десорбция токсичных газов при повторном использовании фильтров побудила ограничивать их использование<ref name="Капцов-2022" />, в РФ наличие проблемы замалчивается. Низкая / высокая температура (интенсивное тепловое излучение), коррозионно-активная атмосфера могут ухудшить защиту и даже разрушить СИЗ<ref name="Сорокин-2007-5" />. СИЗОД могут вызвать воспламенение во [[:w:Взрывозащита|взрывоопасной атмосфере]]. # '''Возможная ложная иллюзия защиты.''' Работодатели выдают работникам сертифицированные СИЗ, показавшие своё соответствовие действующим требованиям при сертификации и испытаниях по разработанным специалистами методам (стандартам) в [[:w:Аккредитация|аккредитованных]] лабораториях. Соответственно, недостаточно компетентные работодатели, рабочие и даже специалисты по гигиене и охране труда могут ошибочно полагать, что использование таких СИЗ обеспечивает защиту рабочих. Но эффективность СИЗ на практике может быть совершенно иной, и недостаточная информированность работающих на производстве (плюс замалчивание поставщиками наличия серьёзных проблем) ''может даже увеличивать опасность''<ref name="Денисов-2013" /><ref name="CCOHS-2025" />. Например, в<ref name="Suruda-2003" /> упомянуты случаи, когда три работника использовали противогазы, а маски [[:w:Способы проверки изолирующих свойств респираторов|неплотно прилегали к лицам]], а ещё двое полагались на фильтрующие СИЗОД при работе в [[:w:Концентрация вредных веществ, мгновенно-опасная для жизни или здоровья|опасной атмосфере с недостатком кислорода]]. При высококачественных подготовке, обучении и тренировке работников, ''а также при отсутствии СИЗ'' они бы остались живы. # '''Негативное влияние на работника и его работоспособность'''. Применение разных СИЗ, а также более чем одного средства защиты, может привести к воздействию на работника разных неблагоприятных факторов: повышение сопротивления дыханию; уменьшение подвижности; давление на голову; ухудшение газообмена при дыхании; уменьшение [[:w:Поле зрения|поля зрения]]; ухудшение восприятия акустической информации; перегрев из-за ухудшения теплоотдачи метаболического тепла в окружающую среду и другие<ref name="Буянов-1974" /><ref name="Полоний-1980" />. СИЗ органов дыхания и слуха могут мешать общению, что снижает [[:w:производительность труда]] и увеличивает количество ошибок<ref name="ГОЧС-7-2006" />. В условиях [[:w:Сдельная система оплаты труда|сдельной оплаты труда]] (и других часто используемых схожих способов стимулирования) это мотивирует рабочих не использовать СИЗ своевременно. В зависимости от температуры окружающего воздуха, применение СИЗ ухудшает работоспособность, для оценки которой могут использоваться разные показатели (мышечная сила, статическая выносливость, способность к динамической работе, способность к тонкой координации движений, биоэлектрическая активность мышц (показатель утомления), потребление кислорода)<ref name="Буянов-2001-" />. На основе изучения негативного влияния СИЗ рекомендовали относить работу, требующую применения респиратора, к более тяжёлой категории<ref name="Буянов-1974" />. Ухудшение физиологического состояния организма могло приводить к тому, что люди срывали с себя противогаз. Даже лёгкие фильтрующие полумаски (10-15 грамм) задерживают у лица непригодный для дыхания воздух при выдохе, заставляя вдыхать его повторно. Из-за этого концентрация вредного вещества, [[:w:Диоксид углерода |углекислого газа]], может превышать 4%<ref name="Sinkule-2013" /> при [[:w:ПДКр.з.|максимально разовой ПДК]] 1,4% (27 г/м<sup>3</sup><ref name="ГН-2-2-5-3532-18" />). # '''Низкая профилактическая эффективность'''. Опыт показал, что выдача СИЗ - наихудший и самый неэффективный способ сберечь жизнь и предотвратить ухудшение здоровье рабочих по сравнению с [[:w:Ранжирование методов защиты от вредных производственных факторов |любым другим способом]]. СИЗ должны использоваться лишь когда [[:w:средства коллективной защиты |средства коллективной защиты]] оказались недостаточно эффективны<ref name="ACGIH-28" />. В Конвенции 148<ref name="Конвенция148" /> [[:w:Международная организация труда |Международной организации труда]], ратифицированной РФ, статьи 9 и 10 прямо и однозначно требуют в первую очередь улучшать [[:w:Гигиенические нормирование#Классы (подклассы) труда|условия труда]], и использовать СИЗ лишь при невозможности снизить вредное воздействие до допустимого. Из-за неэффективной политики [[:w:ru:Министерство труда и социальной защиты Российской Федерации|Минтруда]] доля [[:w:ru:Рабочее место|рабочих мест]] с вредными и опасными условиями труда за 1996-2014 гг. выросла с 17 до 39,7% ([[:w:Федеральная служба государственной статистики |Росстат]]<ref name="Росстат-2016" />). Рост доли рабочих мест с опасными для здоровья условиями труда привёл к тому, что, по данным [[:w:Измеров, Николай Федотович |академика Н. Ф. Измерова]]<ref name="Измеров-2008">{{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1771522810&archive=&start_from=&ucat=& |автор=Измеров Н.Ф.|часть= Перспективные пути реализации охраны здоровья работающего населения в ближайшее десятилетие|заглавие= Материалы III Всероссийского съезда врачей-профпатологов |издание= 24-26 сентября 2008 |ответственный= [[:w:Измеров, Николай Федотович|Измеров Н.Ф.]] и др. отв. ред.|год=2008|место= Новосибирск |издательство= Югус-Принт|isbn=5-87545-113-1 |страницы= 8-21 |страниц=596|тираж=1000}} [https://ohranatruda.ru/fond/fail_obmen/106/617058/ копия]</ref> и [[:w:Медведев, Дмитрий Анатольевич |Д. Медведева]]<ref name="ПЗ-2007" /> уже в 2007 году ежегодно умирало около 190 тыс. человек - хотя продажа СИЗ в 2001-2017 гг. выросла в 7 раз<ref name="Сорокин-2018" />. При использовании СИЗ для защиты от токсичных химических и/или [[:w:Радиоактивный распад|радиоактивных веществ]], в газообразном состоянии и/или в виде аэрозолей, и от опасных микроорганизмов, недостаточное внимание к [[:w:ru:Дегазация (оружие)|дегазации]], обеспыливанию, [[:w:ru:Дезинфекция|дезинфекции]], [[:w:ru:Дезактивация|дезактивации]], может сделать СИЗ переносчиком загрязнений в чистые места, вторичным источником опасного загрязнения воздуха и помещений<ref name="Щербаков-1976" />. {| class="wikitable collapsible collapsed" style="text-align:center" ! colspan="9" | Эргономическая характеристика СИЗ<ref name="Каминский2020">{{Книга |автор=Каминский С.Л. |заглавие=Средства индивидуальной защиты в охране труда |ответственный=рецензенты проф. Русак О.Н., Гендлер С.Г. |год=2020 |часть=Глава 2. Эргономическая характеристика СИЗ |издание=2-е изд. |место =Санкт-Петербург |издательство=Проспект Науки |страницы=29 |всего страниц=304 |isbn=978-5-903090-48-8 |тираж=300}}</ref> |- ! Воздействие СИЗ на !! изолирующие костюмы !! СИЗОД !! спецодежда !! спецобувь !! СИЗ рук !! СИЗ головы !! СИЗ лица и глаз !! противошумы |- | дыхание || сопротивление дыханию, подача воздуха, концентрация СО<sub>2</sub> || сопротивление дыханию, концентрация СО<sub>2</sub> || — || — || — || — || — || — |- | терморегуляцию || colspan="3" | температура тела, кожи; теплосодержание; частота сердечных сокращений; потоотделение || температура кожи ступней || температура кожи рук || водопоглощение || — || — |- | работу мышц || масса, ограничение подвижности, работоспособность || масса, ограничение подвижности, давление на лицо, работоспособность || масса, ограничение подвижности, работоспособность || масса || масса || colspan="3" | масса, давление |- | восприятие и общение || поле и острота зрения, заглушение звуков || поле и острота зрения, заглушение звуков || — || — || чувствительность рук || поле зрения || поле и острота зрения || заглушение звуков |} == Источники == {{примечания|refs= <ref name="ОТиСС-2016">{{статья|автор=[[:w:ru:Капцов, Валерий Александрович|В. Капцов]], А. Филин|заглавие=СИЗ - не панацея|ссылка= http://www.otiss.ru/links/arhiv_otiss_2016.html|автор издания=Группа изданий «Охрана труда и социальное страхование»|издание=Охрана труда и социальное страхование|место=Москва|год=2016|номер=8|страницы=74—79}} ISSN 0131-2618</ref> <ref name="Уши-1968">{{Книга|ссылка= https://archive.org/details/DTIC_AD0670869 |автор=Milton Alexander, Lloyd L. Laubach|заглавие=Anthropometry of the human ear. A photogrammetric study of USAF flight personnel|год=1968|язык=en|место=Wright-Patterson Air Forse Base, Ohio|издательство=Aerospace Medical Research Laboratories|allpages=38|серия=AMRL-TR-67-203}}</ref> <ref name="AIHA-2018">{{Книга|ссылка=https://www.aiha.org/education/marketplace/noise-manual-6th-edition|автор=Elliott H. Berger & Jérémie Voix|часть=Chapter 11. Hearing Protection Devices|заглавие=The Noise Manual|издание=6th ed|ответственный=D.K. Meinke, E.H. Berger, R. Neitzel, D.P. Driscoll & K. Bright eds|год=2020|язык=en|место=Falls Church|издательство=American Industrial Hygiene Association|ссылка часть=https://online-ams.aiha.org/amsssa/ecssashop.show_product_detail?p_mode=detail&p_product_serno=2719|страницы=257|страниц=621}}</ref> <ref name="ОТС-2016">{{Статья|автор=Елена Медынцева|заглавие=За смерть строителя никто не платит и никто не отвечает|ссылка=http://ancb.ru/publication/read/2247|издание=Охрана труда и техника безопасности в строительстве|год=2016|месяц=4|номер=4|страницы=32—34|автор издания=ИД "Панорама"|место=Москва|издательство=Стройиздат|archivedate=2019-08-30|archiveurl=https://web.archive.org/web/20190830104233/http://ancb.ru/publication/read/2247}} ISSN 2074-8795 (первая публикация в: «Агентство Новостей „Строительный Бизнес“») Цитата: "... иногда инспекторы договариваются со следователями – и несчастный случай просто исчезает ... судьи в принципе не понимают, как нужно разбирать эти дела в условиях изменившегося законодательства ... есть уже 9 случаев, когда пострадавшие отказывались судиться с застройщиком - боялись потерять работу ... истцы очень часто просят выплатить компенсацию, но не просят выплатить ущерб от утраты работоспособности - зачастую просто не знают об этом ..." </ref> <ref name="волк">{{Статья|автор=Рябов А.А.|заглавие=Юлия Волк: "Под контролем женщины порядка больше"|ссылка=https://www.btpnadzor.ru/archive/yuliya-volk-pod-kontrolem-zhenshchiny-poryadka-bolshe|язык=ru|издание=Безопасность труда в промышленности|год=2010|месяц=март|число=1|номер=3|страницы=12-15|автор издания=Федеральная служба по экологическому, технологическому и атомному надзору (РОСТЕХНАДЗОР); Закрытое акционерное общество «Научно-технический центр исследований проблем промышленной безопасности» (ЗАО НТЦ ПБ)|место=Москва|издательство=ЗАО "Алмаз-Пресс"}} ISSN 0409-2961 [https://www.elibrary.ru/item.asp?id=13081135 PDF] Цитата: "... Что это за наказание? На предприятии иной нарушитель смеётся над нашим наказанием. Говорит: дайте мне десять квитанций, а сразу же весь штраф вперёд оплачу, и буду делать по-своему! Тут даже суд бессилен. ... В каком случае возможна дисквалификация? Она отвечает: "Ну, для этого надо похоронить не меньше пяти-семи человек!" ... " </ref> <ref name="Басов-1974">{{статья|автор=|заглавие= Всё зависит от нас самих|автор издания=Государственный Комитет по надзору за безопасным ведением работ в промышленности и горному надзору при Совете Министров СССР|издание=Безопасность труда в промышленности|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1753284441&archive=&start_from=&ucat=& |место=Москва|издательство=|год=1974|номер=9|страницы=7-11}} ISSN 0409-2961</ref> <ref name="Беляков-06-2015">{{статья|автор=Беляков Г.И., Юлкин Е.С.|заглавие=Специальную оценку условий труда пора корректировать|ссылка=https://www.elibrary.ru/item.asp?id=23636794 |язык=ru|автор издания=Федеральная служба по экологическому, технологическому и атомному надзору (РОСТЕХНАДЗОР); Закрытое акционерное общество «Научно-технический центр исследований проблем промышленной безопасности» (ЗАО НТЦ ПБ)|издание=Безопасность труда в промышленности|место=Москва|издательство=ЗАО "Алмаз-Пресс"|год=2015|номер=6|страницы=55—59}} ISSN 0409-2961</ref> <ref name="ФСС-2022">{{Книга|ссылка=https://sfr.gov.ru/files/id/press_center/godovoi_otchet/fss/FSS_annual_report_2021.pdf|автор=ФСС|заглавие=Отчёт Фонда Социального Страхования Российской Федерации за 2021 год|год=2022|часть=Структура предупредительных мер по сокращению производственного травматизма и профзаболеваний (по статьям расходов) за 2021 год (в млн. руб.)|место=Москва|издательство=ФСС|страницы=13|страниц=31|серия=Социальное страхование: практика и ориентиры развития}}</ref> <ref name="Росстат-2016">''Росстат.'' Социально-экономические показатели Российской Федерации в 1991-2016 гг. (1,2 Мб). ''www.gks.ru'' (2017). Дата обращения: 16 сентября 2018. [https://web.archive.org/web/20180916201927/http://www.gks.ru/wps/wcm/connect/rosstat_main/rosstat/ru/statistics/publications/catalog/doc_1270707126016 копия] , [https://web.archive.org/web/20180916201927/http://www.gks.ru/free_doc/doc_2017/year/pril_year17-rus.xls таблица xls]</ref> <ref name="Капцов-2016">{{Статья|ссылка=https://naukaru.ru/ru/nauka/article/10152/view |автор=Капцов В.А., Чиркин А.В|заглавие= Об оценке эффективности средств индивидуальной защиты органов дыхания |год=2015|место=Москва|издание=Безопасность в техносфере |издательство=ИНФРА-М |том=4 |номер=5 |страницы=7-14|doi=10.12737/16958}} ISSN 1998-071X [https://www.researchgate.net/publication/290476070_On_Evaluation_of_Effectiveness_of_Respiratory_Protective_Devices PDF]</ref> <ref name="Howie-1"> ''Robin Howie.'' Recommendation 1 (слайд № 82). In: [https://www.arbeidshygiene.nl/symposium/vorige-symposia/symposium-2012/ Reality of PPE performance]. Het 21ste NVvA symposium: "Beheersmaatregelen onder de loep" (28 - 29 maart 2012, Zeist) <small>(англ.).</small> ''Nederlandse Vereniging voor Arbeidshygiëne www.arbeidshygiene.nl'' p. 82. Eindhoven, Nederland: Nederlandse Vereniging voor Arbeidshygiëne (2012). Дата обращения: 5 ноября 2024. [https://www.arbeidshygiene.nl/-uploads/files/insite/1-presentation-reality-of-ppe-performance-nvva-march-2012.pdf PDF]</ref> <ref name="Howie-2">{{Статья|ссылка=https://academic.oup.com/annweh/issue/42/2|заглавие=Robin Howie President of the BOHS 1997–1998|год=1998|язык=en|автор издания=British Occupational Hygiene Society|издание=The Annals of Occupational Hygiene|издательство=Oxford University Press|месяц=2|выпуск=2|pages=71-72|volume=42|doi=10.1093/annhyg/42.2.71}} ISSN 2398-7308</ref> <ref name="ХимЗащОдежда-2017">{{Книга |автор=CEN/TC 162/WG 3 - Protective clothing against chemicals, infective agents and radioactive contamination |заглавие=PD CEN/TR 15419:2017 Protective clothing - Guidelines for selection, use, care and maintenance of chemical protective clothing |ответственный=European Committee for Standardization (CEN) |год=2017 |часть=4.6 Garment material selection criteria (definition of CPC material criteria) |язык=en |издание=2nd ed |место=Brussels, Belgium |издательство=British Standards Institution |pages=13-17 |allpages=49 |серия=ICS 13.340.10 Protective clothing |isbn=978 0 580 98705 2}}</ref> <ref name="Капцов-2022">{{Статья|ссылка=https://www.rjhas.ru/jour/article/view/2011/1419|автор=Капцов В.А., Панкова В.Б., Чиркин А.В.|заглавие=Риск многократного применения противогазных фильтров респираторов (обзор литературы)|год=2022|автор издания=Роспотребнадзор|издание=Гигиена и санитария|том=101 |номер=2|страницы=174-179 |doi=10.47470/0016-9900-2022-101-2-174-179|archivedate=2023-05-19 |archiveurl= https://web.archive.org/web/20230519150148/https://www.rjhas.ru/jour/article/view/2011/1419}} ISSN 0016-9900 [https://www.researchgate.net/publication/359302765_The_risk_of_multiple_uses_of_respirator_gas_filters_literature_review копия] </ref> <ref name="Сорокин-2007-5">{{Книга|автор=Карнаух Н.Н., Пашнин Н.П., Сорокина Т.Ю., Шувалов Е.С., Файнбург Г.З.|заглавие=Средства индивидуальной защиты. Учебное пособие|ответственный=Президент АСИЗ [https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ю.Г. Сорокин], А.Л. Сафонов|год=2007|часть=3. Средства индивидуальной защиты органов дыхания. В: II. Средства индивидуальной защиты; |издание=3 изд|место=Москва|издательство="Золотой телёнок", Минздравсоцразвития РФ|страницы=72-76|страниц=288|серия=Охрана труда|isbn=978-5-88257-099-5|тираж=10 000}}</ref> <ref name="Денисов-2013">{{Статья|ссылка=https://cyberleninka.ru/article/n/problema-realnoy-effektivnosti-individualnoy-zaschity-i-privnosimyy-risk-dlya-zdorovya-rabotnikov-obzor-literatury/viewer|автор=Денисов Э.И., Морозова Т.В., Аденинская Е.Е., Курьеров Н.Н.|заглавие=Проблема реальной эффективности индивидуальной защиты и привносимый риск для здоровья работников (обзор литературы)|год=2013|автор издания=НИИ медицины труда РАН|издание=Медицина труда и промышленная экология|месяц=8|номер=8|страницы=18-25|}} ISSN 1026-9428, {{PMID|24006620}}</ref> <ref name="CCOHS-2025">''Canadian Centre for Occupational Health and Safety.'' [https://www.ccohs.ca/oshanswers/prevention/ppe/designin.html Personal Protective Equipment]. OSH Answers Fact Sheets -- Prevention and Control of Hazards <small>''(англ.).''</small> ''www.ccohs.ca.'' Hamilton (Ontario, Canada): CCOHS (21 января 2025). Дата обращения: 9 сентября 2025.</ref> <ref name="Suruda-2003">{{статья|автор= Anthony Suruda, William Milliken, Dale Stephenson & Richard Sesek|заглавие=Fatal Injuries in the United States Involving Respirators, 1984-1995|ссылка= https://www.researchgate.net/publication/10856558_Fatal_Injuries_in_the_United_States_Involving_Respirators_1984-1995 |язык=en |издание=Applied Occupational and Environmental Hygiene |издательство=Taylor & Francis |год=2003| volume=18|выпуск=4|pages=289-292 |doi= 10.1080/10473220301405}}, ISSN 1521-0898, {{PMID|12637239}}. CDC [https://stacks.cdc.gov/view/cdc/186373/cdc_186373_DS1.pdf PDF]</ref> <ref name="Буянов-1974">{{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731671688&archive=&start_from=&ucat=&|автор=Буянов В.В.|заглавие=Проблемы индивидуальной защиты человека. Часть 1|ответственный=[[:w:ru:Городинский, Семён Михайлович|С.М. Городинский]] (ред.)|год=1974|часть=Исследования физической работоспособности при воздействии на человека неблагоприятных факторов, обусловленных средствами индивидуальной защиты|место=Москва|издательство=ВНИИ медицинской и медико-технической информации|страницы=14-15|страниц=86|серия=научный обзор|тираж=1500}}</ref> <ref name="Полоний-1980">{{Книга|автор=Н.Б. Борисов, [[:w:ru:Ильин, Леонид Андреевич|Л.А. Ильин]], У.Я. Маргулис, Г.М. Пархоменко, В.Т. Хрущ.|заглавие=Радиационная безопасность при работе с полонием-210|ответственный=И.В. Петрянов ред|год=1980|часть=7. Средства индивидуальной защиты, в: Глава 6. Гигиена труда при работе с полонием|место=Москва|издательство=Атомиздат|страницы=172-180|страниц=262|тираж=1300}}</ref> <ref name="ГОЧС-7-2006">{{Книга|ссылка=https://xn--b1ae4ad.xn--p1ai/library/86|автор=Галушкин Б.А., Азаров С.Г., Багаев Н.С., Грачев М.И., Клочков В.Н., Коростин А.С, Кунцевич А.А., Петросян Л.Н., Семенов В.В., Харичев Н.И.|заглавие=Справочник спасателя: Книга 7: Спасательные работы по ликвидации последствий радиоактивных загрязнений|ответственный=ВНИИ ГОЧС|год=2006|часть=Пункт 5.2.5. в|место=Москва|издательство=Рекламно-издательский комплекс “Галерия”|страницы=51|страниц=152|тираж=1500}} "... следует учитывать, что наряду с защитным эффектом некоторые виды СИЗ оказывают нежелательное воздействие на функциональные системы организма человека, затрудняя его теплообмен с окружающей средой или создавая трудности, проявляющиеся в сопротивлении дыханию, давлении лицевых частей СИЗ на мягкие ткани головы, ограничении поля зрения и слуха, либо ухудшении разборчивости речи и т.п." </ref> <ref name="Буянов-2001-">{{Книга|автор=Буянов В.В., Супрун И.П.|заглавие=Средства индивидуальной защиты для работ в микробиологических и вирусологических лабораториях|ответственный=научн. консульт. Т.Н. Калинин|год=2001|часть=Глава 7. Работоспособность человека в средствах индивидуальной защиты|место=Черноголовка|издательство=Институт проблем химической физики|страницы=166-237|страниц=324|серия=Государственный научно-исследовательский институт биологического приборостроения|isbn=5-201-10416-7|isbn2=5-201-10416-9}}</ref> <ref name="Sinkule-2013">{{Статья|ссылка=https://academic.oup.com/annweh/article/57/3/384/230992|автор=E.J. Sinkule, J.B. Powell, F.L. Goss|заглавие=Evaluation of N95 respirator use with a surgical mask cover: effects on breathing resistance and inhaled carbon dioxide|год=2013|язык=en|автор издания=British Occupational Hygiene Society|издание=The Annals of Occupational Hygiene|издательство=Oxford University Press|выпуск=3|pages=384—398|volume=57|doi=10.1093/annhyg/mes068}} ISSN 0003-4878, {{PMID|23108786}}</ref> <ref name="ГН-2-2-5-3532-18">{{Книга|автор=''(Роспотребнадзор)''|заглавие=ГН 2.2.5.3532-18 «Предельно допустимые концентрации (ПДК) вредных веществ в воздухе рабочей зоны»|ответственный=утверждены [[:w:ru:Попова, Анна Юрьевна|А. Ю. Поповой]]|место=Москва|год=2018|страниц=170|ссылка=https://www.rospotrebnadzor.ru/documents/details.php?ELEMENT_ID=9967|серия=Санитарные правила}}; новая редакция {{книга|автор=|часть=II. Химические и биологические факторы производственной среды. Таблица 2.1 Предельно допустимые концентрации (ПДК) загрязняющих веществ в воздухе рабочей зоны | ссылка= http://publication.pravo.gov.ru/Document/View/0001202102030022 |ответственный=Попова А.Ю. |заглавие= СанПиН 1.2.3685-21 "Гигиенические нормативы и требования к обеспечению безопасности и (или) безвредности для человека факторов среды обитания"|место=Москва|издательство= Роспотребнадзор |год=2021 |страницы= |страниц= 516|серия=Санитарные правила и нормы}}</ref> <ref name="СИЗ-2005">{{книга|автор=Файнбург Г.З., Овсянкин А.Д. |часть= 7.4 Инфраструктура обеспечения работников средствами индивидуальной защиты |заглавие=Использование средств индивидуальной защиты от неблагоприятного воздействия производственной среды |издание=7 изд., исправленное и дополненное |место= Пермь |издательство= Отдел публикаций Пермского областного центра охраны труда на базе [[:w:Пермский государственный университет| ПГТУ]]|год=2005 |страницы= 187 |всего страниц= 212|isbn= 5-88151-360-6 |серия= Рекомендовано Департаментом условий и охраны труда Минтруда России в качестве учебного пособия для обучения и проверки знаний работников по охране труда, включая обучение отдельных категорий застрахованных |ответственный=Рецензенты Радостев М.А. ''<small>(ЗАО «Пермь-Восток-Сервис»)</small>'', ктн Коротаев В.Ф. ''<small>(Пермский государственный технический университет)</small>''|тираж=1900|}}</ref> <ref name="ACGIH-28">{{книга|автор=[[:w:Американская ассоциация государственных промышленных гигиенистов|ACGIH]] Industrial Ventilation Committee members |заглавие=Industrial Ventilation. A Manual of Recommended Practice for Design|издание=28 ed|место=Cincinnati, Ohio|издательство=[[:w:Американская ассоциация государственных промышленных гигиенистов|American Conference of Governmental Industrial Hygienists]]|год=2013|страницы=Глава 1, стр. 9|allpages=370|isbn=978-1-607260-57-8}}</ref> <ref name="Конвенция148">Конвенция [[:w:Международная организация труда |Международной организации труда]] № 148 {{Cite web |url=http://www.ilo.org/wcmsp5/groups/public/---ed_norm/---normes/documents/normativeinstrument/wcms_c148_ru.htm |title= «О защите трудящихся от профессионального риска, вызываемого загрязнением воздуха, шумом и вибрацией на рабочих местах» (1977) }} (16 октября 2024). [https://docs.cntd.ru/document/1900829 Официальный перевод]</ref> <ref name="Росстат-2016">''Росстат.'' Социально-экономические показатели Российской Федерации в 1991-2016 гг. (1,2 Мб). ''www.gks.ru'' (2017). Дата обращения: 16 сентября 2018. [https://web.archive.org/web/20180916201927/http://www.gks.ru/wps/wcm/connect/rosstat_main/rosstat/ru/statistics/publications/catalog/doc_1270707126016 копия] , [https://web.archive.org/web/20180916201927/http://www.gks.ru/free_doc/doc_2017/year/pril_year17-rus.xls таблица xls]</ref> <ref name="ПЗ-2007">{{Статья|ссылка=https://rg.ru/2007/03/01/medvedev.html|автор=Павел Дульман|заглавие=Компании обещали заняться здоровьем работников (Дмитрий Медведев призвал крупный бизнес активнее заниматься здоровьем работников)|год=2013|автор издания=ФГБУ «Редакция «Российской газеты»|место=Москва|издание=Российская газета|издательство=АО "Издательство "Российская газета"|тип=газета|месяц=3|число=1|номер=42|archive-date=2023-10-28|archive-url=https://web.archive.org/web/20231028112659/https://rg.ru/2007/03/01/medvedev.html|url-status=live}} ISSN 1606-5484</ref> <ref name="Сорокин-2018">{{Статья|ссылка=https://getsiz.ru/asiz-2018-ne-vse-eshche-skazano.html|автор=[https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Сорокин Ю.Г.]|заглавие=АСИЗ-2018: не все еще сказано!|год=2018|автор издания=Общество с ограниченной ответственностью «Информационно-аналитическое агентство «Полдень»|место=Томск|издание=Гетсиз.ру|тип=сайт|месяц=12|число=10}}</ref> <ref name="Щербаков-1976">{{Книга |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1751551910&archive=&start_from=&ucat=& |автор=Щербаков В.Л., Еськова-Сосковец Л.С., Коростин А.С.|заглавие=Всесоюзная конференция "Пути повышения качества и эффективности средств индивидуальной защиты и совершенствования методов их оценки" |ответственный=Семёнов А.П., Городинский С.М., Романова И.Г., Цуцков М.Е., Гуда В.А., Леоничева В.Д. (редколлегия) |год=1976 |часть= Методика оценки средств индивидуальной защиты как вторичного источника загрязнения окружающей среды радиоактивными веществами |издание=Всесоюзный центральный совет профсоюзов (ВЦСПС) |место=Москва |издательство=Государственный Комитет Совета Министров СССР по науке и технике |страницы=84-86 |страниц=179 |серия=Тезисы докладов, г. Тбилиси, 13-15 октября 1976 г. |тираж=700}}</ref> <ref name="Роструд-доклад-14">{{Книга |ссылка= https://rostrud.gov.ru/control/soblyudenie-zakonodatelstva-o-trude/?CAT_ID |автор=Роструд |заглавие=Доклад об осуществлении и эффективности в 2014 году государственного надзора и контроля в сфере труда и социальной защиты населения |год=2015 |часть= 1.6. Анализ и оценка эффективности федерального государственного надзора за соблюдением трудового законодательства и иных нормативных правовых актов, содержащих нормы трудового права. В: I. Осуществление и эффективность в 2014 году федерального государственного надзора за соблюдением трудового законодательства и иных нормативных правовых актов, содержащих нормы трудового права |место=Москва |издательство=Федеральная служба по труду и занятости |страницы=75 |страниц=147}} [https://rostrud.gov.ru/upload/iblock/5ad/nadzor_2014.pdf PDF]</ref> <ref name="Роструд-доклад-17">{{Книга |ссылка= https://rostrud.gov.ru/control/soblyudenie-zakonodatelstva-o-trude/?CAT_ID |автор=Роструд |заглавие= Доклад об осуществлении государственного надзора за соблюдением трудового законодательства и иных нормативных правовых актов, содержащих нормы трудового права, и надзора в сфере социальной защиты населения за 2017 год |год=2018 |часть= 4.1.2. Сведения о результатах проведения специальной оценки условий труда в хозяйствующих субъектах Россйской Федерации. В: 4. Проведение государственного контроля (надзора), муниципального контроля |место=Москва |издательство=Федеральная служба по труду и занятости |страницы=38 |страниц=101}} [https://rostrud.gov.ru/upload/iblock/b40/nadzor-2017.docx dokx]</ref> }} 37z541zgky2yc4x4asjec6svapjvibt Средства индивидуальной защиты (обзорная лекция)/Введение 0 35623 270419 267373 2026-10-27T07:04:14Z Jcb 79968 270419 wikitext text/x-wiki '''Средства индивидуальной защиты''' (СИЗ) — один из элементов системы [[:w:ru:Профилактическая медицина |профилактических мероприятий]], используемый тогда, когда не удаётся снизить воздействие [[:w:ru:Вредный производственный фактор |вредных и опасных производственных факторов]] на работников до [[:w:ru:Гигиеническое нормирование|допустимых уровней]], и для защиты от загрязнений. Применение СИЗ - самый [[:w:ru:Ранжирование методов защиты от вредных производственных факторов|последний и самый ненадежный]] способ защиты [[:w:ru:жизнь|жизни]] и [[:w:ru:здоровье|здоровья]]<ref name="Кириллов-2010-26" />. Это средства, носимые [[:w:работник|работником]], и используемые для предотвращения или уменьшения воздействия вредных и опасных производственных факторов, а также для защиты от загрязнения. Из-за сравнительно низкой эффективности (пример<ref name="Groenewold-2014" />) '''''должны''''' применяться лишь тогда, когда защиту рабочих не удалось обеспечить [[:w:ru:Ранжирование методов защиты от вредных производственных факторов|более надёжными способами]]<ref name="OSHA-2023" /> - безопасной конструкцией оборудования, изменением [[:w:ru:Развитие техники и технологии горного дела|технологии]] и организации [[:w:ru:Производство|производственных]] процессов, [[:w:ru:Архитектурное решение|архитектурно-планировочными решениями]] и [[:w:ru:средства коллективной защиты |средствами коллективной защиты]]. СИЗ сочетают в себе разные свойства. Это одновременно и [[:w:ru:Товар|товар]]<ref name="ЕС-директива-товар" />, [[:w:ru:Продажа|продаваемый]] на [[:w:ru:рынок|рынке]]<ref name="Berger-2009" /> [[:w:ru:Поставщик|поставщиками]] и изготовителями с извлечением [[:w:ru:Прибыль|прибыли]]; и предмет (или материал)<ref name="ЕС-директива-товар" />, разрабатываемый и изготавливаемый производителями так, чтобы он мог снижать или устранять воздействие вредных и/или опасных производственных факторов; и носимое или удерживаемое работником устройство (или наносимое на кожу вещество)<ref name="ЕС-директива-рабочие" />, предназначенное для сбережения его жизни и здоровья, и защиты от загрязнений<ref name="МОТ-4+" /><ref name="ILO-4+" />. Эффективность СИЗ зависит от многих факторов, включая правильные выбор и использование<ref name="МР-1975" /><ref name="Крутиков-2002" /><ref name="МОТ-4" /><ref name="ILO-4" />. Поэтому в развитых странах разработаны не только минимальные технические требования к качеству самих СИЗ, но и подробные требования к их выбору и организации применения, которые [[:w:ru:Работодатель|работодатели]] обязаны выполнять. В РФ для большинства СИЗ такие требования не разработаны. Использование СИЗ может значительно уменьшить [[:w:ru:Производительность труда|работоспособность]] человека<ref name="Буянов-2001++" />. Если воздействие вредных производственных факторов опасно, но превышает предельно допустимое не очень сильно, [[:w:ru:сдельная оплата труда|сдельная оплата труда]] может эффективно стимулировать рабочих отказываться от использования СИЗ<ref name="Шафранова-1937-1" /><ref name="Бачанац-1997" />. После [[:w:ru:Распад СССР|распада СССР]] произошло значительное увеличение доли [[:w:ru:Рабочее место|рабочих мест]] с вредными и опасными условиями труда<ref name="Росстат-2016" />. В результате использование СИЗ стало не только последним, но и единственным способом защиты жизни и здоровья для миллионов работников в РФ, доминирующей составляющей в области [[Охрана труда |охраны]] и [[:w:ru:Гигиена труда |гигиены труда]]. В условиях [[:w:ru:Демографический кризис в Российской Федерации|демографического кризиса]] и высокого уровня [[:w:ru:Смертность|смертности]] населения трудоспособного возраста, по данным [[:w:ru:Федеральная служба государственной статистики|Росстата]] за 2023 г., доля затрат на СИЗ достигла 49% от всех затрат на охрану труда<ref name="Росстат-2024" />, что многократно превышает аналогичные показатели в других странах - несмотря на несравненно больший [[:w:ru:Основные средства|износ зданий, машин и оборудования]] на [[:w:ru:Предприятие|предприятиях]] в РФ. В то же время, по данным Росстата<ref name="Росстат-2024" />, затраты российских работодателей на улучшение условий труда, на [[:w:ru:средства коллективной защиты|средства коллективной защиты]] исключительно низкие, и в годовом статистическом отчёте<ref name="форма1Т" /> не учитываются вообще (нет соответствующей графы). По данным [[:w:ru:Социальный фонд России|Социального фонда]], из его средств, выделяемых работодателям на [[:w:ru:Профилактическая медицина|профилактику]] [[:w:ru:Страховой случай|страховых случаев]], в 2021 году расходы на улучшение условий труда и [[:w:ru:Средства коллективной защиты|СКЗ]] были в 240 раз меньше, чем на СИЗ<ref name="ФСС-2022" />. (В 2002 г. закупка СИЗ за счёт средств Фонда социального страхования не предусматривалась вообще<ref name="Барановский-2003" />, в 2012 г. расходы на СИЗ превышали расходы на улучшение условий труда лишь в 32,5 раза<ref name="Барановский-2012" />). При государственной поддержке поставщиков товара продажи СИЗ в РФ интенсивно растут, за 2001-2024 гг. средние затраты на 1 работника возросли с 1,2<ref name="Сорокин-2018" /> до 17,9<ref name="Росстат-2024" /> тыс. рублей. == Источники == {{примечания|refs= <ref name="Кириллов-2010-26">{{книга|автор=[https://www.journal-irioh.ru/jour/article/view/385/375 Кириллов В.Ф]. |заглавие=Гигиена труда|издание=1 изд|ответственный=[[:w:ru:Измеров, Николай Федотович|Измеров Н.Ф]]., [https://www.journal-irioh.ru/jour/article/view/385/375 Кириллов В.Ф]. ред |часть=Глава 26. [http://vmede.org/sait/?page=28&id=Gigiena_truda_izmerov_2010&menu=Gigiena_truda_izmerov_2010 Средства индивидуальной защиты] |место=Москва|издательство= Издательская группа «ГЭОТАР-Медиа» |год=2008 |страницы=440—454|страниц=592|isbn=978-5-9704-3691-2|тираж=1000|серия=Учебник}} 2 изд., перераб. и доп. [https://e-library.sammu.uz/uploads/books/Rus%20tilidagi%20adabiyotlar/Гигиена/%2B%2BГигиена%20труда.pdf 2016]</ref> <ref name="Groenewold-2014">{{Статья|ссылка=https://stacks.cdc.gov/view/cdc/36768|автор=Groenewold M.R., Masterson E.A., Themann C.L., Davis R.R|заглавие=Do hearing protectors protect hearing?|год=2014|язык=en|издание=American Journal of Industrial Medicine|издательство=Wiley Periodicals|месяц=4|число= 3|выпуск=9|pages=1001—1010|volume=57 |doi=10.1002/ajim.22323}} ISSN 1097-0274. {{PMID|24700499}}. Есть [https://ru.wikipedia.org/wiki/Файл:СИЗ_органа_слуха,_и_профилактика_ухудшения_слуха.pdf '''перевод 1'''] [https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1668507313&archive=&start_from=&ucat=&#i2701 '''перевод 2''']</ref> <ref name="OSHA-2023">{{Книга|ссылка=https://www.osha.gov/sites/default/files/publications/osha3151.pdf|автор=Occupational Safety and Health Administration|заглавие=Personal Protective Equipment|ответственный=U.S. Department of Labor|год=2023|часть=Introduction|язык=en|pages=3|allpages=46|серия=OSHA 3151-02R 2023}}</ref> <ref name="ЕС-директива-товар">{{Статья|ссылка=https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=celex%3A32016R0425|автор=The European Parliament and the Council of the European Union|заглавие=Regulation (EU) 2016/425 of the European Parliament and of the Council of 9 March 2016 on personal protective equipment and repealing|год=2016| серия=Council Directive 89/686/EEC (OJ L 81, 31.3.2016, pp. 51–98)|язык=en|издание=Official Journal of the European Union|тип=журнал|месяц=3|число=31|выпуск=L 81 (series L – Legislation)|автор издания= European Union |pages=L 81/51 - L 81/98| |volume=59}} ISSN 1977-0677. С 1989 по 2018 гг. действовала [[:w:ru:Директива 89/686/ЕЭС|предыдущая версия Директивы]].</ref> <ref name="ЕС-директива-рабочие">{{Статья |ссылка=https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A01989L0656-20191120 |автор=The Council of the European Communities |заглавие=Council Directive of 30 November 1989 on the minimum health and safety requirements for the use by workers of personal protective equipment at the workplace (third individual directive within the meaning of Article 16 (1) of Directive 89/391/EEC) (89/656/EEC) |год=1989 (amend. 2007) |язык=en |автор издания=European Union |место=EU |издание=Official Journal of the European Union |тип=журнал |месяц=12 |число=30 |выпуск=L 393 (series L – Legislation) |pages=L 393 / 18 - L 393 / 28 |volume=32 }} ISSN 0378-6978. old [https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=OJ:L:1989:183:FULL PDF] [https://meganorm.ru/mega_doc/dop_norm/52/gost_r_70231-2022_natsionalnyy_standart_rossiyskoy/0/direktiva_N_89_656_ees_soveta_evropeyskikh_soobshchestv_o.html?ysclid=moec7pwxxz657959550 перевод]</ref> <ref name="Berger-2009">{{Статья|ссылка=https://www.tandfonline.com/doi/abs/10.1080/10803548.2009.11076803|автор=Canetto P., Voix J., Berger E.H., Jacques J., & Liedtke M.|заглавие=Hearing Protectors “Real-World” Performance and the European Directive 2003/10/EC|год=2009|язык=en|автор издания=Central Institute for Labour Protection|место=Abingdon, UK|издание=International Journal of Occupational Safety and Ergonomics|издательство=Taylor & Francis|выпуск=2|pages=221—226|volume=15|doi=10.1080/10803548.2009.11076803}} ISSN 1080-3548. {{PMID|19572468}}. [https://www.researchgate.net/publication/321775663_Hearing_protectors_real_world_performance_and_the_European_Directive_200310EC копия]</ref> <ref name="МОТ-4+">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =[https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ю.Г. Сорокин] (''руководитель Департамента условий и охраны труда, Минтруд РФ''); Жан-Виктор Груа (''Директор Московского бюро МОТ'')|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[https://base.safework.ru/iloenc?d&nd=857400283&prevDoc=857400283&spack=110LogLength%3D0%26LogNumDoc%3D857400034%26listid%3D010000000100%26listpos%3D3%26lsz%3D6%26nd%3D857400034%26nh%3D1%26 Гигиена труда: Вмешательство как метод контроля вредного воздействия]. В: Том 1; Раздел [https://base.safework.ru/iloenc?d&nd=857400005&prevDoc=857400283 Раздел IV. Методология и практика], Глава [https://base.safework.ru/iloenc?d&nd=857400034&prevDoc=857400034&spack=110LogLength%3D0%26LogNumDoc%3D857400005%26listid%3D010000000300%26listpos%3D3%26lsz%3D7%26nd%3D857400005%26nh%3D0%26 30. Гигиена труда] |автор=Джеймс Стюарт |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|isbn=|серия= Охрана труда}}</ref> <ref name="ILO-4+">''James Stewart''. [https://iloencyclopaedia.org/part-iv-66769/occupational-hygiene-47504/item/573-occupational-hygiene-control-of-exposures-through-intervention Occupational Hygiene: Control of Exposures Through Intervention]. In: Vol. 1; [https://iloencyclopaedia.org/part-iv-66769/occupational-hygiene-47504 Occupational Hygiene] // [https://iloencyclopaedia.org/ Encyclopedia of Occupational Health and Safety] / Michel Hansenne ed. — 4th ed. — Geneva: International Labour Office, 1998.</ref> <ref name="МР-1975">{{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731668649&archive=&start_from=&ucat=&|автор=Гольдштейн Д.С., Шатский С.Н., Щербаков В.Л., Фаустова Д.Г., Буянов В.В., Купчин А.П.|заглавие=Методические рекомендации по организации контроля за применением и содержанием средств индивидуальной защиты|год=1975|часть=1. Общие положения по организации контроля за применением и содержанием средств индивидуальной защиты|место=Москва|издательство=Институт биофизики|страницы=3—5|страниц=19|тираж=5300}}</ref> <ref name="Крутиков-2002">{{Книга|заглавие=Коллективные и индивидуальные средства защиты. Контроль защитных свойств|ответственный=Крутиков В.Н., Фалеев М.И. (науч. ред.)|год=2002|часть=Введение|место=Москва|издательство=ФИД "Деловой экспресс"|страницы=10|страниц=408|серия=Энциклопедия "Экометрия" из серии справочных изданий по экологическим и медицинским измерениям|isbn=5-89644-076-6}}</ref> <ref name="МОТ-4">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =[https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ю.Г. Сорокин] <small>(''руководитель Департамента условий и охраны труда, Минтруд РФ'')</small>; Жан-Виктор Груа <small>(''Директор Московского бюро МОТ'')</small>|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[http://base.safework.ru/iloenc?d&nd=857400340&prevDoc=857400340&spack=010LogLength%3D0%26LogNumDoc%3D857400038%26listid%3D010000000100%26listpos%3D0%26lsz%3D7%26nd%3D857400038%26nh%3D1%26 Современное состояние индивидуальных средств защиты]. В: Том 1; Раздел [http://base.safework.ru/iloenc?d&nd=857400005&prevDoc=857000002 IV], Глава [http://base.safework.ru/iloenc?d&nd=857400038&prevDoc=857400346 31. Средства индивидуальной защиты] |автор=Роберт Ф. Херрик (автор и редактор раздела СИЗ) |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|isbn=|серия= Охрана труда}}</ref><ref name="ILO-4">''Robert F. Herrick''. [https://iloencyclopaedia.org/part-iv-66769/personal-protection-59388/item/686-overview-and-philosophy-of-personal-protection Overview and Philosophy of Personal Protection]. In: Vol. 1; [https://iloencyclopaedia.org/part-iv-66769/personal-protection-59388 Chapter 31. Personal Protection] // [https://iloencyclopaedia.org/ Encyclopedia of Occupational Health and Safety] / Michel Hansenne ed. — 4th ed. — Geneva: International Labour Office, 1998.</ref> <ref name="Буянов-2001++">{{Книга |автор=Буянов В.В., Супрун И.П. |заглавие=Работоспособность человека в средствах индивидуальной защиты |ответственный=дтн. проф. Ю.Т. Калинин |год=2001 |часть=3.3 Влияние термических воздействий на работоспособность человека при использовании хлопчатобумажной спецодежды и фильтрующего противогаза |место=Черноголовка |издательство=Государственный научный центр "Государственный НИИ биологического приборостроения" |страницы=53 |страниц=113 |isbn=5-201-10416-9 |тираж=100}} Цитата: "При температуре воздуха в камере 18-20° ... Способность к тонкой координации движений уже после первого часа работы снизилась на 46,3% от исходной величины."</ref> <ref name="Шафранова-1937-1">{{Книга|автор=Шафранова А.С.|заглавие=Индивидуальная защита глаз рабочего на производстве|ответственный=ВЦСПС, Московский научно-исследовательский институт охраны труда|год=1937|часть=Предисловие; 1. Защита глаз на производстве|место=Москва|издательство=Профиздат|страницы=4; 7-8|страниц=48|тираж=15300|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1738063241&archive=&start_from=&ucat=&}} [https://files.library.by/dl/files/СИЗ%20глаз%201937%20%2048%20с.pdf PDF] '''Цитаты''': "<small>ФЗМК и общественные инспектора по охране труда должны взять под особый контроль всю систему выписки и назначения рабочим очков и других приспособлений.</small> Очень часто эти назначения производятся формально-бюрократически, неправильно, не по глазам рабочего, что вместо пользы даёт только вред. <small>В этих случаях рабочие отказываются носить выданные очки и по существу работают без защитных приспособлений.</small> Защитные приспособления должны помогать рабочим, а не стеснять их, не мешать работе." с. 4; "'''Почему же рабочие так часто отказываются от ношения защитных очков?''' Всякий предмет, надеваемый на лицо человека, так или иначе стесняет его; и обычно, чем лучшую защиту дают те или иные очки, тем больше неудобств они причиняют. Понятно, что рабочий, уже привыкший работать без очков, возражает против них, так как ему приходится приспосабливаться к новым условиям и '''он боится снижения уже достигнутой производительности труда.''' " с. 7-8.</ref> <ref name="Бачанац-1997">{{Статья|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1748444042&archive=&start_from=&ucat=&|автор=Бачанац М.|заглавие=Профилактика офтальмокониоза у рабочих ФВК Кралево|год=1997|место=Москва|издание=Медицина труда и промышленная экология|издательство=НИИ медицины труда РАМН|месяц=4|номер=4|страницы=37—38}} ISSN 1026-9428.</ref> <ref name="Росстат-2016">''Росстат.'' Социально-экономические показатели Российской Федерации в 1991-2016 гг. (1,2 Мб). ''www.gks.ru'' (2017). Дата обращения: 16 сентября 2018. [https://web.archive.org/web/20180916201927/http://www.gks.ru/wps/wcm/connect/rosstat_main/rosstat/ru/statistics/publications/catalog/doc_1270707126016 копия] , [https://web.archive.org/web/20180916201927/http://www.gks.ru/free_doc/doc_2017/year/pril_year17-rus.xls таблица xls]</ref> <ref name="Росстат-2024">{{Книга|ссылка=https://rosstat.gov.ru/folder/11110/document/13264|автор=Главный межрегиональный центр (ГМЦ)|заглавие=Состояние условий труда работников организаций Российской Федерации по отдельным видам экономической деятельности|ответственный=Федеральная служба государственной статистики (РОССТАТ)|год=2024-04-25|часть=Том IV. Фактические расходы на компенсации и средства индивидуальной защиты в организациях по субъектам Российской Федерации по отдельным видам экономической деятельности по форме собственности (без субъектов малого предпринимательства; в 2023 году)|место=Москва}} [https://rosstat.gov.ru/storage/mediabank/usltr2023.rar RAR]</ref> <ref name="Барановский-2003">{{статья|автор=Барановский И.Г., Измайлова О.В., Субботин В.В., Ткачёв В.В. |заглавие= Анализ основных показателей работы отечественной системы обязательного социального страхования профессиональных рисков|автор издания=НИИ медицины труда РАН|издание=Медицина труда и промышленная экология|ссылка= https://www.journal-irioh.ru/jour/ |место=Москва|издательство=|год=2003|номер=9|страницы=1—8|}} ISSN 1026-9428.</ref> <ref name="Барановский-2012">''Барановский И.Г. (ФСС).'' Слайд № 20 в презентации: [http://www.oaontc.ru/media/filebrowser/prezentacii/22.pdf Роль Фонда социального страхования Российской Федерации в обязательном социальном страховании от несчастных случаев на производстве и профессиональных заболеваний]. XI Всероссийский Форум Единой системы оценки соответствия в области промышленной, экологической безопасности, безопасности в энергетике и строительстве (ЕСОС). г. Сочи, 30 сентября - 4 октября 2013 года.</ref> <ref name="Сорокин-2018">{{Статья|ссылка=https://getsiz.ru/asiz-2018-ne-vse-eshche-skazano.html|автор=[https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Сорокин Ю.Г.]|заглавие=АСИЗ-2018: не все еще сказано!|год=2018|автор издания=Общество с ограниченной ответственностью «Информационно-аналитическое агентство «Полдень»|место=Томск|издание=Гетсиз.ру|тип=сайт|месяц=12|число=10}}</ref> <ref name="форма1Т">''ООО "Группа Актион"''. [https://www.zarplata-online.ru/art/164033-otchet-1-t-usloviya-truda-kak-zapolnit-i-sdat Отчет 1-Т (условия труда): как заполнить и сдать]. Статистическая отчетность. ''www.zarplata-online.ru.'' Журнал «Зарплата» (8 ноября 2024) [https://www.rogwu.ru/content/bl_files_pg/%D0%A4%D0%BE%D1%80%D0%BC%D1%8B%20%E2%84%96%201-%D0%A2%20%28%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%20%D1%82%D1%80%D1%83%D0%B4%D0%B0%29.doc ссылка]</ref> <ref name="ФСС-2022">{{Книга|ссылка=https://sfr.gov.ru/files/id/press_center/godovoi_otchet/fss/FSS_annual_report_2021.pdf|автор=ФСС|заглавие=Отчёт Фонда Социального Страхования Российской Федерации за 2021 год|год=2022|часть=Структура предупредительных мер по сокращению производственного травматизма и профзаболеваний (по статьям расходов) за 2021 год (в млн. руб.)|место=Москва|издательство=ФСС|страницы=13|страниц=31|серия=Социальное страхование: практика и ориентиры развития}}</ref> }} mex1w0o0oxrysuyi0o3ebx025zd2mg5 Средства индивидуальной защиты (обзорная лекция)/Изолирующие костюмы 0 35624 270420 269625 2026-10-27T07:04:42Z Jcb 79968 270420 wikitext text/x-wiki [[Файл:Пневмокостюм.jpg|thumb|250px|Схема пневмокостюма]] Изолирующие костюмы могут использоваться для защиты от радиоактивных загрязнений, химических веществ, вредных биологических факторов, при повышенной или пониженной температуре воздуха. Могут быть вентилируемые и не вентилируемые. Вентилируемые костюмы могут обеспечиваться воздухом по шлангу (например ЛГ-4<ref name="РГ-1962-пк" />); подача воздуха позволяет защищать рабочих от высокой температуры окружающего воздуха<ref name="СИЗ-1973-3" /><ref name="Миронов-4-2009" />. При подаче сжатого воздуха его температура может регулироваться [[:w:ru:Вихревой эффект |вихревым кондиционером]]. Одно из первых упоминаний изолирующих полностью закрытых непроницаемых костюмов, в который принудительно нагнетался воздух по шлангу, относится к периоду начала массового производства [[:w:ru:Боевые отравляющие вещества |отравляющих веществ]], обладавших [[:w:ru:Иприт|кожно-нарывным]] действием<ref name="ХВ-2024" />. == Научные исследования == Ожидалось, что уровень защиты таких СИЗ будет высоким, и их широко использовали при [[:w:ru:Пескоструйная обработка |пескоструйных работах]]. Но [[:w:Производственные испытания респираторов |измерения коэффициентов защиты]] показывали, что по ряду причин фактическая защищённость рабочих бывает очень низкой<ref name="Скляров-1937" />. Этот результат объяснял причину развития [[:w:силикоз|силикоз]]а у "защищённых" работников. Снижение эффективности могло происходить из-за: недостаточного количества подаваемого воздуха, его плохой очистки, наличия зазоров в "скафандре" (в том числе из-за повреждения летящими абразивными частицами)<ref name="Nelson-1975" />. Многие исследования показали, что быстрое движение окружающего воздуха нередко приводит к "поддуванию" загрязнений под неплотно прилегающую лицевую часть СИЗОД, а при пескоструйных работах это происходило постоянно. В результате такую работу стали выполнять в закрытых камерах, а оператор находился снаружи, т.е. заменили ненадёжные СИЗ эффективными средствами коллективной защиты ([[:w:Средства коллективной защиты |СКЗ]]). Позднее пневмокостюмы широко использовались в [[:w:ru:Атомная промышленность |атомной промышленности]], проводилось их изучение<ref name="Городинский-1979" /><ref name="БМЭ-17" />. Практически полное отсутствие просачивания неочищенного воздуха через зазоры обеспечило высокий уровень защиты. Испытания пневмокостюмов на предприятиях [[:w:ru:Химическая промышленность |химической промышленности]] также подтвердили хорошую защищённость работников. При работе в условиях нагревающего микроклимата подача воздуха улучшала микроклимат внутри СИЗ и увеличивала время непрерывной работы (температура воздуха 40-59°С, окружающих поверхностей 50-76°С, непрерывная работа 30-90 минут)<ref name="Ильин-2016+-" />. При удачной конструкции и небольшом избыточном давлении, появление небольших отверстий не приводит к значительному прониканию загрязнений внутрь<ref name="ПК-2012" /><ref name="ПК-2019" />. Поэтому такие СИЗ используют и для работы с опасными микроорганизмами. Использование пневмокостюмов, разработанных для атомной промышленности, обеспечило высокий уровень защиты от [[:w:ru:дихлорметан|дихлорметана]], способного попадать в организм и через кожу<ref name="Хохлов-1979" />. Однако исследования пневмокостюмов разных конструкций показало, что при их использовании современных (в том числе импортных, включая СИЗ, разработанный для атомной промышленности) попадание загрязнений в органы дыхания и на кожу может оказаться гораздо выше ожидаемого (декларируемого). Авторы объяснили это возможным прониканием загрязнений через отверстия для выхода воздуха наружу, и предложили устранить недостаток с помощью последовательного пропускания выходящего воздуха через два клапана, удалённых друг от друга на 30 см. По данным авторов, только такое изменение позволило повысить надёжность защиты при перемещении работника - когда он отключен от линии подачи воздуха, и внутри СИЗ нет избыточного давления<ref name="Буянов-2001" />. {| class="wikitable collapsible collapsed" style="text-align:center" ! colspan="14" | Сравнение защитных свойств разных пневмокостюмов (табл. 4.1 и 4.2<ref name="Буянов-2001" />) |- | rowspan="2" | Конструктивные особенности, коэффициент защиты | colspan="13" | Модель пневмокостюма |- | ЛГ-4 || ЛГ-5 || ''(ЛГ-5)'' || Английский ([[:w:en:Atomic Energy Research Establishment|Харвелл]]) || C-4 Япония || ЛГ-У || Шведский ([[:w:en:Trelleborg (company)|Треллеборг]]) || ПКБ-1 || ПКБ-4 || Антибелок-5 || Антибелок-5У || Антибелок-6 || Антибелок-7 |- | Клапаны выпуска воздуха; расстояние между ними, см | — || — || ''(—)'' || — || — || 1 || 1 || 2; 2-3 || 2; 5 || 2; 10 || 2; 15-17 || 2; 30 || 2; 30 |- | КЗ органов дыхания || ~ 100 || ~ 100 || ''(~ 10<sup>'''5'''</sup>)'' || ~ 1000-10000 || ~ 10 || ~ 1000-10000 || ~ 10000 || ~ 10000 || ~ 10<sup>'''5'''</sup> || ~ 10<sup>'''6'''</sup> || ~ 10<sup>'''7'''</sup> || colspan="2" | загрязнения не обнаружены |- | КЗ кожи || ~ 10 || ~ 10 || ''(~ 90-200)'' || ~ 100 || ~ 1-5 || ~ 1-100 || ~ 100 || ~ 100 || ~ 1000 || ~ 10000 || ~ 10<sup>'''5'''</sup> || ~ 10<sup>'''7'''</sup> || ~ 10<sup>'''6'''</sup> |- style="text-align:left" | colspan="14" | Испытания проводили в аэрозольной камере на испытателях, отбор проб воздуха, загрязнённого малоопасными микроорганизмами, проводился из шлема и из подкостюмного пространства. Температура воздуха в камере 18-23°С, оптимальная подача воздуха в СИЗ 5 л/с. Показатели для (''ЛГ-5''), для сравнения, добавлены по данным из<ref name="Городинский-1979" />, см. ниже<div class="toccolours mw-collapsible mw-collapsed">цитата<div class="mw-collapsible-content">"«Испытания пневмокостюмов ЛГ-5 показали, что их конструкция надёжно защищает тело человека от радиоактивных аэрозолей, за исключением области клапанов, где при резких движениях (выпрямление после приседания) происходит небольшой подсос наружного воздуха в подкостюмное пространство, в результате чего отмечена загрязнённость ног до 2,4·10<sup>5</sup> β-частиц (с площади 150 см<sup>2</sup> в 1 мин). Небольшое усовершенствование пневмокостюмов ЛГ-5 в виде включения в конструкцию лепесткового клапана улучшило его защитную эффективность в 25 раз: загрязнённость ног снизилась до 7×10<sup>3</sup> β-част. /(150 см<sup>2</sup> · 1 мин).</div> |} Из-за того, что шланг ограничивает перемещение рабочего, для химической промышленности разработали автономный вариант<ref name="СИЗ-1986-1" />. А у пневмокостюма ЛГ-У была предусмотрена возможность дышать через загубник и фильтр окружающим воздухом при отключенном шланге подачи воздуха, при отказах и при переходе с одного места на другое<ref name="Полоний-1980" />. [[File:Isolated protective suit.jpg|thumb|310px|right|Изолирующий костюм для использования вместе с дыхательным аппаратом]] == Требования к СИЗ == В США [[:w:Национальный институт охраны труда#Институт и респираторная защита |главный орган по сертификации СИЗ органов дыхания]] не разработал никаких требований к таким средствам защиты, и не сертифицирует их вообще. В Европейском Союзе разработаны требования к таким СИЗ и методам их испытаний, в РФ приняты гармонизированные ГОСТы (примеры<ref name="ПК-евро-2016" /><ref name="ПК-РФ-1" />). == Выбор и применение == Из-за специфичных условий использования, и сравнительно небольшого числа случаев применения (наиболее загрязнённые [[:w:ru:Рабочее место|рабочие места]] на предприятиях атомной и химической отраслей, некоторые [[:w:ru:Атомный ледокол |ледоколы]] и т.п.) общегосударственные требования к их выбору и применению в СССР не разрабатывали. Порядок выбора и использования сложился на основе накопленного опыта, и был отражён в локальных и/или отраслевых документах, примеры<ref name="ПК-А-1983" /><ref name="ПК-А-1986" />. [[File:773rd CST suits up to support U S Navy (6389203).jpg|thumb|right|310px|Изолирующие СИЗ, костюмы и дыхательные аппараты]] == Эффективность == Проводились замеры загрязнённости воздуха внутри пневмокостюмов при их использовании работниками во время трудовой деятельности. Например, по данным<ref name="Гущина-10-2-3" /> эти СИЗ позволили надёжно защитить органы дыхания и кожу при работе с пестицидами. Так, при протравливании зерна в пневмокостюме ПШ-1 концентрация [[:w:1,2-Дибром-3-хлорпропан|немагона]] снизилась более чем в 1100 раз. Это значительно больше, чем у противогазов с маской с панорамным стеклом (коэффициенты защиты: от 11, 17, 17, 21 ... до 3498 - всего 35 замеров<ref name="Tannahill-1990" />), но значительно меньше, чем ожидалось по результатам испытаний в лабораториях. Исправные и правильно применяемые пневмокостюмы, при удачной конструкции и подаче чистого воздуха, могут защищать работника от воздушных загрязнений - но и у них на практике уровни защиты бывают значительно ниже декларируемых разработчиками и поставщиками, и получаемых в контролируемых лабораторных условиях. == Источники == {{примечания|refs= <ref name="ХВ-2024">{{Книга|ссылка=https://library.by/portalus/modules/warcraft/readme.php?subaction=showfull&id=1623926831&archive=&start_from=&ucat=&|автор=Фрайс А. Амос, Клапенс Д. Вест|заглавие=Химическая война|ответственный=М.Н. Соболев (перевод)|год=1924|оригинал= [https://archive.org/details/chemicwar00frierich/page/272/mode/2up Chemical warfare]|часть=Глава XV. Прочие меры защиты|ссылка часть=https://www.rulit.me/books/himicheskaya-vojna-read-541582-66.html|издание=2 изд|место=Москва|издательство=Государственное военное издательство|страницы=307|страниц=518}}</ref> <ref name="РГ-1962-пк">{{Книга|заглавие=Радиационная гигиена|автор=Городинский С.М., Панфилова З.Е., Промптова Н.А., Саулевич Н.М., Филимонов Б.В., Фишевская Э.А., Шатский С.Н., Щербаков В.Л.|ответственный=[[:w:ru:Городинский, Семён Михайлович|Городинский С.М.]], Пархоменко Г.М., Тарасенко Н.Ю. ред|год=1962|место=Москва|издательство=Медгиз|том=1. Гигиена труда|часть= Изолирующие средства защиты работающего. В: Раздел 3. Средства индивидуальной защиты, личная гигиена, и вопросы дезактивации - Глава I. Средства индивидуальной защиты|страницы=104-107|страниц=231| серия=сборник статей|ссылка= https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1756652867&archive=&start_from=&ucat=& |тираж=6000}}</ref> <ref name="Городинский-1979">{{книга|автор=Городинский С.М. |заглавие= Средства индивидуальной защиты для работ с радиоактивными веществами |часть=Исследование защитной эффективности изолирующих костюмов |издание=3 изд |место=Москва |издательство=Атомиздат |год=1979|страницы=162-166|страниц=296 |тираж=5700}}</ref> <ref name="БМЭ-17">{{книга|автор= [[:w:ru:Городинский, Семён Михайлович|С.М. Городинский]], В.П. Михайлов. |часть= [http://бмэ.орг/index.php/ОДЕЖДА_СПЕЦИАЛЬНАЯ Одежда специальная] |часть ссылка= |ответственный=гл. ред. Б.В. Петровский|заглавие=Большая медицинская энциклопедия |издание=3 изд |место=Москва| издательство=Советская энциклопедия |год=1981 |том=17. [http://бмэ.орг/index.php/Категория:Том_17 Ниландера проба - Остеопатии] |томов=30 |страницы= |страниц=512 |тираж=150 800}}</ref> <ref name="Скляров-1937">{{Статья|автор=Скляров Ф.И.|заглавие=Новая конструкция шлема для пескоструйщиков|год=1937|издание=Гигиена труда и техника безопасности|номер=2|страницы=74-76}}</ref> <ref name="Nelson-1975">{{Статья|автор=Samimi B., Nelson A., Weill H. & Ziskind M.|заглавие=The Efficiency of Protective Hoods Used by Sandblasters to Reduce Silica Dust Exposure|год=1975|язык=en|издание=American Industrial Hygiene Association Journal|выпуск=2|pages=140–148|volume= 36|doi=10.1080/0002889758507222}} ISSN 0002-8894, {{PMID|167570}}. [https://stacks.cdc.gov/view/cdc/245967 copy]</ref> <ref name="Ильин-2016+-">{{Книга|автор=[[:w:ru:Городинский, Семён Михайлович|С.М. Городинский]], Т.М. Ефремова, В.Л. Щербаков, Ю.Ф. Малахов.|заглавие=Избранные материалы "Бюллетеня радиационной медицины"|ответственный=[[:w:Ильин, Леонид Андреевич|Л.А. Ильин]], С.А. Самойлов ред|год=2016|часть=Опыт использования средств индивидуальной защиты в период швартовых испытаний атомного ледокола "Ленин"|место=Москва|издательство=ФГБУ ГНЦ ФМБЦ им. А.И. Бурназяна ФМБА России|том=1|страницы=59-70|страниц=912|isbn=978-5-905926-14-3|тираж=500}}</ref> <ref name="Хохлов-1979">{{Статья|автор=Хохлов Е.Н., Смородин Э.А., Миронов Л.А., Синицына И.Д.|заглавие=Опыт использования средств индивидуальной защиты от хлористого метилена|год=1979|автор издания=ЦНИИ "РУМБ"|место=Ленинград|издание=Технология судостроения|издательство=Центральный научно-исследовательский институт "РУМБ"|номер=выпуск 7|страницы=92–94}}</ref> <ref name="СИЗ-1973-3">{{Книга|автор=Диденко Н.С., Карпекин В.В., Ильинский Э.Г., Рыбалко А.П.|заглавие=Пути совершенствования средств индивидуальной защиты работающих на производстве|ответственный=Цуцков М.Е., Городинский С.М., Смирнов В.Ф|год=1973|часть=Разработка средств индивидуальной противопылевой защиты в промышленности|место=Москва|издательство=ВЦНИИОТ ВЦСПС|страницы=254-258|страниц=286|серия=материалы всесоюзного совещания|тираж=3000 |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731670742&archive=&start_from=&ucat=&}}</ref> <ref name="Миронов-4-2009">{{Книга|автор=Миронов Л.А. (Нижегородский НИИ гигиены и профессиональной патологии)|заглавие=Применение средств индивидуальной защиты. Методическое пособие|год=2009|часть=Изолирующие СИЗОД |место=Нижний Новгород|издательство=БИОТА-ПЛЮС|страницы=45-51 |страниц=123|isbn=978-5-902095-19-4|тираж=1000}}</ref> <ref name="ПК-2012">{{Статья|ссылка=https://pmc.ncbi.nlm.nih.gov/articles/PMC3446757/ |автор=Jackie A. Steward, Mark S. Lever.|заглавие=Evaluation of the Operator Protection Factors Offered by Positive Pressure Air Suits against Airborne Microbiological Challenge|год=2012|язык=en|издание=Viruses|издательство=MDPI|месяц=8|число=4|выпуск=8|pages=1202–1211|volume=4|doi=10.3390/v4081202}} ISSN 1999-4915, {{PMID|23012620}}, PMC [https://pmc.ncbi.nlm.nih.gov/articles/PMC3446757/ PMC3446757]. [https://www.researchgate.net/publication/231212347_Evaluation_of_the_Operator_Protection_Factors_Offered_by_Positive_Pressure_Air_Suits_against_Airborne_Microbiological_Challenge copy]</ref> <ref name="ПК-2019">{{Статья|ссылка=https://www.sciencedirect.com/science/article/pii/S2590053619300229?via%3Dihub |автор=Limei Hao, Jian-cheng Qi, Runze Wang, Ying Yi, Jinhui Wu.|заглавие=Protective performance test and safety risk evaluation of a powered air-purifying suit|год=2019|ответственный=Chinese Medical Association Publishing House|язык=en|автор издания=National Institute for Viral Disease Control and Prevention, Chinese Center for Disease Control and Prevention|издание=Biosafety and Health|издательство=Elsevier B.V.|месяц=9|выпуск=2|pages=91-97|volume=1|doi=10.1016/j.bsheal.2019.08.002}} ISSN 2590-0536. [https://www.researchgate.net/publication/335643553_Protective_performance_test_and_safety_risk_evaluation_of_a_powered_air-purifying_suit copy]</ref> <ref name="Буянов-2001">{{Книга|автор=Буянов В.В., Супрун И.П.|заглавие=Средства индивидуальной защиты для работ в микробиологических и вирусологических лабораториях|ответственный=научн. консульт. Т.Н. Калинин|год=2001|часть=4.1. Сравнительные исследования отечественных и зарубежных шланговых изолирующих СИЗ ; 4.2. Разработка шланговых изолирующих СИЗ с высокими защитными свойствами|место=Черноголовка|издательство=Институт проблем химической физики|страницы=86, 92|страниц=324|серия=Государственный научно-исследовательский институт биологического приборостроения|isbn=5-201-10416-7|isbn2=5-201-10416-9}}</ref> <ref name="Полоний-1980">{{Книга|автор=Н.Б. Борисов, [https://ru.wikipedia.org/wiki/Ильин,_Леонид_Андреевич Л.А. Ильин], У.Я. Маргулис, Г.М. Пархоменко, В.Т. Хрущ.|заглавие=Радиационная безопасность при работе с полонием-210|ответственный=И.В. Петрянов ред|год=1980|часть=7. Средства индивидуальной защиты, в: Глава 6. Гигиена труда при работе с полонием|место=Москва|издательство=Атомиздат|страницы=172-180|страниц=262|тираж=1300}}</ref> <ref name="СИЗ-1986-1">{{Книга|автор=Шарнин Г.П., Жиляев Г.Г., Жуков В.И., Козлов И.Л., Иванова Р.С., Булюхина М.М.|заглавие=Разработка средств индивидуальной защиты для работников химической промышленности и методов их оценки |ответственный=Бутова Т.Н. отв. ред|год=1986|часть=Пути совершенствования автономных комплектов|место=Черкассы|издательство=ВНИИТЭХИМ |страницы=12-13|страниц=105|серия=Тезисы докладов Всесоюзной конференции, Северодвинск, октябрь 1986 г.|тираж=300 |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731670742&archive=&start_from=&ucat=&}}</ref> <ref name="ПК-евро-2016">{{Книга|автор=CEN / Technical Committee 162 - Protective clothing including hand and arm protection and lifejackets: WG 3 - Protective clothing against chemicals, infective agents and radioactive contamination.|ссылка=https://knowledge.bsigroup.com/products/protective-clothing-against-solid-airborne-particles-including-radioactive-contamination-requirements-and-test-methods-for-compressed-air-line-ventilated-protective-clothing-protecting-the-body-and-the-respiratory-tract?version=standard|заглавие=BS EN 1073-1:2016+A1:2018 Protective clothing against solid airborne particles including radioactive contamination - Requirements and test methods for compressed air line ventilated protective clothing, protecting the body and the respiratory tract|ответственный=European Committee for Standardization|год=2016|язык=en|место=Brussels|издательство=British Standards Institution|allpages=13|серия=ICS 13.280; 13.340.10|isbn=978 0 580 98704 5}}</ref> <ref name="ПК-РФ-1">{{Книга|автор=Институт биофизики Минздрава Российской Федерации|заглавие=ГОСТ Р 12.4.196-99. ССБТ. Костюмы изолирующие. Общие технические требования и методы испытаний|ответственный=ТК-320 СИЗ|год=1999|место=Москва|издательство=ИПК Издательство стандартов|страниц=16|серия=ОКС 13.340.01|тираж=402|ссылка=https://meganorm.ru/Index2/1/4294814/4294814109.htm}} [https://meganorm.ru/Data2/1/4294814/4294814109.pdf PDF]</ref> <ref name="ПК-А-1983">{{Книга|автор=Гольдштей Д.С., Кощеев В.С.|заглавие=Организация индивидуальной защиты в атомной промышленности|ответственный=Синьковский В.В рецензент|год=1983|часть=3.3. Применение изолирующих костюмов. В: Глава 3. Особенности применения отдельных видов СИЗ|место=Москва|издательство=Энергоатомиздат|страницы=42-45|страниц=96|тираж=2200}}</ref> <ref name="ПК-А-1986">{{Книга|автор=В.Н. Бескрестнов составитель.|заглавие=Методическое руководство по индивидуальной защите персонала атомных станций и физиолого-гигиенические требования к изолирующим средствам индивидуальной защиты|год=1986|часть=3.3. Применение изолирующих костюмов|издание=Выпуск 10|место=Москва|издательство=Энергоатомиздат|страницы=15-17|страниц=48|серия=Библиотека эксплуатационщика АЭС|тираж=6300}}</ref> <ref name="Гущина-10-2-3">{{Книга |автор=Гущина Татьяна Викторовна |заглавие=Методология разработки и испытаний средств индивидуальной защиты |ответственный=рецензенты Киричек А.В., Шарупич Т.С. |год=2007 |часть=10.2.3 Средства защиты от токсичных веществ (Пневматические средства защиты). В: 10 Производственная апробация средств индивидуальной защиты в условиях АПК, разработка рекомендаций. 10.2 Проведение производственных испытаний |место=Орёл |издательство=Издательство ОрёлГАУ |страницы=274-278 |всего страниц=330 |серия=Монография |тираж=100}}</ref> <ref name="Tannahill-1990">{{статья|автор=Tannahill S.N., R.J. Willey and M.H. Jackson|заглавие=Workplace Protection Factors of HSE Approved Negative Pressure Full-Facepiece Dust Respirators During Asbestos Stripping: Preliminary Findings|ссылка=http://annhyg.oxfordjournals.org/content/34/6/ |язык=en |автор издания=The British Occupational Hygiene Society|издание=The Annals of Occupational Hygiene |место=Oxford, UK|издательство=Oxford University Press|год=1990|том=34 |номер=6|страницы=541—552|issn= |doi= 10.1093/annhyg/34.6.547}} ISSN 1475-3162</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] pcx01be07744oxld8gy4x7ixoos63iw Средства индивидуальной защиты (обзорная лекция)/СИЗ органов дыхания 0 35625 270425 269049 2026-10-27T07:08:09Z Jcb 79968 270425 wikitext text/x-wiki [[File:Надевание самоспасателя шахтёром.jpg|thumb|right|300px|СИЗ органов дыхания (самоспасатели) используют '''лишь тогда''', когда применение других средств защиты невозможно]] '''Средства индивидуальной защиты органов дыхания''' - вид [[:w:Средства индивидуальной защиты|средств индивидуальной защиты]], предназначенный для обеспечения работника пригодным для дыхания воздухом в загрязнённой атмосфере и/или при недостатке кислорода. В зависимости от лицевой части (полумаска, маска, шлем или капюшон) могут также использоваться для защиты органов зрения, лица и головы. Обзор научных публикаций на русском языке (наибольший охват по времени с 1936 по 2016 гг.)<ref name="Кириллов-2018" /> показал: * Высококачественные [[:w:автономный дыхательный аппарат| дыхательные аппараты]], нечасто используемые обученными и тренированными специалистами, сильно снижают риск острых отравлений, и могут устранить его полностью. * Повседневно применяемые при сравнительно небольшой загрязнённости воздуха фильтрующие СИЗОД, часто неправильно выбираемые, могут заметно снизить профзаболеваемость <u>исключительно редко</u>. * Редко используемые не всегда хорошо обученными рабочими [[:w:самоспасатель|самоспасатели]], и при высоком качестве могут оказаться бесполезны. Условия труда, и большая масса, могут мешать держать рядом постоянно. При аварии их может быть трудно найти; в условиях стресса люди могут допустить опасные ошибки при их надевании и включении. * При обосновании высокой эффективности и профилактической ценности СИЗОД часть авторов использовала некорректные методы: искажали содержание источников информации, при наличии разной информации выбирали "удобную", игнорируя другую и т.п. В других публикациях эффективность доказывалась ссылками на упомянутые выше работы<ref name="Кириллов-2018" />. В целом, СИЗОД нельзя считать альтернативой [[:w:средства коллективной защиты|средствам коллективной защиты]]<ref name="Конвенция148" />. == Научные исследования == === Значительное отличие защитных свойств в лабораторных и реальных условиях === [[File:Workplace Protection Factors Measurements.jpg||thumb|300px|Замер эффективности респиратора (на рабочем месте). Обозначения: (1) [[:w:Персональный пробоотборник воздуха|Персональный пробоотборный насос]], (2) Кассета и фильтр для определения концентрации (в зоне дыхания), (3) Кассета и фильтр для определения концентрации (под маской), (4) Линия отбора проб (из зоны дыхания), (5) Линия отбора проб (из маски). Одновременное измерение концентрации вредных веществ во вдыхаемом воздухе (под маской) и в зоне дыхания позволяет оценить вклад респиратора в уменьшение воздействия воздушных загрязнений]] Начиная с 1970-х в развитых странах начали [[:w:Производственные испытания респираторов |проводить исследования]] для определения коэффициента защиты СИЗ органов дыхания, не только в лабораторных условиях, но и непосредственно на рабочих местах. Обычно одновременно отбирали две пробы воздуха, из маски и снаружи, определяли отношение концентраций воздушных загрязнений во вдыхаемом воздухе и в окружающем, а отношение второй к первой считали коэффициентом защиты. При проведении исследований именно для определения эффективности СИЗОД все работники были обучены, маски [[:w:Проверка изолирующих свойств респираторов|индивидуально подобраны]], респираторы исправны, при защите от газов [[:w:Способы замены противогазных фильтров респираторов|фильтры меняли вовремя]], во время замера за каждым работников непрерывно наблюдали (если маска снималась или поправлялась - результат измерений не учитывали). Все исследования, проводившиеся компанией 3М, показывали высокий уровень защиты (её продукции). А несколько исследований, проведённых специалистами по профзаболеваниям, выявили настолько плохую защиту рабочих, что [[:w:Ожидаемые коэффициенты защиты респираторов |области допустимого применения]] некоторых СИЗОД уменьшили в десятки раз<ref name="КЗ-2019" />. Такие исследования проводили и в СССР, начав их гораздо раньше, чем на западе. Но их проводили не систематично, а главное - результаты не использовали для установления границ допустимого применения респираторов, так, чтобы рабочим не выдавали заведомо ненадёжные средства защиты. Многие исследования выявляли недостаточную эффективность СИЗОД даже при своевременном применении (что не всегда возможно). Поскольку у самых распространённых СИЗОД (фильтрующих, без принудительной подачи воздуха в маску) защитные свойства сильно зависят от способности маски плотно, без зазоров прилегать к лицу, и не сползать во время работы, были изучены разные способы [[:w:Проверка изолирующих свойств респираторов|обнаружения зазоров между маской и лицом]]<ref name="Crutchfield-2000" />. В США (приложение А<ref name="СИЗОД-США+" />) с 1980-х годов, и в других развитых странах позднее, эти индивидуальные проверки стали обязательными для всех случаев использования СИЗОД работниками в опасной атмосфере. === Замена противогазных фильтров === [[File:Respirator canister with ESLI for asid gases -10.JPG|right|thumb|250px|Фильтр, заранее предупреждающий об окончании срока службы. Внизу: сорбент, меняющий цвет при насыщении; вверху: активированный уголь даёт запас времени при насыщении 1 слоя.]]В начале 20-го века считалось, что работник может обнаружить момент окончания срока службы фильтра по появлению запаха вредного газа в маске, и сможет поменять фильтр вовремя. Кроме того, никаких других способов замены фильтров в то время не было. Затем применение этого способа ограничили защитой от газов, у которых есть "хорошие предупреждающие свойства" (запах, раздражение органов дыхания и/или глаз и т.п.). Однако оказалось, что из-за привыкания, отвлечения внимания на выполнение работы, пониженной индивидуальной чувствительности, хотя бы часть рабочих меняет фильтры запоздало, и портит здоровье. Поэтому с 1990-х [[:w:b:ru:Замена_противогазных_фильтров_СИЗОД_(лекция)#ZAPAH|использование ненадёжной реакции органов чувств запретили полностью]]. В результате длительных исследований, и использования результатов испытаний фильтров их производителями, в [[:w:Лос-Аламосская национальная лаборатория#СИЗОД|научном атомном центре США]] был разработан алгоритм и написана универсальная программа для установки на компьютер, [[:w:b:ru:Замена_противогазных_фильтров_СИЗОД_(лекция)#современные-методы|позволяющие вычислять срок службы фильтра с известными свойствами в известных условиях]]. Алгоритм был использован ведущими производителями СИЗОД для создания собственных программ<ref name="Лекция" />. При расчёте срока службы в условиях высокой относительной влажности воздуха алгоритм может дать ошибочный результат, недооценивая снижение срока службы из-за полного заполнения пор сорбента водой. [[File:Миграция токсичных газов в фильтре респиратора при хранении.jpg|left|thumb|250px|[[:w:Компьютерная томография|Томография]] показывает концентрации газов и их перемещение в сорбенте при хранении фильтра<ref name="Berezovska-2015" /><ref name="Капцов-2022" /><ref>На графиках по горизонтальной оси - расстояние в слое сорбента, по вертикальной оси - относительная концентрация одного или двух газов (суммарно), получившаяся при использовании компьютерной томографии</ref>]] При повторном использовании фильтров работник может отравиться из-за десорбции накопившегося при первом применении токсичного вещества, в развитых странах стараются запретить неоднократное использование (кроме случаев, когда доказано, что это безопасно), см. графики слева<ref name="Капцов-2022" />. Из-за сочетания субъективных, а также объективных причин, выпуск устройств, заблаговременно предупреждающих работника о необходимости заменять фильтр, практически прекращён ([[:w:b:ru:Замена_противогазных_фильтров_СИЗОД_(лекция)#ESLI|End of Service Life Indicator, ESLI]]). Использование современных высококачественных фильтрующих СИЗ органов дыхания, с 2014 года полумасок 3М серии 6000, а с 2018 года СИЗОД с принудительной подачей отфильтрованного воздуха - не позволило устранить или даже сильно, заметно снизить профессиональную заболеваемость органов дыхания при электролизном получении никеля ([[:w:Кольская горно-металлургическая компания|Кольская ГМК]]), за 2004-19 гг. 190 случаев у 130 рабочих<ref name="Сюрин-ГиС-2025" />. === Ограничения применения из-за негативного влияния СИЗОД на работников === Применение [[:w:Средства индивидуальной защиты|СИЗ]] органов дыхания оказывает неблагоприятное воздействие на работника. Нагрузка, создаваемая тяжёлыми [[:w:Автономный дыхательный аппарат|автономными дыхательными аппаратами]], повышенная температура вдыхаемого воздуха (у дыхательных аппаратов с закрытым контуром); сопротивление вдоху и выдоху; высокое содержание углекислого газа и пониженное содержание кислорода в воздухе, вдыхаемом из маски, и другие факторы оказывают негативное влияние на работника. В результате, если при планировании работы не учли влияние СИЗОД, с большой вероятностью может оказаться, что хотя бы часть людей не сможет использовать их непрерывно и своевременно при выполнении работы в загрязнённой атмосфере. Соответственно, защитный эффект может сильно снизиться. В четвёртом издании английского учебника по выбору и использованию СИЗОД рекомендуется организовать работу так, чтобы при использовании (самых распространённых и недорогих) фильтрующих СИЗОД без принудительной подачи воздуха в лицевую часть работники использовали их непрерывно не более 1 часа. При необходимости непрерывно работать в загрязнённой атмосфере больше часа следует использовать СИЗОД с принудительной подачей отфильтрованного воздуха в лицевую часть вентилятором<ref name="Великобритания-2013" />. Это улучшает газовый состав вдыхаемого воздуха ("выдувая" из маски насыщенный углекислым газом выдохнутый воздух), и снижает сопротивление дыханию. В немецкую версию первого издания стандарта Европейского Союза включили выдержку из "Технических правил по опасным веществам, TRgA 415", раздел "Ограничение длительности использования средств защиты органов дыхания и изолирующих защитных костюмов без теплообменника". Для фильтрующих СИЗОД без принудительной подачи воздуха длительность непрерывного применения ограничена двумя часами, затем перерыв для восстановления, до 30 минут<ref name="EN-529-1993">{{Книга |автор=Technisches Komitee (TC) 79 „Atemchutzgerate“. |заглавие=ÖNORM CR 529:1993. Anleitung zur Auswahl und Anwendung von Atemschutzgeräten |ответственный=European Committee for Standardization |год=1993 |часть=Приложение 4. Ограничения по времени применения средств индивидуальной защиты органов дыхания ''(Anhang 4: Tragezeitbegrenzungen von Atemschutzgeräten)'' |язык=de |издание=1 Auflage |место=Brüssel |издательство=Deutsches Institut für Normung |seite=115-116 |alleseiten=120 |серия=Deutsche Fassung}}</ref>, фрагмент ниже. {| class="wikitable collapsible collapsed" style="text-align:center" ! colspan=4 | Таблица 15 |- ! Средство индивидуальной защиты !! Продолжительность использования !! Длительность отдыха (восстановления) !! Задания за 8-часовую смену |- | Костюмы изолирующие без теплообмена, с дыхательным аппаратом со сжатым воздухом, или с фильтрующим СИЗОД || Максимум 30 минут || Не менее 90 минут, включая время на одевание и раздевание. Никакой физической работы. || Если легкая работа, то 2 задания; если каждое задание выполняется менее 15 минут, то 3 задания |- | rowspan=3 | Автономный дыхательный аппарат со сжатым воздухом || Время работы ограничен запасом воздуха и нагрузкой на работника || || |- | Лёгкая работа и работа средней тяжести – более 30 минут || 30 минут || 4 задания |- | Тяжёлая работа – до 30 минут || 60 минут || 4 задания |- | Изолирующий дыхательный аппарат с закрытым контуром и массой '''более''' 5 кг || В зависимости от сложности работы её максимальная длительность должна быть не более 120 минут. || 120 минут || 2 задания |- | Изолирующий дыхательный аппарат с закрытым контуром и массой '''менее''' 5 кг || Время работы ограничивается и запасом кислорода, и нагрузкой на работника. || Время отдыха должно быть не меньше длительности выполнения задания. || 4 задания |- | Шланговые СИЗОД с клапанами вдоха и выдоха (шланговые противогазы, шланговые СИЗОД с подачей сжатого воздуха) || Зависит от сложности работы. Из-за меньшей массы нагрузка на работника меньше, чем у автономных дыхательных аппаратов; до 120 минут || до 30 минут || Нет ограничений |- | Фильтрующие СИЗОД || Зависит от затруднения дыхания и от тяжести выполняемой работы. Написанное ниже не учитывает срок службы противогазного фильтра: не более 120 минут. || до 30 минут || Нет ограничений |} Также указано, что длительность работы зависит и от многих других факторов, например от температуры воздуха. Специалисты НИИ охраны труда провели исследование влияния фильтрующих СИЗОД на молодых людей (возраст 21-23 года). Выполнялась физическая и операторская работа, 15 и 6 минут, затем всё повторялось. Два из шести здоровых участников, с плохой физической подготовкой, оказались не способны длительное время использовать противогаз, и прекратили эксперимент (у одного обнаружилась кровь в моче). Были сделаны выводы: людей с плохой физической подготовки (т.е. без проверки) не следует привлекать к выполнению физической работы, требующей использования СИЗОД, и общая длительность использования СИЗ не должна превышать 3 часа за смену<ref name="Фаустов-2003">{{статья|автор=Фаустов С.А., Андреев К.А|заглавие=Разработка режима труда и отдыха при использовании тяжелых средств индивидуальной защиты органов дыхания|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1762615589&archive=&start_from=&ucat=&|автор издания=ФГБНУ «НИИ медицины труда» и Роспотребнадзор|издание=Медицина труда и промышленная экология|место=Москва|издательство=|год=2003|номер=2|страницы=25-31|issn=}} ISSN 0016-9919</ref>. == Требования к респираторам и сертификация == [[Файл:Fire Test (6648737493).jpg|thumb|right|350px|После воздействия открытого огня]]Для предотвращения продажи некачественных СИЗ разрабатывают требования к их техническим характеристикам, минимальные, которые должны выполнять изготовители и поставщики. Требования могут включать в себя описание способов испытаний, тестирующего оборудования, обработку результатов измерений и указания по маркировке. Строгое выполнение всех этих требований не гарантирует безопасность работника, так как они не могут исключать ошибки при выборе и использовании СИЗ (рассмотрено ниже). Проверка соответствия СИЗ минимальным техническим требованиям может проводиться в одной ответственной и компетентной организации (''например, в Северной Америке СИЗОД испытывает [[:w:Национальный институт охраны труда|Национальный институт охраны труда]] в составе Министерства здравоохранения''), или в аккредитованных лабораториях, в разных странах по-разному. Требования к СИЗ обычно разрабатывают с участием компетентных специалистов по СИЗ. Поскольку многие из них тесно связаны и/или непосредственно работают в компаниях, изготавливающих и торгующих СИЗ, то потенциально возможен [[:w:Конфликт интересов |конфликт интересов]]. * '''<big>Международная организация по стандартизации (ИСО) </big>''' [[:w:Международная организация по стандартизации |ИСО]] разработала более 30 стандартов по СИЗОД. Предполагается, что эти документы станут основой для разработки гармонизированных национальных стандартов в разных странах. Часть стандартов имеет существенные недостатки, и по некоторым положениям не соответствует ни современному уровню науки, ни современным требованиям к СИЗОД в ведущих развитых странах<ref name="БТП-2021" />. В отношении противогазных фильтров, ни в одной из стран нет требований к устройствам, которые заранее предупреждают рабочих о необходимости их заменять. [[:w:Способы замены противогазных фильтров респираторов#ESLI|''End of Service Life Indicators, ESLI'']] должны срабатывать до того, как будет использовано 90 % срока службы — чтобы рабочий успел уйти из загрязнённой атмосферы<ref name="NIOSH-ESLI-1" />. У пассивных индикаторов чувствительный элемент должен располагаться так, чтобы рабочий видел его при одетом респираторе<ref name="NIOSH-ESLI-2" />. Все индикаторы должны сохранять работоспособность при падении на твёрдый пол с высоты 1,8 м<ref name="NIOSH-ESLI-3" />. * '''<big> США </big>''' [[File:Сертификация СИЗОД для ЧС.jpg|thumb|right|350px|Замер защитных свойств при сертификации ([[:w:Национальный институт охраны труда#Институт и респираторная защита |''NIOSH'']])]]Сертификация [[:w:СИЗОД|СИЗ органов дыхания]] проводится с 1920 г. После создания [[:w:Национальный институт охраны труда |Национального института охраны труда]] ''(NIOSH)'' в 1970-х разработку требований и сертификационные испытания выполняет лаборатория СИЗ Института. Требования к всем типам СИЗОД установлены в одном документе<ref name="СИЗОД-СШАc" /> (в разных разделах требования к разным типам). Для испытаний заявитель обязан представить план контроля качества при производстве СИЗОД, Институт может проверить выполнение плана в любой момент, и при нарушении - аннулировать уже выданный сертификат. Сертификация [[:w:Самоспасатель#Самоспасатели_для_шахтёров |шахтёрских изолирующих самоспасателей]] предусматривает [[:w:s:ru:Требования к респираторам при их сертификации (США)#84.310|послесертификационные проверки качества]]: часть купленных потребителями изделий забирается у них (взамен им дают новые, те же модели), и испытывается. Разработаны требования и проводится сертификация противогазных фильтров с устройствами, заранее предупреждающими работников о необходимости менять фильтр, т.к. далеко [[:w:b:ru:Замена_противогазных_фильтров_СИЗОД_(лекция)#ZAPAH|не всегда можно вовремя обнаружить окончание срока службы по появлению запаха в маске]] и т.п. Ни в одной из других стран нет требований к устройствам, предупреждающих рабочих о необходимости заменять фильтры. [[:w:Способы замены противогазных фильтров респираторов#ESLI|''End of Service Life Indicators, ESLI'']] должны срабатывать до того, как будет использовано 90 % срока службы — чтобы рабочий успел уйти из загрязнённой атмосферы<ref name="NIOSH-ESLI-1" />. У пассивных индикаторов чувствительный элемент, меняющий цвет, должен располагаться так, чтобы рабочий видел его при одетом респираторе<ref name="NIOSH-ESLI-2" />. Все индикаторы должны сохранять работоспособность при падении на твёрдый пол с высоты 1,8 м<ref name="NIOSH-ESLI-3" />. Сертификация фильтрующих самоспасателей (для защиты при пожарах) не предусмотрена. * '''<big> Канада </big>''' В соответствии с<ref name="CSA-2018" /> работодатели обязаны использовать только сертифицированные СИЗОД. Учтя наличие рядом квалифицированных специалистов и мощную испытательную лабораторию, стандарт Канады требует от работодателей, чтобы СИЗ испытывались в [[:w:Национальный институт охраны труда |Институте охраны труда]] (''NIOSH'', США), а в Канаде испытания СИЗОД не проводят. Поэтому канадские требования совпадают с американскими<ref name="СИЗОД-СШАc" />. Из-за перегрузки NIOSH во время "пандемии" в Канаде начали сертифицировать фильтрующие противоаэрозольные СИЗОД самостоятельно, разработав свой стандарт<ref name="CSA-2021" /> с требованиями к ним. * '''<big> Европейский Союз '''</big> Требования к СИЗ, разных конструкций, установлены в множестве отдельных стандартов, которые часто пересматриваются, постепенно увеличиваясь и усложняясь. У самых распространённых СИЗОД, без принудительной подачи воздуха, при выдохе маска заполняется вредным веществом, [[:w:Диоксид_углерода#Физиологическое_действие|углекислым газом]], при концентрации на порядок превышающей предельно допустимую среднесменную. Затем СО<sub>2</sub> вдыхается снова. В требованиях к свойствам респираторов установлен критерий: средняя концентрация этого газа при вдохе не должна превышать 1% по объёму, что вдвое выше предельно допустимой. А в методе измерений требуется отрегулировать объём вдоха имитатора дыхания 2 литра, что соответствует очень тяжёлой физической работе, выполнение которой длительное время сейчас нетипично для большинства работ. При аномально большом объёме вдоха СО<sub>2</sub> из маски сильно разбавляется, и его концентрация обычно соответствует критерию<ref name="Капцов-2021" />. Результат: СИЗ успешно сертифицируют, о возможной опасности потребителей не предупреждают, и при длительном применении часть рабочих не выдерживает, и снимает маски - или страдает от головных болей<ref name="AN-2006" /> и др. последствий [[:w:Диоксид_углерода#Физиологическое_действие|отравления углекислым газом]]. По сути, недостаток, способный помешать работникам своевременно использовать СИЗОД - замалчивается. В РФ приняты такие же гармонизированные стандарты. * '''<big> Австралия и Новая Зеландия </big>''' Для сертификационных испытаний используют один стандарт, где в разных разделах есть требования к СИЗОД разных типов<ref name="ANZ-СИЗОД-тест" />. Так как было установлено, что СИЗОД с полнолицевой маской с панорамным стеклом, у которых во время вдоха нет избыточного давления в маске, плохо защищают [[:w:Горноспасательное дело|работающих при опасной для жизни загрязнённости воздуха]], сертификация таких [[:w:автономный дыхательный аппарат |автономных дыхательных аппаратов]] прекращена. Для сравнения, в РФ даже нет требований к дыхательным аппаратам с химически связанным кислородом, поддерживающим избыточное давление в маске во время вдоха, и их могут использовать [[:w:горноспасатель |горноспасатели]] в особо опасной атмосфере. Стандарт допускает сертификацию противогазных фильтров с очень маленьким количеством [[:w:сорбенты|сорбента]]. Они могут защищать от некоторых вредных веществ при их низкой концентрации, при этом совершенно не соответствуя европейским требованиям к противогазным фильтрам: проскок токсичных веществ может происходить почти сразу<ref name="Haupt-2006" />. * '''<big> Япония </big>''' Разработаны стандарты с минимальными требованиями к СИЗОД разных типов (например к фильтрующим: противогазным<ref name="Japan-gas" /> и противоаэрозольным<ref name="Japan-dust" />). * '''<big> Индия </big>''' Есть стандарты с требованиями к техническим характеристикам и с методами испытаний СИЗОД и комплектующих (примеры: маски<ref name="Индия-полумаска" />, фильтры<ref name="Индия-фильтр" />). В целом, стандарты разрабатываются на основе иностранных, преимущественно европейских, но не являются точной копией. * '''<big> Китай </big>''' Требования к СИЗОД разных типов, их испытаниям и др. сформулированы в разных стандартах (пример: фильтрующие полумаски промышленные<ref name="КНР-СИЗОД-ФПМ" />, автономные дыхательные аппараты<ref name="КНР-SCBA" />), как в Европейском Союзе. При разработке стандартов широко используются стандарты ЕС и подходы, принятые в США. * '''<big> РФ </big>''' [[Средства индивидуальной защиты (обзорная лекция)/Общая информация#СССР и РФ|Разрабатываются государственные стандарты]], гармонизированные со стандартами ЕС. Их добровольное выполнение необходимо для соответствия требованиям [https://miningwiki.ru/wiki/%D0%A2%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D1%80%D0%B5%D0%B3%D0%BB%D0%B0%D0%BC%D0%B5%D0%BD%D1%82_%22%D0%9E_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D0%A1%D0%98%D0%97%22 Технического Регламента]<ref name="ТР-2009" />. [[File:Сертификат на респиратор Лепесток.JPG|thumb|right|300px|Сертификат абсурдного содержания]]Для проверки соответствия изделия испытываются в [[:w:Аккредитация|аккредитованных]] лабораториях, и затем орган по сертификации выдаёт сертификат. На практике, эта система работает так, что даже содержание сертификатов может быть абсурдным<ref name="Кириллов-2013" />).. Например, при испытании фильтрующей полумаски "Лепесток" был выдан сертификат, в котором указали, что изделие одновременно соответствует требованиям к: фильтрующим полумаскам, полнолицевым маскам с панорамным стеклом, эластомерным полумаскам, и полумаскам с несъёмными противогазными фильтрами (показан на иллюстрации справа). Наличие разных органов, проводящих сертификацию, позволяет, в случае неудачи, обратиться в другой орган - не улучшая изделие. Возможно изготовление небольшой партии повышенного качества для обеспечения успешной сертификации<ref name="Сорокин-2011" />. == Выбор и использование == Индивидуальная защита органов дыхания в разных странах, включая требования к их выбору, рассмотрена в обзоре<ref name="Капцов-2020" />. Во многих странах нет достаточно полноценного учёта значительных [[:w:Производственные испытания респираторов|отличий защитных свойств в лабораторных и реальных условиях]], и эффективных требований к [[:w:Проверка изолирующих свойств респираторов|проверке соответствия маски лицу и умения работников правильно её надевать]]. Но и при наличии адекватных представлений об [[:w:Ожидаемые коэффициенты защиты респираторов|фактической степени защиты СИЗОД разных типов в производственных условиях]], необходима точная информация о загрязнённости воздуха, о степени превышения концентрации загрязнений по отношению к предельно допустимой. Из-за того, что концентрация загрязнений редко бывает постоянной во времени и в пространстве, уже в 1970-х годах было показано, что замеры около головы работника в течение всей смены дадут самый точный результат<ref name="Руководство 1976г" />. Это соответствует результатам проведённых в РФ исследований: по данным<ref name="Федорук-2025" />, сравнение результатов измерений персональными пробоотборниками с результатами измерений, выполненными при проведении специальной оценке условий труда, обнаружило занижение воздействия на работников вредных веществ, свинца до 143 раз, и мышьяка до 60 раз. Недостаточно качественная оценка риска в РФ<ref name="Кириллов-2016в" />, измерение загрязнённости воздуха стационарными приборами, и/или отбор проб не около лица рабочего, также может привести к не выдаче рабочим СИЗОД когда они необходимы, и к неправильному выбору типа СИЗОД по защитным свойствам. [[File:Испытания СИЗОД для ЧС сертификационные.jpg|thumb|right|310px|Даже высококачественные сертификационные испытания (в лаборатории) - не гарантируют надёжную защиту людей (на рабочих местах)]] * '''<big> США </big>''' [[:w:Управление по охране труда (OSHA)|Департамент условий и охраны труда]] разработал требования к выбору и использованию СИЗ органов дыхания. [[:w:OSHA|Государственная инспекция]] проверяет их выполнение, используя инструкцию<ref name="CPL-СИЗОД" />. Требования к выбору и использованию респираторов<ref name="СИЗОД-США+" /> обязывают работодателей: # Выбирать тип СИЗОД так, чтобы учесть [[:w:Ожидаемые коэффициенты защиты респираторов|научно обоснованные ограничения]], разработанные при проведении [[:w:Производственные испытания респираторов|десятков исследований фактической защиты рабочих на заводах]]. # Давать каждому рабочему возможность выбрать подходящую и удобную маску из нескольких, и затем обязательно [[:w:Проверка изолирующих свойств респираторов|проверять, насколько плотно, без зазоров она прилегает к лицу]], отделяя органы дыхания от окружающей атмосферы. # Не допускать [[:w:b:ru:Замена противогазных фильтров СИЗОД (лекция)|замены противогазных фильтров]] на основе субъективной и ненадёжной реакции органов чувств на появление запаха в маске, раздражения и т.п. * '''<big> Канада </big>''' Стандарт<ref name="CSA-2018" /> содержит требования к выбору и организации использования СИЗОД всех типов. Области применения установлены такие же, как и в США, т.е. с учётом отличий защитных свойств в лабораторных условиях и на практике. Этот стандарт - единственный, где есть конкретные указания по выбору типа СИЗОД для защиты от биологических аэрозолей с учётом их опасности. Замена противогазных фильтров по появлению запаха в маске - запрещена, их меняют по расписанию, или по показаниям [[:w:Способы_замены_противогазных_фильтров_респираторов# Замена_по_показаниям_Индикаторов_Окончания_Срока_Службы_(End_of_Service_Life_Indicators,_ESLI)| индикатора окончания срока службы (''ESLI'')]]. * '''<big> Европейский Союз </big>''' Разработан стандарт с требованиями к выбору и организации применения СИЗОД. Особенности документа<ref name="EN-529" /> по сравнению с требованиями в США и Канаде: - Области допустимого применения ([[:w:ожидаемые коэффициенты защиты респираторов|ожидаемые коэффициенты защиты]]) для разных стран указаны разные. Отличие настолько велико, и во многих случаях так сильно превышает научно обоснованные американские ограничения, что видно, что во многих странах, где не измеряли защитные свойства респираторов у работников на заводах, не учли отличие лабораторной и реальной эффективности (или учли частично). В результате новые члены ЕС, и страны, использующие стандарты ЕС как образец, принимая свои национальные стандарты, и не ознакомившись с современным уровнем науки в этой области, просто скопировали соответствующие места текста. В результате стандарты Болгарии БДС EN 529 и Украины ДСТУ EN 529 не дают никакой информации читателям - в каких случаях какие типы СИЗОД следует использовать. - Замена противогазных фильтров по запаху запрещена как "ненадёжная". Должны использоваться или индикаторы срока службы, или замена по расписанию. При этом требований к индикаторам (''ESLI'') в ЕС (в отличие от США) нет вообще, т.е. потребителям предлагается использовать не сертифицированные изделия. У фильтра 3М для защиты от органических соединений есть индикатор, который предупреждает работников, но для разных токсичных газов - при разной концентрации. При оценке его работы и российских предельно допустимых концентрациях получилось, что при защите от уайт-спирита он сработает при концентрации 1/60 от среднесменной ПДК, а при защите от изопропилового спирта – при превышении максимально разовой ПДК в 32 раза<ref name="НН-2023" />. * '''<big> Япония </big>''' Разработан и регулярно пересматривается национальный стандарт, устанавливающий требования к работодателю, регулирующие выбор и организацию использования СИЗ органов дыхания всех типов. Области допустимого применения (2006 г.) очень схожи с научно обоснованными ограничениями в США. Последнее издание<ref name="Japan-СИЗОД" /> разработано с учётом стандартов ISO/TS 16975-1 и -3. Для замены противогазных фильтров работодатель обязан определить срок службы, обратившись к изготовителю. Также для выбора противопылевых респираторов выпущено предписание<ref name="Japan-dust-" />. * '''<big> Индия </big>''' Для правильного выбора и применения СИЗОД в Индии разработан стандарт<ref name="Индия-СИЗОД" />. При разработке за основу взяли стандарты США, Великобритании и Австралии (ANSI Z 88-2-1969, BS 4275:1968, AS CZ 11-1968). Авторы указали, что для оценки защитных свойств СИЗОД разных типов следует использовать результаты [[:w:Производственные испытания респираторов|измерений на рабочих местах]], у работников. Но в Индии такие дорогостоящие и трудоёмкие замеры не проводились, а результаты западных исследований не были полноценно использованы разработчиками стандарта - они ориентировались, в первую очередь, на западные стандарты 1960-х годов. А замеры коэффициентов защиты СИЗОД разных типов начались в 1970-х, и не учитывались в документах, взятых за основу при разработке стандарта Индии. В результате стандарт, фактически, не различает значительное (на порядки) отличие защитных свойств СИЗОД в лабораториях при сертификации и на предприятиях<ref name="Обзор-2014" /><ref name="Обзор-2019" />, и допускает применение разных видов СИЗОД при слишком большой загрязнённости воздуха, когда они не могут надёжно защищать работников. * '''<big> Китай </big>''' Для выбора и правильного использования СИЗ органов дыхания разработан национальный стандарт. При разработке использованы результаты научных исследований и аналогичные требования в США, Великобритании и Австралии, в результате получились схожие ограничения областей допустимого применения СИЗОД разных типов<ref name="КНР-СИЗОД+" />. Но требования не являются юридически обязательными, а могут выполняться работодателями на добровольной основе. При защите от токсичных газов рекомендуется использовать фильтры с индикаторами окончания срока службы, или изолирующие СИЗОД - если у газов "плохие предупреждающие свойства" (запах, раздражение и т.п.). В разработке проекта документа участвовала компания 3М. * '''<big> РФ </big>''' Конкретные требования к выбору и организации использования СИЗ органов дыхания, юридически обязательные для выполнения работодателем - отсутствуют. Для выбора СИЗОД работодатель должен использовать результаты специальной оценки условий труда, и данные о защитных свойствах СИЗОД - предоставляемые изготовителем. Поскольку те стабильно завышают эффективность, порой на порядки, часть работников получает средства защиты, совершенно не соответствующие условиям труда<ref name="КЗ-2019" />. == Обучение == Опубликовано много учебных пособий на разных языках, список и ссылки на них даны [[:w:Респиратор#Обучение|в свёрнутой таблице]]. Учебные пособия [[:w:Национальный институт охраны труда#Институт и респираторная защита|Национального института охраны труда]] (''NIOSH'') доступны в переводе на русский язык<ref name="Учебник 2004" /><ref name="Учебник 1987" /><ref name="Учебник 1999" />. В них области допустимого применения СИЗОД разных типов ограничена с учётом современного уровня науки, т.е. учтено значительное отличие<ref name="Обзор-2014" /><ref name="Обзор-2019" /> [[:w:Производственные испытания респираторов|защитных свойств на предприятиях]] и в лабораториях при сертификации<ref name="Кириллов-2013" />. Также есть перевод учебника по замене противогазных фильтров [[:w:Управление по охране труда (OSHA)|Департамента условий и охраны труда]]<ref name="eTool" />. Для защиты органов дыхания чаще всего используют простые и дешёвые фильтрующие СИЗОД без принудительной подачи воздуха в лицевую часть. В английском учебнике, в отличие от многих других, на основании большого накопленного опыта, работодателям и специалистам по охране труда рекомендуется организовать использование этих средств защиты так, чтобы работник не применял их без перерыва более 1 часа<ref name="Учебник-2013" />. Это связано с тем, что если требовать от обычных работников регулярно использовать такие СИЗОД более часа, то "это будет трудно добиться на практике". Точная причина не указана, при необходимости длительной носки СИЗОД советуют применять модели с принудительной подачей воздуха в лицевую часть. Возможно, отчасти это объясняется тем, что без подачи воздуха в лицевую часть она заполняется углекислым газом при выдохе, при концентрации, на порядок больше чем среднесменная предельно допустимая - и затем непригодный для дыхания воздух вдыхается повторно<ref name="Капцов-2021" />. По крайней мере часть работников не сможет переносить вдыхание вредного вещества (углекислого газа<ref name="Лазарев-3" /><ref name="NIOSH-CO2" />) долго, и добиться своевременного использования СИЗОД всеми работниками не удастся. При принудительной подаче воздуха углекислый газ удаляется из лицевой части, и вдыхаемый воздух пригоден для дыхания. [[Файл:Рисунок к учебнику по применению респираторов.jpg|thumb|left|350px|Максимальная загрязнённость воздуха, при которой можно использовать полумаски (OY). Маркеры - рекомендации советских и российских авторов разных лет<ref name="Кириллов-2013" />.]]В СССР и РФ опубликовано много книг по СИЗОД. К сожалению, во многих значительно завышается способность полумасок и полнолицевых масок, лицевых частей самых распространённых СИЗОД, отделять органы дыхания от окружающей загрязнённой атмосферы. Соответственно, выполнение рекомендаций авторов (например - использовать респираторы-полумаски при большом превышении предельно допустимой концентрации) приведёт к тому, что хотя бы часть рабочих получит заведомо недостаточно эффективные СИЗ, и не будет защищена при своевременном и правильном их использовании. На диаграмме показано как соотносятся эти рекомендации по полумаскам с научно обоснованными ограничениями, действующими и в США, и в большинстве развитых стран. Участие [https://miningwiki.ru/wiki/Ассоциация_СИЗ Ассоциации СИЗ] в разработке документов, влияющих на выбор, применение (и закупку) СИЗ, выразилось (в том числе) подписанием соглашения с Всероссийским НИИ сертификации в 2015 г.<ref name="ВНИИС" /> Документ предусматривает совместное участие в работе Технического комитета ТК-320, которые разрабатывает ГОСТы РФ по СИЗ. Позднее корпорация АО «Корпорация Росхимзащита» разработала ГОСТ, который (должен был) регулировать выбор и применение СИЗОД в РФ<ref name="ГОСТ-РХЗ" />. Как декларировалось, документ разрабатывался на основе стандарта ЕС того же назначения. Через год был принят идентичный стандарт<ref name="ГОСТ-РХЗ-2" />. Но по [[:w:Законодательное регулирование выбора и организации применения респираторов#таблица|'''всем''' ключевым моментам]], определяющим эффективность защиты работников, этот документ не соответствовал стандарту ЕС<ref name="EN-529" />, а в некоторых случаях имел [[:w:Законодательное регулирование выбора и организации применения респираторов#таблица|прямо противоположное содержание]]. В то же время обе версии ГОСТа «Росхимзащиты» - при их добровольном выполнении работодателем - нисколько не нарушали уже сложившуюся в РФ (к моменту разработки) практику выбора и применения СИЗОД. По мнению компетентного специалиста с большим опытом работы<ref name="Кириллов" />, из-за значительного числа недостатков и отличий от оригинала<ref name="Кириллов-2016" />, можно сказать, что : <blockquote>... гармонизация рассмотренного документа по отношению к стандарту ЕС (и аналогичного [8] в США) - не состоялась. </blockquote>. [https://miningwiki.ru/wiki/Ассоциация_СИЗ Ассоциация СИЗ] опубликовала рекомендации по выбору и применению СИЗОД. В документе предлагается заменять противогазные фильтры по появлению запаха в маске<ref name="Сорокин-2006" />, завышается эффективность полумасок. [[File:КОНТРАФАКТ+.jpg|thumb|400px|right|Способ борьбы с контрафактом, неиспользуемый поставщиками СИЗ в РФ]] В целом, использование российских рекомендаций и даже ГОСТов может создать повышенную опасность отравлений и развития хронических профессиональных заболеваний и при своевременном использовании высококачественных, исправных и сертифицированных СИЗОД. Значительное отличие рекомендаций, публикующихся на русском языке не первое десятилетие, от современного уровня науки, не позволяет объяснять негативные последствия применения СИЗОД в загрязнённой атмосфере исключительно "контрафактом" и недисциплинированностью самих работников. Для снижения риска покупки ответственными потребителями контрафакта есть много средств, но при упаковке СИЗОД и противогазных фильтров российскими производителями они не используются. Плохо обученные специалисты по охране труда не информируются поставщиками о том, что во многих случаях использования самых распространённых СИЗОД (фильтрующих, без принудительной подачи воздуха) концентрация углекислого газа во вдыхаемом воздухе обычно превышает среднесменную предельно допустимую, и может иногда превышать максимально разовую (среднюю за полчаса). Соответственно, работа сотрудников организуется так, что часть из них не выдерживает дыхания непригодным для этого воздухом. За десятилетия, выдача работникам средств защиты заведомо недостаточной эффективности стала, по сути, традицией. Часть работников, экспериментально убедившаяся в недостаточной степени защиты, перестаёт её использовать своевременно. Особо следует отметить книгу<ref name="Кошелев-Тарасов" />, более трети которой посвящено тому, как определить срок службы противогазных фильтров без использования субъективной реакции органов чувств. Несмотря на ряд недостатков, именно в части замены фильтров подход к проблеме уникален, и разительно отличается от подавляющего большинства публикаций на русском языке. Описанные выше недостатки показывают, что в настоящее время в РФ имеется пока не используемая возможность значительного улучшения защиты работающих в загрязнённой атмосфере. == Эффективность == В США провели широкомасштабный опрос (более 30,2 тыс. компаний) о использовании респираторов. Результаты показали, что во многих компаниях нарушают [[:w:Законодательное регулирование выбора и организации применения респираторов|требования к выбору и организации использования СИЗОД]], так, что это создаёт опасность для работников. Чаще всего нарушения допускались в маленьких компаниях, из-за отсутствия компетентных специалистов и недостатка ресурсов<ref name="Обзор-2001" />. Английские специалисты проверили то, как выбирают и используют СИЗОД на разных предприятиях<ref name="UK-2011" /><ref name="UK-2012" />. Суммарно, два исследования охватили результаты проверок на 51 предприятии. На многих выявлены недостаточная компетентность и ошибки, плохое обучение работников и т.п. Но из-за небольшого числа предприятий сложно сказать, насколько эти результаты типичны. Условия выбор и использования СИЗОД в РФ отличаются от западных: нет конкретных и подробных требований законодательства, и контроля за их выполнением, специалистов по охране труда не обучают - как организовать индивидуальную защиту, и потому работников учить просто некому. Для оценки влияния выдачи СИЗ органов дыхания на сбережение здоровья работников был проведён поиск информации в научных публикациях. Но найти работы, где бы сравнивалась заболеваемость в одинаковых условиях, до и после начала использования СИЗОД не удалось. Обзор сотен статей из более 30 журналов и более 360 сборников научных работ (максимальный охват по времени с 1936 по 2016 гг.) показал, что предотвратить профзаболевания с помощью СИЗОД удавалось исключительно редко. Также выяснилось, что для обоснования высокой профилактической ценности СИЗОД в ряде публикаций использовались некорректные способы (искажение первоисточников информации при цитировании и т.п.); или ссылались на эти публикации<ref name="Кириллов-2018" />. Материалы, собранные при подготовке обзора, и позднее позволяют сделать выводы: * Высококачественные, исправные [[:w:автономный дыхательный аппарат| дыхательные аппараты]], с избыточным давлением в маске при вдохе (исключающем попадание загрязнений через зазоры в месте касания маски и лица), используемые, обученными, тренированными специалистами, и применяемые не повседневно - сильно снижают риск острых отравлений, а порой и полностью устраняют его. * Фильтрующие СИЗОД, часто неправильно выбираемые, и повседневно применяемые, при сравнительно небольшой загрязнённости воздуха, могут заметно снизить профзаболеваемость <u>исключительно редко</u>. В части публикаций, декларировавших обратное, использовали некорректные методы: искажали содержание источников информации, при наличии разной информации выбирали "удобную", игнорируя другую и т.п.<ref name="Кириллов-2018" />. * Редко используемые не всегда хорошо обученными рабочими [[:w:самоспасатель|самоспасатели]], и при высоком качестве могут оказаться бесполезны. Условия труда, и большая масса, могут мешать держать рядом постоянно. При аварии их может быть трудно найти; в условиях стресса люди могут допустить опасные ошибки при их надевании и включении. СИЗОД нельзя считать альтернативой [[:w:средства коллективной защиты|средствам коллективной защиты]]. == Примечания == {{примечания|refs= <ref name="Конвенция148">Конвенция [[:w:Международная организация труда |Международной организации труда]] № 148 {{Cite web |url=http://www.ilo.org/wcmsp5/groups/public/---ed_norm/---normes/documents/normativeinstrument/wcms_c148_ru.htm |title= «О защите трудящихся от профессионального риска, вызываемого загрязнением воздуха, шумом и вибрацией на рабочих местах» (1977) }} (16 октября 2024). [https://docs.cntd.ru/document/1900829 Официальный перевод]</ref> <ref name="КЗ-2019">{{Статья|ссылка=https://www.rjhas.ru/jour/article/view/383/362?locale=ru_RU|автор=Капцов В.А., Чиркин А.В.|заглавие=Выбор работодателем средств индивидуальной защиты органов дыхания в зависимости от результатов их испытаний на рабочих местах (обзор)|год=2019|ответственный=ФБУН "Федеральный научный центр гигиены им. Ф.Ф. Эрисмана" Роспотребнадзора|место=Москва|издание=Гигиена и санитария|издательство=ГЭОТАР-Медиа|месяц=9|том=98|номер=8|страницы=845-850|doi=10.18821/0016-9900-2019-98-8-845-850}} ISSN 0016-9900.</ref> <ref name="Капцов-2022">{{Статья|ссылка=https://www.rjhas.ru/jour/article/view/2011/1419|автор=Капцов В.А., Панкова В.Б., Чиркин А.В.|заглавие=Риск многократного применения противогазных фильтров респираторов (обзор литературы)|год=2022|автор издания=Роспотребнадзор|издание=Гигиена и санитария|том=101 |номер=2|страницы=174-179 |doi=10.47470/0016-9900-2022-101-2-174-179|archivedate=2023-05-19 |archiveurl= https://web.archive.org/web/20230519150148/https://www.rjhas.ru/jour/article/view/2011/1419}} ISSN 0016-9900. [https://www.researchgate.net/publication/359302765_The_risk_of_multiple_uses_of_respirator_gas_filters_literature_review копия]</ref> <ref name="Crutchfield-2000">{{Статья|ссылка= https://www.researchgate.net/publication/12680414_Effect_of_Test_Exercises_and_Mask_Donning_on_Measured_Respirator_Fit|автор= C.D. Crutchfield, E.O. Fairbank, S.L. Greenstein|заглавие= Effect of Test Exercises and Mask Donning on Measured Respirator Fit |год=2000|язык=en|автор издания=AIHA & ACGIH |издание=Applied Occupational and Environmental Hygiene|издательство=Taylor & Francis|год=1999|volume=14|выпуск=12|pages=827-837|issn=|doi=10.1080/104732299302062}} ISSN 1521-0898</ref> <ref name="СИЗОД-СШАc">[https://www.ecfr.gov/current/title-42/chapter-I/subchapter-G/part-84 42 Code of Federal Register Part 84 "Approval of Respiratory Protective Devices"] [https://www.law.cornell.edu/cfr/text/42/part-84 копия]. Есть перевод [http://commons.wikimedia.org/wiki/File:42_CFR_84_28.pdf PDF] [[:w:s:Требования к респираторам при их сертификации (США)|Wiki]]</ref> <ref name="CSA-2018">{{Книга|заглавие=CSA Standard Z94.4-18 (R2023) Selection, Use and Care of Respirators|год=2018|язык=en|издание=5th ed|место=Toronto, Ontario, Canada|издательство=Canadian Standards Association|allpages=112|isbn=978-1-4883-1583-1}}</ref> <ref name="CSA-2021">{{Книга |автор=CSA |заглавие=CSA Z94.4.1:21 Performance of filtering respirators |год=2021 |язык=en |место=Toronto, Ontario, Canada |издательство=Canadian Standards Association |allpages=83 |серия=ICS 13.340.30 |isbn=978-1-4883-3813-7}}</ref> <ref name="БТП-2021">{{Статья|автор=В.А. Капцов, В.Б. Панкова, А.В. Чиркин|заглавие=Международные стандарты по индивидуальной защите органов дыхания (обзор)|ссылка=https://elibrary.ru/item.asp?id=49432018 |год=2021|издание=Безопасность труда в промышленности|месяц=3|номер=3|страницы=70-75|автор издания=Федеральная служба по экологическому, технологическому и атомному надзору (РОСТЕХНАДЗОР); Закрытое акционерное общество «Научно-технический центр исследований проблем промышленной безопасности» (ЗАО НТЦ ПБ)|место=Москва|издательство=ЗАО "Алмаз-Пресс"}} ISSN 0409-2961.</ref> <ref name="Лекция">''Капцов В.А. и др.'' [https://ru.wikibooks.org/wiki/Замена_противогазных_фильтров_СИЗОД_(лекция) Замена противогазных фильтров СИЗОД (лекция)] [https://web.archive.org/web/20210415085113/https://ru.wikibooks.org/wiki/Замена_противогазных_фильтров_СИЗОД_(лекция) Архивировано] 15 апреля 2021 года.</ref> <ref name="Berezovska-2015">{{Статья |автор=Berezovska I., Fettaka H., Salmon T., Toye D., Lodewyck P. |заглавие=Redistribution of a mixture of organic vapours inside an activated carbon filter |год=2015 |язык=en |издание=Chemical Engineering Journal |издательство=Elsevier B.V. |месяц=11 |число=15 |pages=677–681 |volume=280 |doi=10.1016/j.cej.2015.05.129}} ISSN 1385-8947.</ref> <ref name="Капцов-2021">{{Статья|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1641162202&archive=&start_from=&ucat=&|автор=[[:w:Капцов, Валерий Александрович|Капцов В.А.]], Чиркин А.В.|заглавие=Воздействие углекислого газа на работников, использующих респираторы (обзор|год=2021|место=Владивосток|издание=Доклад на 16 Российском национальном конгрессе с международным участием "Профессия и здоровье"|месяц=сентября|число=23|archivedate=2022-01-03 |archiveurl= https://web.archive.org/web/20220103221803/https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1641162202&archive=&start_from=&ucat=&}}</ref> <ref name="NIOSH-ESLI-1">{{Книга|ссылка=https://www.cdc.gov/niosh/npptl/stps/pdfs/RCT-APR-0066-508.pdf|автор=National Personal Protective Technology Laboratory (NPPTL) in NIOSH|заглавие=Determination of end of service life indicator (ESLI) test. <small>Procedure No. RCT-APR-0066</small>|год=2005|язык=en|место=Pittsburgh, Pennsylvania|издательство=National Institute for Occupational Safety and Health (NIOSN)|серия=[https://www.cdc.gov/niosh/npptl/stps/respirator_testing.html Standard testing procedure, STP]. Air-purifying respirators|access-date=2024-02-01|archive-date=2023-05-21|archive-url=https://web.archive.org/web/20230521165006/https://www.cdc.gov/niosh/npptl/stps/pdfs/RCT-APR-0066-508.pdf|url-status=live}} [[:w:s:ru:Сертификация СИЗОД (NIOSH) - Индикаторы срока службы противогазных фильтров. Проверка момента срабатывания.|'''перевод''']]</ref> <ref name="NIOSH-ESLI-2">{{Книга|ссылка=https://www.cdc.gov/niosh/npptl/stps/pdfs/RCT-APR-0061-508.pdf|автор=National Personal Protective Technology Laboratory (NPPTL) in NIOSH|заглавие=Determination of End-of-Service-Life Indicator Visibility. <small>Procedure No. RCT-APR-0061</small>|год=2005|язык=en|место=Pittsburgh, Pennsylvania|издательство=National Institute for Occupational Safety and Health (NIOSN)|серия=[https://www.cdc.gov/niosh/npptl/stps/respirator_testing.html Standard testing procedure, STP]. Air-purifying respirators|access-date=2024-02-01|archive-date=2023-05-21|archive-url=https://web.archive.org/web/20230521165006/https://www.cdc.gov/niosh/npptl/stps/pdfs/RCT-APR-0061-508.pdf|url-status=live}} [[:w:s:ru:Сертификация СИЗОД (NIOSH) - Индикаторы срока службы противогазных фильтров. Проверка визуальной заметности |'''перевод''']]</ref> <ref name="NIOSH-ESLI-3">{{Книга|ссылка=https://www.cdc.gov/niosh/npptl/stps/pdfs/RCT-APR-0060-508.pdf|автор=National Personal Protective Technology Laboratory (NPPTL) in NIOSH|заглавие=Determination of end of service life indicator (ESLI) drop test. <small>Procedure No. RCT-APR-0060</small>|год=2005|язык=en|место=Pittsburgh, Pennsylvania|издательство=National Institute for Occupational Safety and Health (NIOSN)|серия=[https://www.cdc.gov/niosh/npptl/stps/respirator_testing.html Standard testing procedure, STP]. Air-purifying respirators|access-date=2024-02-01|archive-date=2023-05-21|archive-url=https://web.archive.org/web/20230521165006/https://www.cdc.gov/niosh/npptl/stps/pdfs/RCT-APR-0060-508.pdf|url-status=live}} [[:w:s:ru:Сертификация СИЗОД (NIOSH) - Индикаторы срока службы противогазных фильтров. Проверка при падении |'''перевод''']]</ref> <ref name="Сюрин-ГиС-2025">{{Статья|ссылка= https://www.rjhas.ru/jour/article/view/5099?locale=ru_RU |автор= Сергей Алексеевич Сюрин, Александр Александрович Ковшов, Марина Николаевна Кирьянова, Алена Владимировна Шильниковская|заглавие= Профессиональные болезни органов дыхания работников, занятых в производстве никеля|год=2022|автор издания=ФБУН «Федеральный научный центр гигиены им. Ф.Ф. Эрисмана» Роспотребнадзора|издание=Гигиена и санитария|том=104 |номер=8|страницы= 1035-1042 |doi= 10.47470/0016-9900-2025-104-8-1035-1042 }} ISSN 0016-9900.</ref> <ref name="EN-529">{{Книга|автор=Technical Committee CEN/TC 79 "Respiratory protective devices",|заглавие=EN 529:2005. Respiratory protective devices. Recommendations for selection, use, care and maintenance. Guidance document|ответственный=CEN|год=2005|язык=en|место=Brussels|издательство=European Committee for Standardization|allpages=50|серия=13.340.30}}</ref> <ref name="AN-2006">{{Статья|ссылка=https://onlinelibrary.wiley.com/doi/full/10.1111/j.1600-0404.2005.00560.x|автор=E.C.H. Lim, R.C.S. Seet, K.‐H. Lee, E.P.V. Wilder‐Smith, B.Y.S. Chuah, B.K.C. Ong|заглавие=Headaches and the N95 face-mask amongst healthcare providers|год=2006|язык=en|издание=Acta Neurologica Scandinavica|издательство=John Wiley & Sons|выпуск=3|pages=199—202|volume=113|doi=10.1111/j.1600-0404.2005.00560.x }} ISSN 0001-6314, {{PMID|16441251}}, есть [https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1606578563&archive=&start_from=&ucat=& перевод] </ref> <ref name="ANZ-СИЗОД-тест">{{Книга|ссылка=https://www.standards.govt.nz/shop/ASNZS-17162012|автор=Joint Technical Committee SF-010, Occupational Respiratory Protection |заглавие= AS/NZS 1716:2012. Respiratory protective devices |год=2012|язык=en|издание=5th ed|место=Sydney, New South Wales|издательство=Standards Australia|allpages=128|isbn=978-1-74342-024-9}}</ref> <ref name="Haupt-2006">{{Статья|автор=Nadine Haupt & Peter Paszkiewicz|заглавие=Breakthrough Measurements for Small-Capacity Cartridges at Elevated Flow Rates in Different Flow Modes|год=2006|язык=en|автор издания=International Society for Respiratory Protection|место=Pittsburgh, PA|издание=[https://www.isrp.com/the-isrp-journal Journal of the International Society for Respiratory Protection]|издательство=Navigator Printing|выпуск=3-4|pages=77-88|volume=23 }} ISSN 0892-6298.</ref> <ref name="Japan-gas">{{Книга|ссылка= https://webdesk.jsa.or.jp/books/W11M0090/index/?bunsyo_id=JIS+T+8152%3A2012 |автор=Japanese Safety Appliances Association|заглавие=JIS T 8152:2012 Gas respirators |ответственный=Technical Committee on Protective Equipment for Occupational Safety|год=2012 |оригинал=JIS T 8152:2012 防毒マスク |язык=jp en|место=Minato-ku, Tokio|издательство=Japanese Standards Association|allpages= 32 }} [https://www.jisha.or.jp/international/jicosh/english/law/GasMask/index.html html en]</ref> <ref name="Japan-dust">{{Книга|ссылка= https://webdesk.jsa.or.jp/books/W11M0090/index/?bunsyo_id=JIS+T+8151%3A2018 |автор=Japanese Safety Appliances Association|заглавие=JIS T 8151:2018 Particulate respirators |ответственный=Technical Committee on Protective Equipment for Occupational Safety|год=2018 |оригинал=JIS T 8151:2018 防じんマスク |язык=jp en|место=Minato-ku, Tokio|издательство=Japanese Standards Association|allpages= 39 }} [https://www.jisha.or.jp/international/jicosh/english/law/DustMask/index.html html en]</ref> <ref name="Индия-полумаска">{{Книга|автор=Industrial Safety and Chemical Hazards Sectional Committee, CHD 8|заглавие=Indian Standard IS 14746:1999. Respiratory protective devices — Half masks and quarter masks — Specification|ссылка= https://www.iitr.ac.in/safety/PPE/14746_RESPIRATORY_PROTECTIVE_DEVICES-HALF_FACE_MASKS__QUATER_MASKS-SPECIFICATION.pdf |год=2004|язык=en|место=New Deli|издательство=Bureau of Indian Standards|allpages=23|серия=ICS 13.340.30}}</ref> <ref name="Индия-фильтр">{{Книга|автор=Industrial Safety and Chemical Hazards Sectional Committee, CHD 8|заглавие=Indian Standard IS 15323:2003. Gas filters and combined filters used in respiratory protective equipment — Specification|ссылка= https://law.resource.org/pub/in/bis/S02/is.15323.2003.pdf |год=2003|язык=en|место=New Deli|издательство=Bureau of Indian Standards|allpages=15|серия=ICS 13.340.30}}</ref> <ref name="КНР-СИЗОД-ФПМ">{{Книга|ссылка=https://www.chinesestandard.net/PDF.aspx/GB2626-2019|заглавие=GB 2626-2019. Respiratory protection - Non-powered air-purifying particle respirator|год=2019|оригинал=GB 2626-2019 呼吸防护 自吸过滤式防颗粒物呼吸器|язык=en|издательство=China National Standards|ответственный=Standardization Administration of PRC|allpages=57|серия=ICS 13.340.30}}</ref> <ref name="КНР-SCBA">{{Книга|ссылка=|автор=Institute of Chemical Defense|заглавие=GB/T 16556-2007. Respiratory protection - Self-contained open-circuit compressed air breathing apparatus (EN 137:2002) |год=2007|оригинал= GB/T 16556-2007 自给开路式压缩空气呼吸器|язык=en|ответственный=Standardization Administration of PRC |издательство=State Administration for Market Regulation|allpages=57|серия=ICS 13.340.30}}</ref> <ref name="Сорокин-2011">{{статья|автор=Сорокин ЮГ (АСИЗ)|заглавие=Роль средств индивидуальной защиты в охране труда|издание=Справочник специалиста по охране труда|место=Москва|издательство=МЦФР|год=2011|номер=7|страницы=43-48}} ISSN 1727-6608. Цитата: ''"Не секрет, что проблемы с качеством СИЗ существуют. К сожалению, ситуация в данной сфере такова, что достаточно выпустить 5-7 доброкачественных изделий, провести испытания и получить сертификат, а потом можно выпускать изделия более низкого качества. Особенно эта проблема актуальна для лёгких респираторов и некоторых других технически несложных СИЗ''"</ref> <!-- Комментарий --> СИЗОД выбор <ref name="СИЗОД-США+">Стандарт США ('''''действующий''''') [http://www.osha.gov/pls/oshaweb/owadisp.show_document?p_table=STANDARDS&p_id=12716 US Standard 29 CFR 1910.134 «Respiratory protection»] - OSHA. Перевод: [http://commons.wikimedia.org/wiki/File:Стандарт респиратор.pdf PDF] [[:w:s:ru:Требования_к_выбору_эффективных_респираторов_и_к_организации_их_применения| Wiki]]</ref> <ref name="Руководство 1976г">{{книга|автор=Nelson Leidel, Kenneth Bush & Jeremiah Lich|заглавие=NIOSH Occupational Exposure Sampling Strategy Manual|ссылка=https://www.cdc.gov/niosh/docs/77-173/|место=Cincinnati, Ohio|издательство=National Institute for Occupational Safety and Health|год=1977|серия=DHHS (NIOSH) Publication Number 77-173|allpages=150}} Есть перевод: [[:w:File:Руководство NIOSH по измерению загрязнённости воздуха 25.04.2014.pdf|PDF]] [https://ru.wikibooks.org/wiki/Измерение_загрязнённости_воздуха Wiki] Документ однозначно показывает, что измерение загрязнённости воздуха "рабочей зоны" (1.5 м от пола) может сильно занизить реальную загрязнённость вдыхаемого воздуха в зоне дыхания (25 см от лица) - см. [https://ru.wikibooks.org/wiki/Измерение_загрязнённости_воздуха#PriligenieC приложение '''С''' ''стр. 77-79'']</ref> <ref name="Федорук-2025">{{Книга |ссылка=https://irioh.ru/publish-books-2025-18ohrnc-materials/ |автор= Федорук А.А., Иващенко М.А., Мартин С.В. |заглавие=Материалы 18‐го Российского Национального Конгресса с международным учас­тием «Профессия и здоровье» и 5‐го Международного Молодежного Форума «Профессия и здоровье», 21‐26 сентября 2025 г., Красноярск. |ответственный=[[:w:Бухтияров, Игорь Валентинович|И.В. Бухтияров]] науч. ред. |год=2025 |часть=Подходы к контролю и оценке экспозиции промышленного аэрозоля |ссылка часть=https://doi.org/10.31089/978-5-6042929-8-3-2025-1-447-450 |место=Москва |издательство=ФГБНУ "НИИ медицины труда им. акад. [[:w:Измеров, Николай Федотович|Н.Ф. Измерова]]" |страницы=447-450 |всего страниц=492 |серия=Редколегия Кузьмина Л.П., Рубцова Н.Б., Прокопенко Л.В., Шиган Е.Е., Лысухин В.Н. |isbn=978-5-6042929-8-3 |doi=10.31089/978-5-6042929-8-3-2025-1-447-450}}</ref> <ref name="Кириллов-2016в">{{статья|автор=Кириллов В.Ф., Филин А.С.|заглавие=Измерение концентрации вредных веществ в воздухе (обзор)|подзаголовок=|ссылка=http://novtex.ru/bjd/archiv2016.html|язык=ru|автор издания=|издание=Безопасность жизнедеятельности|место=Москва|издательство="Новые технологии"|год=2016|номер=11|страницы=9 – 14|issn=|archivedate=2017-02-26|archiveurl=https://web.archive.org/web/20170226130824/http://novtex.ru/bjd/archiv2016.html}} ISSN 1684-6435</ref> <ref name="CPL-СИЗОД">''Charles Jeffress'' [http://www.osha.gov/pls/oshaweb/owadisp.show_document?p_table=DIRECTIVES&p_id=2275 «Instruction CPL 2-0.120»]. — OSHA, 1998. Есть перевод: [http://commons.wikimedia.org/wiki/File:Проверка_инспектором.pdf «Инструкция для инспекторов по охране труда с указаниями - как проводить проверку выполнения требований стандарта по респираторной защите (США)»] [[:w:s:Инструкция для инспектора по охране труда, проверяющего выполнение требований стандарта Респираторная защита| Wiki]]</ref> <ref name="НН-2023">{{Книга|ссылка=https://medialnn.ru/?id=58984 |автор=Капцов В.Н., Панкова В.Б.|заглавие=Проблемы гигиенической безопасности и профилактики нарушений трудоспособности у работающих|ответственный=И.А. Умнягина (ред.)|год=2023|часть= Определение периодичности замены противогазных фильтров респираторов |издание=ФБУН «Нижегородский научно-исследовательский институт гигиены и профпатологии» Роспотребнадзора|место=Нижний Новгород|издательство= «Медиаль»|страницы=153-161|страниц=298|серия=Материалы Всероссийской научно-практической интернет-конференции с международным участием, г. Нижний Новгород, 29–30 ноября 2023 г.|isbn=978-5-6051016-3-5|doi=10.21145/978−5-6051016−3-5_2023}} [https://elibrary.ru/item.asp?id=56122087 PDF]</ref> <ref name="Japan-СИЗОД">{{Книга|ссылка=https://webdesk.jsa.or.jp/books/W11M0090/index/?bunsyo_id=JIS+T+8150%3A2021|автор=Japanese Safety Appliances Association|заглавие=JIS T 8150:2021. Guidance for selection, use and maintenance of respiratory protective devices|ответственный=Technical Committee on Protective Equipment for Occupational Safety|год=2021|оригинал=JIS T 8150:2021 呼吸用保護具の選択,使用及び保守管理方法|язык=jp en|место=Minato-ku, Tokio|издательство=Japanese Standards Association|allpages=120}} [https://kikakurui.com/t8/T8150-2006-01.html текст 2006 г., на японском]</ref> <ref name="Japan-dust-">{{Книга|ссылка=https://www.mhlw.go.jp/web/t_doc?dataId=00tc2747&dataType=1&pageNo=1|автор=Labour Standards Bureau|заглавие=Selection, and use of respiratory protection equipment|ответственный=Ministry of Health Labour and Welfare|год=2005-02-07|язык=jp|место=Japan|серия=Labor Standards Bureau Notification No. 0207006}}</ref> <ref name="Индия-СИЗОД">{{Книга|ссылка=https://upload.wikimedia.org/wikipedia/commons/3/38/ГОСТ_Индии_Выбор_и_организация_применения_СИЗОД_is.9623.2008.pdf|автор=Occupational Safety and Health and Chemical Hazards Sectional Committee, CHD 8|заглавие=Indian Standard IS 9623 (2008): Selection, use and maintenance of respiratory protective devices|год=2008 (2023)|язык=en|издание=1st ed|место=New Deli|издательство=Bureau of Indian Standards|allpages=35|серия=Code of practice}} [https://law.resource.org/pub/in/bis/S02/is.9623.2008.html копия] [https://standardsbis.bsbedge.com/BIS_SearchStandard.aspx?Standard_Number=IS%209623&id=21 копия] [https://www.iitr.ac.in/safety/PPE/9623_RECOMENDATION_FOR_SELECTION__USE_OF_RESPIRATORY_DEVICE.pdf (1981)]</ref> <ref name="Обзор-2014">{{статья|автор=Кириллов В.Ф. и др.|заглавие=Обзор результатов производственных испытаний средств индивидуальной защиты органов дыхания (СИЗОД)|ссылка=https://cyberleninka.ru/article/n/obzor-rezultatov-proizvodstvennyh-ispytaniy-sredstv-individualnoy-zaschity-organov-dyhaniya-sizod |автор издания=ФБУЗ "Российский регистр потенциально опасных химических и биологических веществ" Роспотребнадзора|издание=Токсикологический вестник|место=Москва|год=2014|номер=6 (129)|страницы=44—49 }} ISSN 0869-7922. [https://ru.wikisource.org/wiki/Обзор_результатов_производственных_испытаний_средств_индивидуальной_защиты_органов_дыхания_(СИЗОД) Wiki] </ref> <ref name="Обзор-2019">{{Статья|ссылка=https://www.rjhas.ru/jour/article/view/383|автор=[[:w:Капцов, Валерий Александрович|Капцов В.А.]], Чиркин А.В.|заглавие=Выбор работодателем средств индивидуальной защиты органов дыхания в зависимости от результатов их испытаний на рабочих местах (обзор)|год=2019|автор издания=Издатель ФБУН «Федеральный научный центр гигиены им. Ф.Ф. Эрисмана» Роспотребнадзора|место=Москва|издание=Гигиена и санитария|тип=журнал|том=98|номер=8|страницы=845-850|doi=10.47470/0016-9900-2019-98-8-845-850}} ISSN 0016-9900.</ref> <ref name="КНР-СИЗОД+">{{Книга|ссылка= https://www.chinesestandard.net/PDF.aspx/GBT18664-2002 |автор=State Administration of Work Safety|заглавие=GB/T 18664-2002 Selection, use and maintenance of respiratory protective equipment|год=2002|оригинал=GB/T 18664-2002 呼吸防护用品的选择、使用与维护|язык=en|allpages=62|серия=ICS 13.340.30}}</ref> <ref name="Капцов-2020">{{Статья|ссылка=https://journal.fcrisk.ru/2020/4/21|автор=Капцов В.А., Чиркин А.В.|заглавие=Требования к организации респираторной защиты работающих (обзор мировой практики)|год=2020|язык=ru|автор издания=ФБУН и «Федеральный научный центр медико-профилактических технологий управления рисками здоровью населения» Роспотребнадзора|место=Пермь|издание=Анализ риска здоровью|месяц=12|номер=4|страницы=188-195|doi=10.21668/health.risk/2020.4.21}} ISSN 2308-1155. [https://cyberleninka.ru/article/n/trebovaniya-k-organizatsii-respiratornoy-zaschity-rabotayuschih-obzor-mirovoy-praktiki копия]</ref> <ref name="ТР-2009">{{Статья|автор=А. Лянг|заглавие=Требуются публичные обсуждения|год=2009|автор издания=Общество с ограниченной ответственностью ТехНадзор|место=Екатеринбург|издание=[https://www.elibrary.ru/contents.asp?titleid=51310 Технадзор]|месяц=7|номер=7 (32)|страницы=84-85}}</ref> <ref name="ГОСТ-РХЗ">{{Книга|автор=ОАО "Росхимзащита"|заглавие=ГОСТ Р 12.4.279-2012. ССБТ. Средства индивидуальной защиты органов дыхания. Рекомендации по выбору, применению и техническому обслуживанию|место=Москва|издательство=ФГУП "Стандартинформ"|год=2014|страниц=41|серия=EN 529:2005 Respiratory protective devices - Recommendations for selection, use, care and maintenance - Guidance document|ссылка= https://meganorm.ru/Index2/1/4293776/4293776889.htm|ответственный=ТК 320 «СИЗ»|тираж=66}} [https://meganorm.ru/Data2/1/4293776/4293776889.pdf PDF]</ref> <ref name="ГОСТ-РХЗ-2">{{Книга|автор=ОАО "Росхимзащита"|заглавие=ГОСТ Р 12.4.299-2015. ССБТ. Средства индивидуальной защиты органов дыхания. Рекомендации по выбору, применению и техническому обслуживанию|место=Москва|издательство=ФГУП "Стандартинформ"|год=2016|страниц=28|серия=EN 529:2005 Respiratory protective devices - Recommendations for selection, use, care and maintenance - Guidance document|ссылка=https://meganorm.ru/Index/60/60298.htm |ответственный=ТК 320 «СИЗ»|тираж=1}} [https://meganorm.ru/Data2/1/4293762/4293762732.pdf PDF]</ref> <ref name="Кириллов-2016">{{статья|автор=Кириллов В.Ф. и др.|заглавие=О респираторной защите работников |автор издания=НИИ медицины труда РАН|издание=Медицина труда и промышленная экология|ссылка= https://www.journal-irioh.ru/jour/article/view/513|Медицина труда и промышленная экология|место=Москва|издательство=|год=2016|номер=9|страницы=39-42}} ISSN 1026-9428.</ref> <ref name="Учебник 2004">{{книга|автор=Nancy Bollinger|заглавие=NIOSH Respirator Selection Logic|ссылка=https://www.cdc.gov/niosh/docs/2005-100/|издание=NIOSH|место=Cincinnati, OH|издательство=National Institute for Occupational Safety and Health|год=2004|серия=DHHS (NIOSH) Publication No 2005-100|allpages=32}} Есть перевод: Руководство по выбору респираторов [https://commons.wikimedia.org/wiki/File:NIOSH_Respirator_Selection_Logic_---_Руководство_по_выбору_респираторов_NIOSH_2004г.pdf PDF] [[w:b:ru:Выбор респираторов (NIOSH, США)| Wiki]]</ref> <ref name="Учебник 1987">{{книга|автор=Nancy J. Bollinger, Robert H. Schutz et al|заглавие=NIOSH Guide to Industrial Respiratory Protection|ссылка=https://www.cdc.gov/niosh/docs/87-116/|издание=NIOSH|место=Cincinnati, Ohio|издательство=National Institute for Occupational Safety and Health|год=1987|серия=DHHS (NIOSH) Publication No 87-116|allpages=305}} Есть перевод (2014): [https://commons.wikimedia.org/wiki/File:NIOSH_Руководство_по_применению_респираторов_в_промышленности_1987.pdf PDF] [[w:b:ru:Применение респираторов в промышленности|Wiki]]</ref> <ref name="Учебник 1999">{{книга|автор=Linda Rosenstock et al|заглавие=TB Respiratory Protection Program In Health Care Facilities - Administrator's Guide|ссылка=https://www.cdc.gov/niosh/docs/99-143/|место=Cincinnati, Ohio|издательство=National Institute for Occupational Safety and Health|год=1999|серия=DHHS (NIOSH) Publication No. 99-143|страниц=120}} Есть перевод: Руководство по применению респираторов в медучреждениях для профилактики туберкулёза [https://commons.wikimedia.org/wiki/File:TБ_Руководство_NIOSH.pdf PDF] [[w:b:ru:Профилактика туберкулёза в медучреждениях |Wiki]]</ref> <ref name="Учебник-2013">{{книга|автор=Great Britain Health and Safety Executive|заглавие=Respiratory protective equipment at work. A practical guide|ссылка=http://www.hse.gov.uk/pubns/books/hsg53.htm |издание=4 ed|издательство=HSE Books |год=2013|серия=Health and safety guidance HSG53 | allpages=59|isbn=978-0-71766-454-2}}</ref> <ref name="eTool">[[:w:b:ru:Замена противогазных фильтров СИЗОД|Замена противогазных фильтров по расписанию]]. Требования и рекомендации Управления по охране труда — OSHA. www.osha.gov (2019). ; Occupational Safety and Health Administration. [https://www.osha.gov/SLTC/etools/respiratory/change_schedule.html Respirator Change Schedules]. Respiratory Protection eTool (англ.). www.osha.gov (2019). Дата обращения 8 декабря 2019.</ref> <ref name="Лазарев-3">{{Книга|ссылка=https://eco-profi.info/index.php/othod/liter/article/dokum-klop/24-ld-lc/651-lazarev3.html |автор=Абрамова Ж.И., Гадаскина И.Д. и др|заглавие=Вредные вещества в промышленности. Справочник для химиков, инженеров и врачей|ответственный=Н.В. Лазарев, И.Д. Гадаскина ред|год=1977|часть=Углекислый газ|издание=7-е изд|место=Ленинград|издательство=Издательство "Химия"|том=III|страницы=23|страниц=608|тираж=52 000}} копия [https://makston-engineering.ru/library-no8-7 1] [https://vk.com/doc6787360_437497730?hash=JPOOsh21mKIia3XIBWnAGZN9FlA2R6hnWl2Q8mnvrZz 2] [http://www.vixri.ru/?p=4632 3]</ref> <ref name="NIOSH-CO2">[https://www.cdc.gov/niosh/npg/npgd0103.html Carbon dioxide] . {{книга|заглавие=NIOSH Pocket guide to chemical hazards|ссылка= https://www.cdc.gov/niosh/npg/ |ответственный=Michael E. Barsan (technical Editor)|издание=NIOSH|место=Cincinnati, Ohio|год=2007|серия=DHHS (NIOSH) Publication No. 2005-149|pages=53|allpages=454|}}</ref> <ref name="ВНИИС">''Сорокин Ю.Г. <small>(АСИЗ)</small>, Версан В.Г. <small>(ВНИИС)</small>''. Соглашение о сотрудничестве. ''www.asiz.ru''. АСИЗ (27 февраля 2015).</ref> <!-- Комментарий -->{{Cite web|url=http://asiz.ru/tk320/sotrud_tk_siz.pdf|title=Соглашение о сотрудничестве|author=Сорокин Ю.Г. (АСИЗ), Версан В.Г. (ВНИИС)|website=www.asiz.ru|date=27-02-2015|publisher=АСИЗ}} <ref name="Обзор-2001">{{книга|автор=U.S. Department of Labor, Bureau of Labor Statistics|заглавие=Respirator Usage in Private Sector Firms, 2001|ссылка=https://www.regulations.gov/document/EPA-HQ-OPPT-2016-0231-0120 |издание=U.S. Department of Health and Human Services, Centers for Disease Control and Prevention, National Institute for Occupational Safety and Health|место=Morgantown, WV|год=2003|allpages=273}} [http://www.cdc.gov/niosh/docs/respsurv/pdfs/respsurv2001.pdf PDF]</ref> <ref name="UK-2011">{{Статья|автор=R. Graveling, A. Sánchez-Jiménez, C. Lewis, S. Groat|заглавие=Protecting Respiratory Health: What Should be the Constituents of an Effective RPE Programme? |язык=en|язык издания=en|автор издания=British Occupational Hygiene Society|издание=The Annals of Occupational Hygiene|издательство=Oxford University Press|год=2011|месяц=3|выпуск=3|pages= 230–238 |volume=55|doi=10.1093/annhyg/meq098}} ISSN 2398-7308, {{PMID|21257742}}.</ref> <ref name="UK-2012">{{Статья|автор=N. Bell, N.P. Vaughan, L. Morris, P. Griffin|заглавие=An Assessment of Workplace Programmes Designed to Control Inhalation Risks Using Respiratory Protective Equipment|язык=en|язык издания=en|автор издания=British Occupational Hygiene Society|издание=The Annals of Occupational Hygiene|издательство=Oxford University Press|год=2012|месяц=3|выпуск=3|pages=350-361|volume=56|doi=10.1093/annhyg/mer109}} ISSN 2398-7308, {{PMID|22156569}}.</ref> <ref name="Кириллов-2018">{{статья|автор=Капцов В.А., Чиркин А.В.|заглавие=[[:w:s:Об эффективности средств индивидуальной защиты органов дыхания как средства профилактики заболеваний (обзор)|Об эффективности средств индивидуальной защиты органов дыхания как средства профилактики заболеваний (обзор)]]|автор издания=ФБУЗ "Российский регистр потенциально опасных химических и биологических веществ" Роспотребнадзора|издание=[http://toxreview.ru/ Токсикологический вестник]|место=Москва|год=2018|номер=2 (149)|страницы=2-6 |doi=10.36946/0869-7922-2018-2}} ISSN 0869-7922. [https://cyberleninka.ru/article/n/ob-effektivnosti-sredstv-individualnoy-zaschity-organov-dyhaniya-kak-sredstva-profilaktiki-zabolevaniy-obzor копия]</ref> <ref name="Кириллов">{{статья|автор=Редакция|заглавие=Некролог. Памяти Владимира Федоровича Кириллова |язык=ru|автор издания=НИИ медицины труда РАМН|ссылка= https://www.journal-irioh.ru/jour/article/view/385 |издание=Медицина труда и промышленная экология|место=Москва|год=2015|номер=10|страницы=46}} ISSN 1026-9428.</ref> <ref name="Сорокин-2006">{{Книга|автор=под ред. Сорокина Ю.Г., Преображенского В.Б. и др|заглавие=Методические рекомендации по выбору и применению средств индивидуальной защиты органов дыхания|ответственный=|издание=|место=Москва|издательство=Издательство "КОЛОС"|год=2006|страницы=22-35|страниц=56|isbn=5-10-003932-9|часть=3.3 Выбор фильтрующих СИЗОД|язык=ru|тираж=2000}} [https://web.archive.org/web/20150725140959/http://gochs.info/p0898.htm аналог]</ref> <ref name="Кошелев-Тарасов">{{Книга|автор=Тарасов В.И., Кошелев В.E.|заглавие=Просто о непростом в применении средств защиты дыхания|год=2007|часть=8. Приложения|место=Пермь|издательство=Агентство "Стиль-МГ"|страницы=179-273|страниц=280|isbn=978-5-8131-0081-9|ссылка=https://vk.com/wall-108649797_8150?ysclid=m30i2dz4em910619809|серия=для отделов охраны труда промышленных предприятий}}</ref> <ref name="Кириллов-2013">{{Статья|ссылка=https://cyberleninka.ru/article/n/o-sredstvah-individualnoy-zaschity-organov-dyhaniya-rabotayuschih-obzor-literatury/viewer|автор=Кириллов В.Ф., Бучнев А.А., Чиркин А.В.|заглавие=О средствах индивидуальной защиты органов дыхания работающих (обзор литературы) |год=2013|автор издания=НИИ медицины труда РАН и Роспотребнадзор|место=Москва|издание=[https://www.journal-irioh.ru/jour/about Медицина труда и промышленная экология]|месяц=4|номер=4|страницы=25-31}} ISSN 1026-9428. [https://ru.wikipedia.org/wiki/Файл:Медицина_труда_и_промышленная_экология_2013_04_25-31.jpg JPG] [https://ru.wikisource.org/wiki/О_средствах_индивидуальной_защиты_органов_дыхания_работающих_(обзор_литературы) Wiki] </ref> <ref name="Великобритания-2013">{{книга|автор=The Health and Safety Executive|заглавие=Respiratory protective equipment at work. A practical guide|ссылка=http://www.hse.gov.uk/pubns/books/hsg53.htm|издание=4 edition|издательство=Crown|год=2013|серия=HSG53|allpages=59|isbn=978-0-71766-454-2|archive-date=2015-08-09|archive-url=https://web.archive.org/web/20150809032140/http://www.hse.gov.uk/pubns/books/hsg53.htm}}</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] ca1jcapemq5d7zm1a79x3j3lgcgryli Средства индивидуальной защиты (обзорная лекция)/СИЗ органов слуха 0 35688 270426 269660 2026-10-27T07:08:36Z Jcb 79968 270426 wikitext text/x-wiki Средства индивидуальной защиты органов слуха - вид [[:w:ru:Средства индивидуальной защиты|средств индивидуальной защиты]], предназначенный для уменьшения опасного воздействия [[:w:ru:Производственный шум|шума]] на органы слуха. [[File:Ослабление-шума-СИЗОС.jpg|thumb|right|410px|Средние ослабления звуков разных частот у 121 (1975) и 241 модели СИЗОС (1994)<ref name="Рязань-2023" />]] [[File:Алиса-2003-0002+++.jpg|thumb|right|410px|Ослабление шума одними и теми же моделями [[:w:ru:СИЗОС|СИЗ]], на <span style="color:Green">'''рабочих местах'''</span> и <span style="color:Red">'''в лабораториях'''</span><ref name="Алиса-2003" />]] Поиск публикаций на русском языке<ref>''[[:w:ru:Капцов,_Валерий_Александрович |Капцов В.А.]], Панкова В.Б., Чиркин А.В.'' [https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1653059572&archive=&start_from=&ucat=& Повышение эффективности средств индивидуальной защиты органа слуха]. <small>(Доклад на Втором Всероссийском конгрессе с международным участием "Лечебно-реабилитационные перспективы при слухоречевых и голосовых расстройствах")</small> 17 мая 2022 г. ''www.library.by'' (22 мая 2022). Дата обращения: 28 ноября 2020. [https://www.researchgate.net/publication/360777777_Povysenie_effektivnosti_sredstv_individualnoj_zasity_organa_sluha_Improving_the_effectiveness_of_hearing_protective_devices копия] </ref> не выявил исследований, в которых бы сравнивалась заболеваемость работников использовавших и не использовавших СИЗ органа слуха в схожих условиях. По данным<ref name="AIHA-2018" /> на западе провели три исследования влияния СИЗ органа слуха на риск развития [[:w:ru:нейросенсорная тугоухость|нейросенсорной тугоухости]]. Ни одно не выявило значимого отличия в заболеваемости — при том, что в США выбор и применение СИЗ органа слуха организовано более тщательно, чем в СССР и в РФ. Так например, группа специалистов из [[:w:ru:Национальный институт охраны труда|Национального института охраны труда]] (NIOSH, в Министерстве здравоохранения США), используя уникальную базу данных, подобрала сведения о более чем 19 тыс. рабочих разных отраслей экономики, у которых [[:w:ru:Аудиометрия|проверяли состояние органа слуха]] в течение 5 лет. Оказалось, что частота значительного ухудшения слуха у тех, кто использовал СИЗ органа слуха, немного ниже, чем у тех, кто их совсем не использовал. А анализ этого отличия показал, что оно [[:w:ru:Статистическая значимость|статистически незначительно]]<ref name="Groenewold-2014" />. Причём ситуацию в РФ усугубляет то, что работникам просто выдают СИЗ органа слуха — без индивидуального подбора и [[:w:ru:Производственный контроль эффективности средств индивидуальной защиты органа слуха|проверки фактической эффективности]]<ref name="AIHA-2018-12">{{Книга|ссылка=https://www.aiha.org/education/marketplace/noise-manual-6th-edition|автор=Jérémie Voix, Pegeen Smith, Elliott Berger|часть=Chapter 12. Field Fit-Testing and Attenuation-Estimation Procedures|заглавие=The Noise Manual|издание=6th ed|ответственный=D.K. Meinke, E.H. Berger, R. Neitzel, D.P. Driscoll & K. Bright eds|год=2020|язык=en|место=Falls Church|издательство=American Industrial Hygiene Association|ссылка часть=https://online-ams.aiha.org/amsssa/ecssashop.show_product_detail?p_mode=detail&p_product_serno=2720|страниц=621|archive-date=2022-03-09|archive-url=https://web.archive.org/web/20220309002640/https://www.aiha.org/education/marketplace/noise-manual-6th-edition}}</ref>. В результате часть работников получает такие средства защиты, которые могут вызывать непереносимые болевые ощущения, и при этом не обеспечивать снижение уровня шума до безопасного уровня. Но даже при своевременном использовали, как показали первые исследования в 1970-х гг., ослабление шума у работников очень разное, и в среднем значительно меньше, чем при сертификационных испытаниях в лабораторных условиях<ref name="NIOSH-1979" /><ref name="Алиса-2003" />; и у значительной доли работников оно может быть близким к нулю<ref name="Lee-2022" />. === Научные исследования === До второй половины 1970-х изучение ослабления шума при использовании СИЗОС велось лишь в лабораторных условиях, т.к. ожидалось, что у рабочих оно будет таким же, или немножко меньше. Кроме того, возможность проводить измерения у работников часто отсутствовала. Результаты лабораторных исследований показали, что ослабление звуков зависит от их частоты, низкочастотные звуки ослабляются значительно хуже, чем высокочастотные. Также оказалось, что у участников исследований при использовании одних и тех же моделей противошумов получаются схожие ослабления шума. На основе это информации в США был разработан Закон "О защите от шума", с разделом по СИЗОС. Требовалось испытывать их в лабораторных условиях, и затем наносить маркировку, показывающую степень ослабления шума со "стандартным" частотным спектром<ref name="Алиса-2003" /> (т.н. [[:w:ru:Фликкер-шум|"розового"]], у него распределение акустической энергии по диапазонам частот ([[:w:ru:октава|октавам]]) схоже с "средним" промышленным шумом). За нарушение требований предусматривались большие штрафы, т.к. предполагалось, что правильная маркировка станет эффективным помощником работодателю при выборе подходящих средств защиты работников при известном воздействии шума. Замеры ослабления шума у рабочих на заводах показали, что оно очень нестабильное, и в среднем гораздо меньше, чем при испытаниях, примеры<ref name="NIOSH-1979" /><ref name="Lee-2022" />. Например, в группе работников, использующих одинаковые модели в схожих условиях, разнообразие ±20 дБ - не редкость<ref name="CSA-2014" />. Чтобы снизить отличие между средними лабораторными и реальными результатами, разработан новый способ тестирования<ref name="ISO-5" />: оказалось, что если к сертификации привлекают совершенно неопытных людей, и те надевают СИЗОС самостоятельно, по инструкции от изготовителя, результаты более похожи на получаемые у рабочих на заводах (см. диаграмму справа). Из-за организационных и бюрократических проблем скорректировать требования законодательства, приведя их в соответствие с современным уровнем науки, в США не удалось (описано ниже). Получив результаты измерений у рабочих, специалисты не имели никакой возможности учесть сильное разнообразие ослабления шума у разных людей. Они сначала попытались учесть хотя бы то, что среднее ослабление шума у группы рабочих заметно ниже, чем у испытателей при сертификации. Для этого в разных странах разные организации предложили корректировать результаты сертификационных испытаний, как показано в таблице (p. 289<ref name="AIHA-2018" /> и<ref name="Капцов-2023" />): [[Файл:Usage_NIOSH_Well-Fit_for_HPD_Field-Testing_(earplug_fit_test,_2015).jpg|thumb|right|410px| [[:w:ru:Производственный контроль эффективности СИЗОС|Замер фактического ослабления]] шума [[:w:ru:Беруши|вкладышами]] у 2 работников<ref name="NIOSH-2015" /> с помощью специального оборудования.]] {| class="wikitable" style="text-align:center" |+ Попытки снизить значительное отличие между ослаблением шума в лабораториях и на заводах ! rowspan="2" | Страна, организация ! colspan="2" | Вкладыши ! rowspan="2" | Наушники |- ! Из пористого эластичного материала, сжимаемые перед установкой в ухо ! Из эластомерного материала |- | США, OSHA || Снижение '''в 2 раза''' || Снижение в '''2 раза''' || Снижение '''в 2 раза''' |- | США, NIOSH || Снижение '''в 2 раза''' || Снижение '''в 3,3 раза''' || Снижение '''в 1,33 раза''' |- | Италия || Снижение '''в 2 раза''' || Снижение '''в 3,3 раза''' || Снижение '''в 1,33 раза''' |- | Великобритания || ''Снижение на 4 дБ'' || ''Снижение на 4 дБ'' || ''Снижение на 4 дБ'' |- | Франция || ''Снижение на 10 дБ'' || ''Снижение на 10 дБ'' || ''Снижение на 5-7 дБ'' |- | ФРГ || ''Снижение на 9 дБ'' || ''Снижение на 5 дБ'' || ''Снижение на 5 дБ'' |- | Китай || colspan="3" | Уменьшали показатель ослабления шума (в виде одного числа) на 60% - в прошлом<ref name="КНР-шум-практика" /> |- | Австралия Новая Зеландия Бразилия | colspan="3" | При сертификации испытывают СИЗ на совершено неопытных участниках, полученный результат используют без уменьшения<ref name="КНР-шум-практика" /> |} Видно, что эта "половинчатая" попытка снизить отличие реальной степени защиты от сертификационной оказалась не очень удачной: в разных странах, и даже в одной стране, предлагались очень разные способы коррекции. И все они не учитывали значительное разнообразие уровней защиты у отдельных, конкретных работников, то есть - не позволяли выявить тех, кто плохо защищён. Всё же, использование "дерейтинга" снижает дезинформированность потребителей и риск выдачи работникам совершенно неэффективных СИЗ; поэтому российские специалисты по профзаболеваниям предложили использовать такой подход и в РФ (2 издание<ref name="Кириллов-2010" />, статья<ref name="Денисов-2013" />) - за отсутствием лучших способов индивидуальной защиты. В 1990-х в NIOSH была проведена большая работа по созданию такого средства, которое позволит проверять ослабление шума у конкретного работника, при проведении измерений прямо на предприятии. Т.к. в США чаще используют вкладыши, и у них ослабление шума менее стабильно, чем у наушников, для проверки был разработан сильно упрощённый аналог [[:w:ru:Аудиометр|аудиометра]]: наушники + программное обеспечение для компьютера (работодателя). У работника измеряли пороги восприятия звуков разных частот, а потом повторяли замеры при установленных вкладышах. Позднее другие средства измерений начали изготавливаться разными компаниями, и на западном рынке есть в продаже более десятка измерительных систем. Во всех развитых странах специалисты настоятельно рекомендуют работодателям [[:w:ru:Производственный контроль эффективности СИЗОС|проводить проверки индивидуально]], и при первоначальном выборе СИЗОС, и потом периодически<ref name="AIHA-2018" />. В нескольких странах намерены изменить законодательство, и сделать такие проверки обязательными, но пока это произошло лишь в одной провинции Канады<ref name="Альберта-2022" />. Проверка качества работы разных измерительных систем показала, что они могут давать значительно отличающиеся друг от друга результаты. Поэтому в США разработали требования к показателям качества таких средств измерений<ref name="ANSI-2018" />. === Требования к противошумам и их сертификация === * '''<big> США </big>''' В 1970-х началась работа по сертификации СИЗ органа слуха, этим занималось [[:w:Агентство по охране окружающей среды США|Агентство по охране окружающей среды]] ''(EPA)''<ref name="Alice-2012" />, т.к. они вели работу и по коммунальному, и по [[:w:ru:Промышленный шум|производственному шуму]], и всем средствам защиты от него, включая коллективные<ref name="Алиса-2003" />. Для испытаний был выбран новый (на то время) стандарт [[:w:Американский национальный институт стандартов|Института стандартов]]<ref name="ANSI-1974" />. Работа продвигалась, но в начале 1980-х [[:w:Рейган, Рональд|Рейган]] полностью [[:w:ru:Управление по охране труда (OSHA)#noise|прекратил её (для "уменьшения государственного регулирования экономики")]]<ref name="Alice-2012" />. Требование испытывать СИЗОС по стандарту 1974 г. осталось в тексте закона, и по сей день производители в США испытывают СИЗ по методике совершенно устаревшего стандарта полувековой давности<ref name="ANSI-1974" />, который даже не предусматривает возможность испытаний [[:w:Средства индивидуальной защиты органа слуха от шума с электронно-акустическими компонентами|СИЗОС с электронно-акустическими компонентами]]<ref name="AIHA-2018" />; а вкладыши в слуховые каналы участников испытаний устанавливает специалист, а не они сами. После изменений ослабления звуков разных частот определяется показатель ослабления шума в виде одного числа ''NRR'', который, как надеялись в 1970-х, позволит спрогнозировать ослабление шума у рабочих, применяющих эту модель СИЗОС. Но проведённые позже многочисленные исследования показали, что ослабление шума у работников на предприятиях очень нестабильное, и в среднем значительно ниже чем получаемое в лабораториях (пример<ref name="Lee-2022" />). Т.к. ''EPA'' прекратило работу по защите от шума, пересмотреть требования не удаётся, и в продажу поступают СИЗ с маркировкой, дезинформирующей потребителя (фактически - недобросовестная реклама). Многие склонны покупать СИЗ с наибольшим значением показателя ослабления шума, и в результате часть рабочих очень плохо защищена, а часть получает эффективные, но такие неудобные СИЗ, что не всегда их применяет. Некоторые крупные производители СИЗ оборудовали свои испытательные лаборатории, и сами проверяют свои изделия, получая при этом очень-очень хорошие показатели ослабления шума<ref name="Алиса-2003" />. Для снижения вероятности ошибок неправильно выбора СИЗ разработаны новые требования к испытаниям и маркировке, вместо показателя ослабления шума в виде одного числа результат испытаний сообщается потребителю в виде 2 графиков или таблицы, которые показывают возможное ослабление шума при более и при менее аккуратном надевании СИЗОС, и с учётом свойств шума (низкочастотные звуки ослабляются хуже высокочастотных). [[File:NRR new.jpg|thumb|350px|right|(1) старая маркировка СИЗОС (США), 1 число; (2) новая маркировка, графики, показывает, что низкочастотный шум (OX, правые концы графиков) ослабляется хуже высокочастотного, и что ослабление шума у разных людей разное.]] * '''<big> Канада </big>''' Требования к выбору и использованию СИЗ органа слуха установлены в стандарте<ref name="CSA-2014" />. По результатам испытаний определяется ослабление звуков разных частот, и по этим данным определяется, к какому из трёх классов СИЗ органа слуха (''A, B'' или ''C'') принадлежит данная модель. Замеры ослабления звуков проводят согласно требованиям стандарта США<ref name="ANSI-1974" />. Поскольку большинство СИЗ плохо защищает от низкочастотных звуков, введены ещё два "подкласса" СИЗОС (''AL ''и'' BL''). К ним относят СИЗ классов ''А'' (наибольшее ослабление шума) и ''В'' (умеренное ослабление шума), если они в лабораторных условиях при сертификационных испытаниях ослабляли звуки с частотой 125 Гц не меньше чем на 20 дБ. * '''<big> Европейский Союз </big>''' Разработана серия стандартов с требованиями к разным СИЗОС, в значительной степени на основе стандартов ИСО. Позднее её дополнили стандарты с требованиями к [[:w:Средства индивидуальной защиты органа слуха от шума с электронно-акустическими компонентами|средствам защиты с электронно-акустическими компонентами]]. Новые стандарты предполагают, что ослабление шума у работников будет таким же, как и у испытателей в лабораториях при сертификации, и получаемые с их помощью результаты могут завышать эффективность СИЗ по сравнению с реальной. * '''<big> Австралия и Новая Зеландия </big>''' Требования к всем СИЗ органа слуха содержатся в стандарте<ref name="ANZ-СИЗОС" />. Они, в целом, схожи с европейскими, но при определении ослабления шума обработка результатов (ослабление звуков разных частот) происходит по-другому. В Австралии все СИЗОС по ослаблению шума делят на 5 классов, для каждого установлен диапазон ослаблений шума (отчасти схоже с Канадой). Определяется, к какому классу принадлежит СИЗОС, и номер класса наносится на упаковку. * '''<big> Япония </big>''' На основе стандартов ИСО и ЕС разработаны требования к измерению ослабления шума<ref name="Япония-СИЗОС-тест" /> и оценке результата<ref name="Япония-СИЗОС-обраб" />. * '''<big> Индия </big>''' Разработаны стандарты с требованиями к СИЗ от шума<ref name="Индия-СИЗОС" /> и их испытаниям<ref name="Индия-СИЗОС-тест" />. * '''<big> Китай </big>''' В КНР разработаны требования к СИЗОС<ref name="CH-СИЗОС-вкладыш" />, их испытаниям<ref name="CH-СИЗОС-тест" />, обработке результатов испытаний<ref name="КНР-шум-прогноз" />. Часть стандартов гармонизирована со стандартами ИСО и ЕС. * '''<big> РФ </big>''' Как упоминалось выше, ведётся разработка государственных стандартов, гармонизированных с европейскими, с минимальными требованиями к противошумам и способам их испытаний. Качество документов разное. Например, в стандарте ISO 1994 г. описаны разные методы вычисления ослабления шума у работников на основании результатов лабораторных измерений<ref name="ИСО-1994" />. В документе не учтено отличие лабораторной эффективности от реальной, и разнообразие ослабления шума у работников; но читателя предупреждают, что ослабление шума у работников может отличаться от вычисленного "если работники наденут противошумы не так аккуратно, как испытатели ... и при разных индивидуальных анатомических особенностях". Это предупреждение в ГОСТе отсутствует, но есть фраза: "3. Настоящий стандарт представляет собой аутентичный текст международного стандарта ИСО 4869-2-94 ... и содержит дополнительные требования, отражающие потребности экономики страны"<ref name="ГОСТ-212" />. === Выбор противошумов === Для правильного выбора СИЗОС необходимо учесть множество разных факторов. Специалисты<ref name="AIHA-2018" /> отмечают, что многие обращают внимание на ослабление шума. Однако на практике в большинстве случаев доза воздействия шума обычно превышает предельно допустимую на небольшую величину, гораздо меньшую, чем ослабление шума, обеспечиваемое протившумами при своевременном применении. И проблема обычно в том, что работники не применяют их вовремя. Причины этого могут быть достаточно серьёзны: помехи общению, и недостаток акустической информации, мешающие выполнению трудовых обязанностей; дискомфорт и даже трудно переносимая боль (при длительном использовании вкладышей, сдавливающих ткани в слуховом канале); не соответствие выбранной модели индивидуальным особенностям работника, условиям труда, характеру выполняемой работы и свойствам шума, и по другим причинам. Нередко модель с меньшим показателем ослабления шума, но удобная и подходящая, и потому своевременно и правильно применяемая, защищает людей лучше, чем СИЗОС с очень высокими показателями защитных свойств - но неудобное и/или неподходящее. Для оценки риска необходима информация о воздействии шума на работников. Важно учесть, что при не постоянном воздействии шума можно допустить грубые ошибки при оценке воздействия. С учётом результатов исследования [[:w:Национальный институт охраны труда|NIOSH]]<ref name="Руководство 1976г" /> работодателям рекомендуется не вычислять воздействие непостоянного шума, а измерять его непосредственно, используя носимые рабочими дозиметры. А трудовая инспекция проводит замеры исключительно дозиметрами. Для примера: сравнение результатов измерений дозиметрами с результатами специальной оценки условий труда выявило превышение первых над вторыми во многих случаях<ref name="Мартин-2021" />, на величину, достигшую 19,7 дБ<ref name="Мартин-2023" />. Редкое использование шумовых дозиметров в РФ создаёт предпосылки для ошибочной и значительной недооценке опасности. Вредное действие шума на орган слуха может заметно усилиться, если работник одновременно подвергается воздействию [[:w:ru:Ототоксичность|некоторых вредных химических веществ]] (растворители, [[:w:монооксид углерода|монооксид углерода]], [[:w:стирол|стирол]] и другие) и некоторых лекарств<ref name="Campo-2009" /><ref name="AIHA-2018-7" />. Западных работодателей уже давно предупреждают о повышенной опасности в таких случаях, но это пока никак не отражено в требованиях и рекомендациях по выбору и использованию противошумов. * '''<big> США </big>''' Департамент условий и охраны труда разработал требования защите рабочих от шума, включая требования к выбору и использованию противошумов, государственная инспекция проверяет выполнение требований<ref name="инспектор-2022" />. При превышении предельно допустимого уровня шума работодатели обязаны периодически измерять его воздействие на работников, проводить у них первоначальные и затем ежегодные проверки слуха, дать возможность выбрать подходящие, удобные противошумы из нескольких предложенных (минимум 4 модели, из них минимум 2 - вкладыши), и обучить их правильному использованию<ref name="OSHA-noise" />. Ответственным работодателям, которые хотят надёжно защитить работников от шума, и не смогли добиться этого без СИЗ, специалисты предлагают использовать [[:w:ru:Производственный контроль эффективности СИЗОС|устройства для измерения ослабления шума]], и проверять работников индивидуально. Это помогает выбрать для каждого подходящую модель, проверять качество обучения правильному надеванию наушников и установки вкладышей, и контролировать эффективность защиты при повседневном применении СИЗ. Для обеспечения качества работы средств измерений разработан стандарт с требованиями к ним<ref name="ANSI-2018" />. Но, к сожалению, по данным<ref name="МОТ-шум" /><ref name="ILO-шум" /><ref name="Alice-2012" /> многие работодатели выполняют эти [[:w:Программа защиты от шума|программы защиты от шума]] формально и поверхностно, без какого-то эффекта: лишь выдаёт работникам СИЗОС, и периодически оплачивает проверки слуха. А часть работодателей с небольшим числом сотрудников и это не делает. * '''<big> Канада </big>''' Общенациональный стандарт<ref name="CSA-2014" /> определяет, как работодатель должен выбирать и организовать использование противошумов. В частности, рекомендуется измерять ослабление шума у каждого работника индивидуально. В канадской провинции [[:w:Альберта|Альберта]] законодатели изменили местные требования к защите от шума (2022): уменьшили предельно допустимый уровень, и потребовали, чтобы все работодатели, у которых рабочие должны использовать СИЗОС, проводили [[:w:ru:Производственный контроль эффективности СИЗОС|проверку для оценки фактического ослабления шума конкретной моделью противошумов у каждого работника]]<ref name="Альберта-2022" />. * '''<big> Европейский Союз </big>''' Ситуация в странах ЕС противоречивая. С одной стороны, в ЕС стабильно принимают стандарты, гармонизированные со стандартами ИСО по противошумам, их испытаниям, и прогнозированию ослабления шума у рабочих на основе результатов лабораторных замеров. На основе последних разработан чисто европейский стандарт с указаниями по выбору и организации использования СИЗОС работодателями. Все его три редакции, начиная с 1990-х, игнорируют отличие реальной и лабораторной эффективности. Чтобы хоть как-то снизить резкий контраст, в последней редакции упомянули, что "все описанные способы вычислений не позволяют определить ослабление шума у конкретного работника, из-за вариабельности". С другой стороны, Директива ЕС по защите работников от шума<ref name="Директива-шум" /> однозначно обязывает работодателей: * При эквивалентном уровне шума от 80 до 85 дБА выдавать работникам противошумы (и не требует их обязательного применения, т.к. считается, что риск утраты слуха небольшой); * При шума от 85 до 87 дБА работодатели обязаны выдавать СИЗОС, а работники обязаны непрерывно их использовать; * При шуме выше 87 дБА работа запрещена вообще, при любом ослаблении шума СИЗОС. Последнее требование, фактически, показывает низкую реальную эффективность противошумов, и очень хорошо согласуется с результатами проведённого через 11 лет исследования<ref name="Groenewold-2014" />. Поскольку с 1970-х известно, что ослабление шума у работника будет, скорее всего, совершенно не таким, как указывается на упаковке СИЗ (по результатам сертификации), в ЕС разработали стандарт, помогающий работодателям проводить индивидуальные измерения ослабления шума у каждого конкретного сочетания (работник — модель СИЗОС)<ref name="EN-2021" />. Но и этот метод не позволяет полноценно определять защитные свойства [[:w:ru:Средства индивидуальной защиты органа слуха от шума с электронно-акустическими компонентами|новых типов СИЗ органа слуха - с электронными компонентами]]<ref name="Капцов-2024-1" /><ref name="Капцов-2024-2" />. * '''<big> Австралия и Новая Зеландия </big>''' Для выбора СИЗОС в зависимости от уровня шума в Австралии используют деление на классы<ref name="ANZ-выборСИЗОС" />: {| class="wikitable collapsible collapsed" style="text-align:center" ! Класс !! Диапазон воздействий шума на рабочего, дБА |- | 1 || до 90 |- | 2 || 90 - 95 |- | 3 || 95 - 100 |- | 4 || 100 - 105 |- | 5 || 105 - 110 |- | colspan="2" | При дозе воздействия, превышающей эквивалентный среднесменный уровень шума 110 дБА, следует обратиться за советом к специалисту |} Использование классов служит средством, стимулирующим работодателей выбирать адекватные СИЗОС, а не просто покупать ту модель, у которой наибольший показатель ослабления шума (''Sound Level Conversion, SLC<sub>80</sub>''). Слишком часто бывает, что модель с очень высоким показателем не подходит работнику, и он не использует её вовремя; в то время как другая модель, с несколько меньшим показателем (вполне достаточным) обеспечит адекватную защиту из-за её правильного, своевременного использования. Выбирая какую-нибудь модель их группы моделей определённого класса, потребитель будет обращать больше внимания на удобность и другие важные свойства. * '''<big> Япония </big>''' Закон<ref name="Japan-закон" /> требует работодателей обеспечивать работников СИЗ при опасном воздействии<ref name="Japan-ПДУ" />. Разработаны рекомендации специалистов по защите от шума, в которых упомянуто применение СИЗОС, и обучение работников<ref name="Japan-рекоменд" />, но сколько-нибудь подробных рекомендаций нет. Работодатель обязан обеспечивать работников противошумами при превышении 85 дБА. * '''<big> Китай </big>''' Для оценки ослабления шума при использовании СИЗОС сначала приняли стандарт для прогнозирования ослабления шума у рабочих по результатам лабораторных измерений (''аналог ISO 4869-2:1994'')<ref name="КНР-шум-прогноз" />. Позже был принят стандарт с указаниями по выбору и организации использования СИЗ от шума<ref name="КНР-шум-выбор" />. По данным<ref name="КНР-шум-практика" /> ранее, при оценке ослабления шума у работников, старались учесть отличие средних ослаблений в лабораториях и на практике, уменьшая показатель ослабления шума (в виде одного числа) на 60%. А с 2021 года все СИЗОС и все условия труда по шуму делят на 2 вида: более эффективные / более опасные; и менее эффективные / менее опасные. При дозе воздействия шума до 95 дБА необходимо использовать СИЗОС с показателем ослабления шума от 17 до 34 дБ, а при дозе 95 дБА и более - с показателем больше 34 дБ. Фактически, все модели разделили на 2 класса, как в Канаде и Австралии. === Обучение и эффективность === Наиболее подробные требования к обучению работников даны в австралийском стандарте. <div class="toccolours mw-collapsible mw-collapsed"> Рекомендации по обучению (общего характера, которые следует приспособить к особенностям конкретного предприятия)<ref name="ANZ-выборСИЗОС" /> <div class="mw-collapsible-content"><small>Как учить. Результат гораздо лучше, если обучаемые не просто слушают, а участвуют в процессе. Предложите рабочим задавать вопросы, если они хоть что-то не поняли; делиться своим и чужим опытом; при наличии дополнительной информации и/или вопросов – сказать об этом. Чтобы обратить внимание на самые важные моменты, желательно дополнительно использовать визуальные средства (презентация и т.п.). Используйте при обучении: примеры по теме из своего и чужого опыта; инструкции Вашего предприятия (правила выполнения работ, правила эксплуатации оборудования); образцы противошумов – те модели, которые у Вас применяют. Вы обязаны дать информацию по темам: орган слуха и его работа (+ проверки слуха, как он ухудшается); шум и его свойства (постоянный / не постоянный, низко- и высокочастотный, импульсный); измерение шума (логарифмическая шкала, децибелы + примеры громкости, доза воздействия – эквивалентный уровень); в каких местах и при каких видах работ на Вашем предприятии есть опасное воздействие шума (можно использовать план/схему предприятия/цеха); что законы требуют от работодателя по защите рабочих от шума; что они требуют от начальников; и что обязаны делать работники. Расскажите о: предельно допустимых уровнях шума; важности сбережения здоровья (не пугая, расскажите о проблемах в повседневной жизни при разной степени ухудшения слуха); [[средства коллективной защиты|средствах коллективной защиты]] (кожухи для оборудования, перегородки, экраны, шумопоглощающие покрытия, изолированные кабины), какие СКЗ используются на Вашем предприятии; какие недостатки СКЗ мешают обойтись без противошумов; СИЗ органов слуха (виды, достоинства и недостатки; границы допустимого применения; какие используют на Вашем предприятии; причины выбора используемых у Вас моделей). Проинструктируйте, когда какие СИЗОС следует применять; как их проверять (покажите, как это делать), очищать (дайте практические советы), (ремонтировать) и хранить (покажите, где и как хранить), что делать при обнаружении дефектов или других проблем. Расскажите, почему важно, чтобы ослабление шума снизило его воздействие до безопасного уровня, но не слишком маленького (риск не услышать предупреждения об опасности, помехи при получении акустической информации, необходимой для работы, при общении). '''Научите <u>каждого работника индивидуально</u> правильному надеванию СИЗОС''': как надеть и отрегулировать наушники, как установить вкладыши. Обсудите проблемы при использовании противошумов: дискомфорт (боль), работа при высокой и низкой температуре воздуха, выделение пота, работа в загрязнённых местах (стимулируйте мыть руки перед установкой вкладышей), совместимость с респираторами, касками, очками и т.п.; о медосмотрах перед применением СИЗОС и выборе противошумов для рабочих с ухудшившимся слухом.</small></div></div> В руководстве по шуму американской ассоциации специалистов по гигиене труда даны очень разносторонние и подробные рекомендации и по выбору СИЗОС, и по обучению работников. Например, настоятельно рекомендуется использовать СИЗОС по нескольку часов в день тем сотрудникам, которые занимаются их выбором и закупкой, чтобы они лучше представляли себе достоинства и недостатки этих средств защиты<ref name="AIHA-2018" />. Указано, что хотя индивидуальное обучение каждого работника надеванию требует больше времени и ресурсов, но эффект от него настолько больше, что необходимо учить именно индивидуально (если это вообще возможно). При обучении рекомендуют проверять [[:w:ru:Производственный контроль эффективности СИЗОС|фактическое ослабление шума]], если нет такой возможности - использовать контролируемый источник шума (в малошумном месте), производственный шум для "суррогатной" проверки. [https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ассоциация СИЗ] опубликовала рекомендации, которые фактически стали единственным документом с советами специалистов по выбору СИЗ от шума на русском языке<ref name="АСИЗ-шум" />. Вопреки современному уровню науки авторы (из ''3М Russia'') предлагают определять степень уменьшения воздействия шума на рабочих на основании результатов измерений в лабораторных условиях, т.е. без учёта индивидуальных особенностей работников, анатомических (диаметр слуховых каналов у людей от 3 до 14 мм), и в отношении совершенства навыков правильного надевания СИЗОС. Для сравнения, та же компания (''3М Russia'') предлагает западным потребителям оборудование для индивидуального измерения фактического ослабления шума у каждого работника, т.к. без этого у многих из них оно будет близким к нулю. Определить влияние выдачи противошумов на сбережение здоровья работников непросто. Для получения полноценного и качественного результата следует сравнить состояние здоровья у двух схожих групп работников, при схожих условиях труда, так, чтобы одна группа использовала средства защиты, а другая не применяла. Но уже много десятилетий закон обязывает работодателей обеспечивать всех работников СИЗ при опасном воздействии вредных факторов. И найти предприятие, где не только массово нарушают закон, но и согласятся участвовать в исследовании, результат которого будет опубликован - вряд ли возможно. Специалисты [[:w:ru:Национальный институт охраны труда|Национального института охраны труда]] сумели решить проблему: используя уникальную базу данных с результатами проверки слуха работников, они выбрали аудиограммы для более чем 19 тыс. работников разных отраслей, за период 5 лет, и достаточно высокого качества. При отборе они выбирали лишь тех работников, которые при медосмотре проходили опрос, и отвечали на вопрос "Используете ли Вы противошумы?". Выбранных работников разделили на 3 подгруппы: всегда отвечавших, что используют, всегда отвечавших, что не используют, и остальных. Сравнение частоты значительного ухудшения слуха в первых двух подгруппах показало, что у применявших СИЗОС частота утраты слуха была немножко ниже. Затем углублённый статистический анализ показал, что отличие - [[:w:ru:Статистическая значимость|статистически незначительно]] (т.е. может быть случайным)<ref name="Groenewold-2014" />. По данным обзорной работы<ref name="AIHA-2018" /> не опубликовано ни одного исследования, которое бы показало, что выдача работникам СИЗОС позволяет сколько-нибудь заметно помочь сохранить здоровье. Так как при обеспечении работников противошумами в РФ не требуется давать им возможность выбрать наиболее удобный из нескольких разных (как в США и ряде других стран), можно ожидать, что эффект от их выдачи будет (в среднем) не лучше, чем полученный в исследовании<ref name="Groenewold-2014" />. Часть специалистов по СИЗОС считает что эффект от их использования этих СИЗ можно повысить при проверках [[:w:ru:Производственный контроль эффективности СИЗОС|фактического ослабления шума у выбираемых моделей]], и периодическом повторении проверок<ref name="AIHA-2018" />. В СССР на крупных предприятиях иногда измеряли фактическое ослабление шума у вкладышей (при наличии в медико-санитарных частях предприятий [[:w:ru:Аудиометр|аудиометров]] и специалистов)<ref name="Барский-1971" />. Но сейчас большая часть медико-санитарных частей (МСЧ) ликвидирована, а специальное оборудование для проверок не разрабатывается, (дорогое) импортное купить стало сложно. == Примечания == {{примечания|refs= <ref name="Алиса-2003">{{Книга|ссылка=https://nonoise.org/epa/hearingpro.pdf|автор=Alice H. Suter et al.|заглавие=Workshop on Hearing Protector Devices, March 27-28, 2003|год=2003|язык=en|место=Washington, DC|издательство=United States Environmental Protection Agency|allpages=212|access-date=2024-08-13|archive-date=2024-07-16|archive-url=https://web.archive.org/web/20240716183701/https://www.nonoise.org/epa/hearingpro.pdf|url-status=live}} перевод {{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1723229272&archive=&start_from=&ucat=&|автор=Алиса Сатер (редактор)|заглавие=Материалы конференции по индивидуальной защите от шума|год=2003|место=Вашингтон|издательство=Агентство по охране окружающей среды (EPA)}} [https://ru.wikipedia.org/wiki/Файл:Алиса-2003++.pdf PDF]</ref> <ref name="NIOSH-1979">{{Книга|ссылка=https://ntrl.ntis.gov/NTRL/dashboard/searchResults/titleDetail/PB299319.xhtml|автор=Edwards R.G., Hauser W.P., Moiseev N.A., Broderson A.B., Green W.W., Lempert B.L.|заглавие=A field investigation of noise reduction afforded by insert-type hearing protectors|год=1979|язык=en|издание=NIOSH Report No. 79-115|место=Cincinnati, Ohio|издательство=National Institute for Occupational Safety and Health|страниц=54|серия=Technical Report}} '''Доступен перевод документа [https://ru.wikipedia.org/wiki/Файл:NIOSH_Шум_перевод_1979%2B%2B.pdf PDF] [[:w:s:ru:Измерения эффективности берушей у рабочих|Wiki]] [https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1670696418&archive=&start_from=&ucat=& копия]'''</ref> <ref name="NIOSH-2015">{{Книга |ссылка=https://www.cdc.gov/niosh/pubs/surveyreports/ |автор=William J. Murphy, Christa L. Themann, M.A., Taichi K. Murata (NIOSH in US HHS) and Roey Holliday, Rose Capers-Webb (US Department of the Interior) |заглавие=Field-Testing NIOSH HPD Well-Fit: Off-Shore Oil Rig Inspectors in Texas & Louisiana |ответственный=United States Centers for Disease Control and Prevention |год=2015 |язык=en |место=Louisiana & Texas |издательство=National Institute for Occupational Safety and Health |allpages=38 |серия=In-Depth Survey Report - EPHB Report No. 360-11a |doi=10.1080/14992027.2016.1204470}} [https://www.cdc.gov/niosh/surveyreports/pdfs/360-11a.pdf PDF] </ref> <ref name="Lee-2022">{{Статья|ссылка=https://www.researchsquare.com/article/rs-807643/v1|автор=Kah Heng Lee, Geza Benke, Dean Mckenzie|заглавие=The efficacy of earplugs at a major hazard facility|год=2022|язык=en|издание=Physical and Engineering Sciences in Medicine|издательство=Springler|выпуск=1|pages=107-114|volume=45||doi=10.1007/s13246-021-01087-y|archivedate=2021-09-01|archiveurl=https://web.archive.org/web/20210901112639/https://www.researchsquare.com/article/rs-807643/v1}} ISSN 2662-4729. Доступен [https://commons.wikimedia.org/wiki/File:Австралия_Шум.pdf перевод]</ref> <ref name="Капцов-2023">{{Статья|ссылка=https://www.elibrary.ru/item.asp?edn=iqmpkz&ysclid=m2w84hrfq9457558565|автор=Капцов В.А., Панкова В.Б., Чиркин А.В|заглавие=Современные подходы к выбору и применению противошумов|год=2023|ответственный=Ломовцева С.Д., Храпко Н.Н., Васильева В.К., Иванов Н.И. (ред.)|автор издания=Балтийский государственный технический университет «ВОЕНМЕХ» им. Д.Ф. Устинова|место=Санкт-Петербург|издание=Защита от повышенного шума и вибрации|издательство=Институт акустических конструкций|тип=Сборник трудов конференции IX Всероссийской научно-практической конференции с международным участием|месяц=4|число=26–28|страницы=113-120}} [https://upload.wikimedia.org/wikipedia/commons/8/88/Шум_Капцов_СПб_2023+ru.pdf PDF]</ref> <ref name="Alice-2012">{{Статья|ссылка=http://www.sandv.com/downloads/1201sute.pdf|автор=Alice H. Suter|заглавие=Engineering Controls for Occupational Noise Exposure - The Best Way to Save Hearing|год=2012|язык=en|место=Henderson, Nevada|издание=Sound & Vibration|издательство=Tech Science Press|выпуск=1|pages=24-31|volume=48|archivedate=2022-01-26|archiveurl=https://web.archive.org/web/20220126123850/http://www.sandv.com/downloads/1201sute.pdf}} ISSN 1541-0161. Есть перевод [https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1690379818&archive=&start_from=&ucat=& онлайн] , [https://files.library.by/dl/files/-Сатер-2012.zip ZIP]</ref> <ref name="ISO-5">{{Книга|ссылка= https://www.iso.org/ru/standard/32305.html|автор=TC ISO/TC 43/SC 1 Noise|заглавие=ISO/TS 4869-5:2006. Acoustics — Hearing protectors. Part 5: Method for estimation of noise reduction using fitting by '''inexperienced test subjects'''|год=2006|язык=en|место=Geneva, Switzerland|издательство=International Organization for Standardization |allpages=28}}</ref> <ref name="ANSI-1974">{{Книга|автор=Accredited Standards Committee S12, Noise|заглавие=ANSI S3.19-1974. Method for the Measurement of Real-Ear Protection of Hearing Protectors and Physical Attenuation of Earmuffs|ответственный=Acoustical Society of America|год=1974|язык=en|место=Melville, New York|издательство=American National Standards Institute|allpages=19}} [https://www.iitr.ac.in/safety/PPE/6229_METHOD_FOR_MEASERMENT_OF_REAL-EAR_PROTECTION_OF_HEARING_PROTECTORS__PHYSICAL_ATTENUATION_OF.pdf аналог]</ref> <ref name="AIHA-2018">{{Книга|ссылка=https://www.aiha.org/education/marketplace/noise-manual-6th-edition|автор=Elliott H. Berger & Jérémie Voix|часть=Chapter 11. Hearing Protection Devices|заглавие=The Noise Manual|издание=6th ed|ответственный=D.K. Meinke, E.H. Berger, R. Neitzel, D.P. Driscoll & K. Bright eds|год=2020|язык=en|место=Falls Church|издательство=American Industrial Hygiene Association|ссылка часть=https://online-ams.aiha.org/amsssa/ecssashop.show_product_detail?p_mode=detail&p_product_serno=2719|страницы=257|страниц=621}}</ref> <ref name="ИСО-1994">{{Книга|автор=ISO/TC 43/SC 1|заглавие=ISO 4869-2:1994. Acoustics - Hearing protectors - Part 2: Estimation of effective A-weighted sound pressure levels when hearing protectors are worn|год=1994|язык=en|издательство=International Organization for Standardization|allpages=12|серия=ICS 13.340.20 Head protective equipment}}</ref> <ref name="ГОСТ-212">{{Книга|ссылка=https://meganorm.ru/Index2/1/4294820/4294820410.htm |автор=Научный центр социально-производственных проблем охраны труда|заглавие=ГОСТ Р 12.4.212-99 (ИСО 4869-2-94). ССБТ. СИЗОС. Оценка результирующего значения А-корректированных уровней звукового давления при использовании средств индивидуальной защиты от шума|ответственный=ТК 320 "СИЗ"|год=2000|часть=Предисловие|место=Москва|издательство=ИПК Издательство стандартов,|страницы=II|страниц=14|серия=ICS 13.340.20 Head protective equipment|тираж=301}} [https://meganorm.ru/Data2/1/4294820/4294820410.pdf PDF]</ref> <ref name="Рязань-2023">{{Книга|ссылка=https://sgm.rzgmu.ru/binder|автор=Капцов В.А., Панкова В.Б., Чиркин А.В.|заглавие=Социально-гигиенический мониторинг здоровья населения|ответственный=В.А. Кирюшин (ред.)|год=2023|часть=Эффект ослабления антифонами воздействия шума на работника|место=Рязань|издательство=ФГБОУ ВО Рязанский государственный медицинский университет им. акад. И.П. Павлова Минздрава России|том=Выпуск 27|страницы=74-81|страниц=253|серия=Материалы к 27-й Международной научно - практической конференции|isbn=978-5-8423-0245-1}}</ref> <ref name="Руководство 1976г">{{книга|автор=Nelson Leidel, Kenneth Bush & Jeremiah Lich|заглавие=NIOSH Occupational Exposure Sampling Strategy Manual|ссылка=https://www.cdc.gov/niosh/docs/77-173/|место=Cincinnati, Ohio|издательство=National Institute for Occupational Safety and Health|год=1977|серия=DHHS (NIOSH) Publication Number 77-173|allpages=150}} Есть перевод: [[:Файл:Руководство NIOSH по измерению загрязнённости воздуха 25.04.2014.pdf|PDF]] [https://ru.wikibooks.org/wiki/Измерение_загрязнённости_воздуха Wiki] </ref> <ref name="Мартин-2021">{{Книга|ссылка=https://irioh.ru/publish-books-2021-16ohrnc-materials/|автор=Мартин С.В., Кудряшов И.Н., Иващенко М.А.|заглавие=Материалы 16-го Российского Национального Конгресса с международным учас­тием «ПРОФЕССИЯ и ЗДОРОВЬЕ», 21‐24 сентября 2021 г., Владивосток|ответственный=науч. ред. [[:w:Бухтияров, Игорь Валентинович|Бухтияров И.В.]] и др.|год=2021|часть=Оценка акустического воздействия на работников промышленных предприятий|ссылка часть=https://doi.org/10.31089/978-5-6042929-2-1-2021-1-345-349|место=Москва|издательство=НКО Ассоциация врачей и специалистов медицины труда|страницы=345-349|страниц=624|isbn=978-5-6042929-2-1|doi=10.31089/978-5-6042929-2-1|access-date=2024-06-21|archive-date=2023-10-28|archive-url=https://web.archive.org/web/20231028115915/https://irioh.ru/publish-books-2021-16ohrnc-materials/|url-status=live}}</ref> <ref name="Мартин-2023">{{Книга|ссылка=https://irioh.ru/publish-books-2023-17ohrnc-materials/|автор=Мартин С.В., Федорук А.А., Иващенко М.А|заглавие=Материалы 17-го Российского Национального Конгресса с международным участием «Профессия и здоровье», 26‑29 сентября 2023 года, г. Нижний Новгород|ответственный=[[:w:Бухтияров, Игорь Валентинович|Бухтияров И.В.]] и др|год=2023|часть=Уровни шума на рабочих местах работников промышленных предприятий|ссылка часть=https://doi.org/10.31089/978-5-6042929-1-4-2023-1-301-306|место=Москва|издательство=ФГБНУ Научно-исследовательский институт медицины труда имени академика [[:w:Измеров, Николай Федотович|Н.Ф. Измерова]]|страницы=301-306|страниц=548|isbn=978-5-6042929-1-4|archive-date=2023-10-15|archive-url=https://web.archive.org/web/20231015001912/https://irioh.ru/publish-books-2023-17ohrnc-materials/}}</ref> <ref name="Campo-2009">{{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1702135988&archive=&start_from=&ucat=&|автор=Пьер Кампо, Кэти Маген, Стефан Габриэль, Анжела Мёллер, Эберхард Нис, Мария Долорес Соле Гомес и Эско Топпила|заглавие=Ухудшение слуха при воздействии промышленного шума и химикатов. Обзор|ответственный=Эусебио Риал Гонсалес и Джоанна Коск-Биенко (ред)|год=2009|оригинал=Combined exposure to Noise and Ototoxic Substance|язык=en|место=Люксембург|издательство=Европейское агентство по безопасности и гигиене труда|страниц=63|isbn=978-92-9191-276-612|doi=10.2802/16028|access-date=2023-12-09|archive-date=2023-12-09|archive-url=https://web.archive.org/web/20231209181723/https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1702135988&archive=&start_from=&ucat=&|url-status=live}} <small>{{Книга|ссылка=https://osha.europa.eu/en/publications/combined-exposure-noise-and-ototoxic-substances|автор=P. Campo, K. Maguin, S. Gabriel, A. Möller, E. Nies, M. Dolores, S. Gómez, E. Toppila|заглавие=Combined Exposure to Noise and Ototoxic Substances|ответственный=E.R. González, J. Kosk-Bienko|год=2009|язык=en|место=Luxembourg|издательство=European Agency for Safety and Health|allpages=62|серия=Literature reviews|isbn=978-92-9191-276-6|doi=10.2802/16028|archive-date=2023-12-03|access-date=2023-05-11|archive-url=https://web.archive.org/web/20231203151419/https://osha.europa.eu/en/publications/combined-exposure-noise-and-ototoxic-substances|url-status=live}}</small></ref> <ref name="AIHA-2018-7">{{Книга|ссылка=https://www.aiha.org/education/marketplace/noise-manual-6th-edition|автор=Thais C. Morata, Colleen G. Le Prell, Chris Spankovich, and Adrian Fuente|часть=Chapter 7. Ototoxicity and Otoprotection: Complex Interactions Between Noise and Chemicals |заглавие=The Noise Manual|издание=6th ed|ответственный=D.K. Meinke, E.H. Berger, R. Neitzel, D.P. Driscoll & K. Bright eds|год=2020|язык=en|место=Falls Church|издательство=American Industrial Hygiene Association|ссылка часть=https://online-ams.aiha.org/amsssa/ecssashop.show_product_detail?p_mode=detail&p_product_serno=2715|страницы=123-151|страниц=621}}</ref> <ref name="OSHA-noise">Пункт [[:s:ru:Стандарт по охране труда при работе в условиях шума (США)#выбор|1910.95(i)(3)]] в: [[:w:ru:Управление по охране труда (OSHA)|Occupational Safety and Health Administration]] Standard 29 CFR 1910.95 [https://www.law.cornell.edu/cfr/text/29/1910.95 Occupational noise exposure]. Есть [[:s:ru:Стандарт по охране труда при работе в условиях шума (США)| перевод]]</ref> <ref name="CSA-2014">{{Книга|ссылка=https://www.csagroup.org/store/product/2701515/|автор=A. Behar et al|заглавие=Z94.2-14. Hearing protection devices — Performance, selection, care and use|год=2014|часть=|язык=en|издание=7th ed|место=Toronto, Ontario, Canada|издательство=Canadian Standards Association (CSA Group)|pages=|allpages=54|isbn=978-1-77139-417-8|серия=Protective equipment - Head protective equipment|access-date=2023-11-07|}}</ref> <ref name="Альберта-2022">''Government of Alberta.'' [https://ohs-pubstore.labour.alberta.ca/lh003 Change highlights: Noise exposure – Part 16 in the OHS Code.] <small>OHS information for work site parties and service providers (англ.).</small> ''ohs-pubstore.labour.alberta.ca'' (декабрь 2022). — «... Добавлено новое требование, согласно которому работодатели должны обеспечить проверку соответствия противошумов работникам и их умения правильно применять СИЗОС. ... Изменение введено для снижения риска развития нейросенсорной тугоухости, вызванной шумом. Эффективность противошумов сильно снижается, если они неправильно выбраны, неправильно вставлены или неправильно надеты. ...». Дата обращения: 11 февраля 2023. [https://miningwiki.ru/wiki/Файл:СИЗОС_Альберта_перевод-2.jpg перевод]</ref> <ref name="ANZ-СИЗОС">{{Книга|ссылка=https://www.standards.govt.nz/shop/asnzs-12702002|автор=Committee AV-003|заглавие=AS/NZS 1270:2002. Hearing protectors|год=2002|язык=en|издание=4th ed|место=Sydney, New South Wales|издательство=Standards Australia|allpages=30|серия=Acoustics|isbn=0-7337-4261-0}}</ref> <ref name="Япония-СИЗОС-тест">{{Книга|ссылка=https://webdesk.jsa.or.jp/preview/pre_jis_t_08161_001_000_2020_e_ed10_ch.pdf|автор=Technical Committee on Safety|заглавие=JSA JIS T 8161-1-2020 Acoustics - Hearing protectors - Part 1: Subjective method for the measurement of sound attenuation|ответственный=Japanese Industrial Standards Committee|год=2020|оригинал=JSA JIS T 8161-1-2020 聴覚保護具(防音保護具)―第1部:遮音値の主観的測定方法|язык=en|место=Tokyo|издательство=Japanese Standards Association|allpages=22|серия=ISO 4869-1:2018}}</ref> <ref name="Япония-СИЗОС-обраб">{{Книга|ссылка=https://webdesk.jsa.or.jp/preview/pre_jis_t_08161_002_000_2020_e_ed10_ch.pdf|автор=Technical Committee on Safety|заглавие=JSA JSA JIS T 8161-2-2020 Acoustics - Hearing protectors - Part 2: Estimation of effective A-weighted sound pressure levels when hearing protectors are worn|ответственный=Japanese Industrial Standards Committee|год=2020|оригинал=JSA JIS T 8161-2-2020 [https://kikakurui.com/t8/T8161-2-2020-01.html 聴覚保護具(防音保護具)―第2部:着用時の実効A特性重み付け音圧レベルの推定]|язык=en|место=Tokyo|издательство=Japanese Standards Association|allpages=20|серия=ISO 4869-2:2018}}</ref> <ref name="Индия-СИЗОС">{{Книга|автор=Acoustics Sectional Committee, LTDC 5|заглавие=Indian Standard IS 9167-1979. Specification for ear protectors |ссылка= https://www.iitr.ac.in/safety/PPE/9167_SPECIFICATION_FOR_EAR_PROTECTORS.pdf |год= 2004|язык=en|место=New Deli|издательство= Bureau of Indian Standards|allpages=18|UDC=614.892:616.28-072.7}}</ref> <ref name="Индия-СИЗОС-тест">{{Книга|автор=AcousticalSectional Committee, LTDC 5|заглавие=Indian Standard IS 6229:1980. Method for measurement of real-ear protection of hearing protectors and physical attenuation of earmmuffs|ссылка= https://law.resource.org/pub/in/bis/S04/is.6229.1980.pdf |год=2001|язык=en|место=New Deli|издательство= Indian Standards Institution|allpages=22|серия=UDC 614:892 : 616:28-072.7}}</ref> <ref name="CH-СИЗОС-вкладыш">{{Книга|ссылка=https://www.gbstandards.org/China_standard_english.asp?code=GB/T%207584.1-2004&id=7885|автор=The Standardization Administration of the People's Republic of China|заглавие= GB/T 31422-2015. Personal protective equipment - General technical requirements for hearing protectors|год=2015|оригинал=GB/T 31422-2015 个体防护装备 护听器的通用技术条件 |язык=en|издательство=China National Standards|allpages=40|серия=13.340.99}} [http://down.foodmate.net/standard/yulan.php?itemid=55144 ch]</ref> <ref name="CH-СИЗОС-тест">{{Книга|ссылка=https://www.gbstandards.org/China_standard_english.asp?code=GB/T%207584.1-2004&id=7885|автор=The Standardization Administration of the People's Republic of China|заглавие=GB/T 7584.1-2004. Acoustics - Hearing protectors - Part 1: Subjective method for the measurement of sound attenuation|год=2004|оригинал=GB/T 7584.1-2004 声学 护听器 第1部分:声衰减测量的主观方法 |язык=en|издательство=China National Standards|allpages=12|серия=ISO 4869-1:1990}}</ref> <!-- Комментарий --> противошумы выбор <ref name="Кириллов-2010">{{книга|автор=Кириллов В.Ф.|часть=Глава 25. Средства индивидуальной защиты |заглавие=Гигиена труда|издание=|ответственный=[[w:ru:Измеров, Николай Федотович|Измеров Н.Ф.]], Кириллов В.Ф. ред. | место=Москва|издательство= Издательская группа «ГЭОТАР-Медиа» |год=2008 |страницы=303-304|страниц=480|isbn=978-5-9704-3691-2|тираж=1000|серия=Учебник}} 2 изд., перераб. и доп. [https://e-library.sammu.uz/uploads/books/Rus%20tilidagi%20adabiyotlar/Гигиена/%2B%2BГигиена%20труда.pdf 2016]</ref> <ref name="инспектор-2022">Инструкция для инспектора по охране труда. [[:w:s:ru:Шум. Инструкция для инспектора по охране труда 2022 г.|Часть 5. Шум. ]] ''(США)'' US OSHA. [https://www.osha.gov/otm/section-3-health-hazards/chapter-5#noisecontroloverview NOISE]. OSHA Technical Manual (OTM) Section III: Chapter 5 ''(англ.).'' www.osha.gov. Occupational Safety and Health Administration (6 июля 2022)</ref> <ref name="ANSI-2018">{{Книга|ссылка=https://webstore.ansi.org/standards/asa/ansiasas12712018|автор=E.H. Berger et al (eds)|заглавие=ANSI/ASA S12.71-2018. Performance Criteria for Systems that Estimate the Attenuation of Passive Hearing Protectors for Individual Users|год=2018|язык=en|место=Melville, New York|издательство=American National Standard Institute|allpages=54|archive-date=2023-03-15|archive-url=https://web.archive.org/web/20230315103402/https://webstore.ansi.org/standards/asa/ansiasas12712018}} Цитата: Стандарт относится к системам для измерения ослабления шума, воздействующего на индивидуального работника, на предприятиях. В документе приводится классификация этих измерительных систем, и установлены критерии для оценки их эффективности. Также описано, как оценивать и вычислять погрешность измерения при использовании этих систем, и вычислять показатель ослабления шума у конкретного работника.</ref> <ref name="EN-2021">{{Книга|автор=British Standards Institution|заглавие=BS EN 17479:2021. Hearing protectors. Guidance on selection of individual fit testing methods|год=2021|издательство=BSI|allpages=46|isbn=978 0 539 04746 2}}</ref> <ref name="Директива-шум">{{Книга|автор=Publications Office of the European Union|заглавие=Directive 2003/10/EC of the European Parliament and of the Council of 6 February 2003 on the minimum health and safety requirements regarding the exposure of workers to the risks arising from physical agents (noise)|ссылка=https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02003L0010-20190726|ответственный= P. Cox <small>''(European Parliament, President)''</small>, G. Efthymiou <small>''(Council, President)''</small>|год=2003 (2021)|часть=Article 6. Personal protection|язык=en|издание=Official Journal of the European Union, L|место=Brussels|pages=L 42/38 - L 42/44|серия=Document 02003L0010-20190726. Seventeenth individual Directive within the meaning of Article 16(1) of Directive 89/391/EEC}} [https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:02003L0010-20190726 html] [https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:02003L0010-20190726 PDF]</ref> <ref name="Japan-закон">{{Книга|ссылка=https://www.japaneselawtranslation.go.jp/en/laws/view/3440|автор=Ministry of Health, Labour and Welfare|заглавие=Industrial Safety and Health Law|год=2006-08-02|часть=Article 22 in: Chapter IV. Measures for Preventing the Dangers or Health Impairment of Workers|язык=en|серия=[Law No. 57 of 1972] (Ordinance No. 257 of August 2, 2006)}}</ref> <ref name="Japan-ПДУ">{{Книга|ссылка=https://www.mhlw.go.jp/content/001089239.pdf|автор=厚生労働省労働基準局長 (Occupational health and safety standards department - Ministry of Health, Labour and Welfare)|заглавие=Пересмотр требований к защите от производственного шума|год=2020-04-20|часть=表 等価騒音レベル(A特性音圧レベル)による許容基準 等価騒音レベ ル(dB) (Таблица. Предельно допустимое воздействие шума, дБА, для разных продолжительностей воздействия). В документе: |оригинал=騒音障害防止のためのガイドラインの改訂について|язык=jp|место=Japan|pages=4|allpages=27}}</ref> <ref name="Japan-рекоменд">''The Japan International Center for Occupational Safety and Health (JICOSH)''. [https://www.jisha.or.jp/international/jicosh/english/guideline/Guide-1.html Guidelines for the Prevention of Noise-Induced Impairments (1992)] <small>(англ.).</small> www.jisha.or.jp. Japan: JICOSH (1999). Дата обращения: 19 октября 2024.</ref> <ref name="ANZ-выборСИЗОС">{{Книга|ссылка=https://www.standards.govt.nz/shop/ASNZS-1269-32005|автор=Joint Technical Committee AV-003, Acoustics, Human Effects|заглавие=AS/NZS 1269.3:2005. Occupational noise management. Part 3: Hearing protector program|год=2005 (2016-06-10)|язык=en|издание=3th ed|место=Sydney, New South Wales|издательство=Standards Australia|allpages=36|серия=Occupational noise management|isbn=0-7337-6550-5}}</ref> <ref name="Капцов-2024-1">{{Книга|ссылка=https://www.elibrary.ru/item.asp?id=75486593&pff=1|автор=Капцов В.А., Панкова В.Б., Чиркин А.В.|заглавие=Социально-гигиенический мониторинг здоровья населения|часть=Сертификация и выбор противошумов с активным подавлением шума |ответственный=Кирюшин В.А. отв. ред.|год=2024|место=Рязань|издательство=Рязанский государственный медицинский университет им. акад. И.П. Павлова|страницы=71-76|страниц=219|серия=Материалы к Двадцать восьмой Международной научно-практической конференции, посвященной 175-летию со дня рождения академика И.П. Павлова, 10–11 октября 2024 года|isbn=978-5-8423-0322-9}} [https://rzgmu.ru/images/upload/users/sc/SGM_sbornik_ITOG_merged.pdf Сборник PDF]</ref> <ref name="Капцов-2024-2">{{Книга|ссылка=https://www.elibrary.ru/item.asp?id=75486627&pff=1|автор=Капцов В.А., Панкова В.Б., Чиркин А.В.|заглавие=Социально-гигиенический мониторинг здоровья населения|часть= Сертификация и выбор противошумов с электронно-акустическими компонентами|ответственный=Кирюшин В.А. отв. ред.|год=2024|место=Рязань|издательство=Рязанский государственный медицинский университет им. акад. И.П. Павлова|страницы=76-81|страниц=219|серия=Материалы к Двадцать восьмой Международной научно-практической конференции, посвященной 175-летию со дня рождения академика И.П. Павлова, 10–11 октября 2024 года|isbn=978-5-8423-0322-9}} [https://rzgmu.ru/images/upload/users/sc/SGM_sbornik_ITOG_merged.pdf Сборник PDF]</ref> <ref name="КНР-шум-прогноз">{{Книга|ссылка=https://www.gbstandards.org/GB_standard_english2.asp?code=GB/T%207584.2-1999|автор=The Standardization Administration of the People's Republic of China|заглавие=GB/T 7584.2-1999. Acoustics - Hearing protectors - Part 2: Estimation of effective A-weighted sound pressure levels when hearing protectors are worn|год=1999|оригинал=GB/T 7584.2-1999 声学 护听器 第2部分:戴护听器时有效的A计权声压级估算|язык=en|издательство=China National Standards|allpages=16|серия=ISO 4869-2:1994}}</ref> <ref name="КНР-шум-выбор">{{Книга|ссылка=https://www.gbstandards.org/GB_standard_english2.asp?code=GB/T%2023466-2009|заглавие=GB/T 23466-2009. Guideline for selection of hearing protectors|год=2009|оригинал=GB/T 23466-2009. 护听器的选择指南|язык=en|издательство=China National Standards|allpages=16}}</ref> <ref name="КНР-шум-практика">{{Статья|ссылка=https://pubs.aip.org/asa/jasa/article/152/2/1074/2838503/Personal-attenuation-ratings-versus-derated-noise|автор=William J. Murphy, Wei Gong, Stephanie J. Karch, Jeremy Federman, Theresa Y. Schulz|заглавие=Personal attenuation ratings versus derated noise reduction ratings for hearing protection devices|год=2022|язык=en|автор издания=Acoustical Society of America|место=Melville, New York|издание=The Journal of the Acoustical Society of America|издательство=American Institute of Physics|месяц=8|число=22|выпуск=2|pages=1074–1089|volume=152|doi=10.1121/10.0013418}} ISSN 0001-4966, {{PMID|36050158}}.</ref> <ref name="Groenewold-2014">{{Статья|ссылка=https://stacks.cdc.gov/view/cdc/36768|автор=Groenewold M.R., Masterson E.A., Themann C.L., Davis R.R|заглавие=Do hearing protectors protect hearing?|год=2014|язык=en|издание=American Journal of Industrial Medicine|издательство=Wiley Periodicals|месяц=4|число= 3|выпуск=9|pages=1001-1010|volume=57 |doi=10.1002/ajim.22323}} ISSN 1097-0274, {{PMID|24700499}}. Есть [https://ru.wikipedia.org/wiki/Файл:СИЗ_органа_слуха,_и_профилактика_ухудшения_слуха.pdf '''перевод 1'''] [https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1668507313&archive=&start_from=&ucat=&#i2701 '''перевод 2''']</ref> <ref name="Барский-1971">{{Статья|ссылка=https://cyberleninka.ru/article/n/opyt-organizatsii-raboty-po-borbe-s-shumom-na-himicheskom-predpriyatii|автор=Барский И.П., Мазаев А.А., Маламут И.Е., Гутникова Е.Г., Килин В.Ф|заглавие=Опыт организации работы по борьбе с шумом на химическом предприятии|год=1971|язык=ru|издание=Гигиена и санитария|месяц=12|номер=12|страницы=89-92|archivedate=2022-12-14|archiveurl=https://web.archive.org/web/20221214175410/https://cyberleninka.ru/article/n/opyt-organizatsii-raboty-po-borbe-s-shumom-na-himicheskom-predpriyatii}} ISSN 0016-9900.</ref> <ref name="МОТ-шум">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =Ю.Г. Сорокин <small>(''руководитель Департамента условий и охраны труда, Минтруд РФ'')</small>; Жан-Виктор Груа <small>(''Директор Московского бюро МОТ'')</small>|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[http://base.safework.ru/iloenc?d&nd=857100159&prevDoc=857100159&spack=110LogLength%3D0%26LogNumDoc%3D857000269%26listid%3D010000000100%26listpos%3D3%26lsz%3D5%26nd%3D857000269%26nh%3D1%26 Программы защиты слуха]. В: Том 2; Раздел [http://base.safework.ru/iloenc?d&nd=857400005&prevDoc=857000002 IV. Вредные факторы общего характера], Глава [http://base.safework.ru/iloenc?d&nd=857000269&prevDoc=857000002 47. Шум] |автор=Ларри Х. Ройстер, Джулия Досвелл Ройстер |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|isbn=|серия= Охрана труда}} </ref> <ref name="ILO-шум">''Larry H. Royster & Julia D. Royster''. [https://iloencyclopaedia.org/part-vi-16255/noise/item/754-hearing-conservation-programmes Hearing Conservation Programmes]. In: Vol. 2; [https://iloencyclopaedia.org/part-vi-16255/noise Chapter 47. Noise] // [https://iloencyclopaedia.org/ Encyclopedia of Occupational Health and Safety] / Michel Hansenne ed. — 4th ed. — Geneva: International Labour Office, 1998.</ref> <ref name="Денисов-2013">{{Статья|ссылка=https://cyberleninka.ru/article/n/problema-realnoy-effektivnosti-individualnoy-zaschity-i-privnosimyy-risk-dlya-zdorovya-rabotnikov-obzor-literatury/viewer|автор=Денисов Э.И., Морозова Т.В., Аденинская Е.Е., Курьеров Н.Н.|заглавие=Проблема реальной эффективности индивидуальной защиты и привносимый риск для здоровья работников (обзор литературы)|год=2013|автор издания=НИИ медицины труда РАН|издание=Медицина труда и промышленная экология|месяц=8|номер=8|страницы=18-25}} ISSN 1026-9428, {{PMID|24006620}}.</ref> <ref name="АСИЗ-шум">{{Книга|ссылка=https://asiz.ru/wp-content/uploads/2023/04/siz_metodishka_a5.pdf|автор=Спельникова М.И, Булгакова М. В., Жукова В.А., Ларионов А.Н., Хохлов А.И|заглавие=Методические рекомендации по подбору и применению средств индивидуальной защиты органа слуха|ответственный=В.И. Котов|год=2018|место=Москва|издательство=Ассоциация СИЗ|страниц=24}}</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] g90lf83hdvcj08vff0ayzht99d0sijm Средства индивидуальной защиты (обзорная лекция)/СИЗ лица и глаз 0 35736 270424 269050 2026-10-27T07:07:37Z Jcb 79968 270424 wikitext text/x-wiki [[File:230308-N-DE439-1051 - Engineering Drills.jpg|thumb|200px|Использование защитных очков]]'''Средства индивидуальной защиты лица и глаз''' - вид [https://miningwiki.ru/wiki/Средства_индивидуальной_защиты средств индивидуальной защиты], предназначенный для защиты лица и [[:w:глаз|глаз]] от: механических повреждений, воздействия химических веществ, [[:w:Пыль (вредный производственный фактор)|аэрозольных загрязнений воздуха]] и биоаэрозолей, раскалённых частиц, [[:w:лазер|лазерного]] и других [[:w:Электромагнитное излучение|электромагнитных излучений]] видимого и невидимых диапазонов разной интенсивности, неблагоприятного [[:w:Микроклимат|микроклимата]], [[:w:Поражение электрическим током|поражения электрическим током]], [[:w:Ионизирующее излучение|радиации]]. При работе с раскалённым металлом, стеклом и др., сварке на глаза и лицо действует интенсивное излучение инфракрасной, видимой и ультрафиолетовой частей спектра. [[:w:Инфракрасное излучение|Инфракрасное излучение]] может значительно повысить риск развития [[:w:Катаракта|катаракты]]<ref name="БМЭ-3изд-ТОМ-10" /> хрусталика глаза<ref name="Lydahl-1984" />. Действие [[:w:Ультрафиолетовое излучение|ультрафиолетового облучения]] проявляется гораздо быстрее, уже через 2-6 часов появляется [[:w:Эпифора (медицина)|слезотечение]], [[:w:светобоязнь|светобоязнь]], боли, [[:w:Головная боль|головная боль]]<ref name="Шафранова-1937-6" />. === СИЗ сварщиков === [[File:СИЗОД-с-принудительной-подачей-воздуха-под-шлем-сварщика-2.jpg|thumb|120px|left|Комбинированное СИЗ сварщиков]]При сварке работники подвергаются воздействию нескольких вредных производственных факторов: интенсивного светового и теплового излучения; [[:w:Пыль (вредный производственный фактор)|пыли]] токсичных веществ; вредных газов ([[:w:Монооксид углерода|окись углерода]], [[:w:Оксиды азота|оксидов азота]], углеводороды) и других<ref name="БМЭ-Воронцова" /><ref name="МОТ-сварка" />. Соответственно, лучше всего использовать для защиты комбинированные СИЗ, защищающие глаза, лицо, голову и органы дыхания<ref name="СИЗ-1986-2" />, пример слева (защита глаз, лица, органов дыхания), особенно при отсутствии хорошего местного отсоса и общеобменной [[:w:вентиляция |вентиляции]]. [[:w:Электроофтальмия|Электроофтальмия]]<ref name="Электроофтальмия-2010" /> наблюдалась у вспомогательных рабочих ([[:w:Слесарь|слесарей]] и др.) даже чаще, чем у сварщиков<ref name="Найман-1961-" />. Для их защиты (например, при удерживании свариваемых деталей в требуемом положении при их креплении) рекомендованы СИЗ с полностью непроницаемой для света боковой поверхностью и умеренно затемнённым передним стеклом<ref name="Шафранова-1937-6" />. ==== Научные исследования ==== Неудобства, связанные с необходимостью поднимать и отпускать защитный щиток электросварщика, побуждали использовать разные приспособления, например - электропривод. Для профилактики электроофтальмии поднимание откидной части щитка со светофильтром блокировало зажигание сварочной дуги<ref name="Найман-1961" />. Для создания удобных в работе [[:w:Светофильтр|светофильтров]], прозрачных до зажигания [[:w:Электрическая дуга|сварочной дуги]], и быстро уменьшающих прозрачность при увеличении [[:w:Световой поток|светового потока]], проводились [[:w:Научно-исследовательские и опытно-конструкторские работы|научные исследования и опытно-конструкторские работы]]. Изучалось влияние [[:w:Поляризация волн|поляризованного света]] на животных и сварщиков<ref name="Автозатемнение-1988" />. ==== Требования к СИЗ ==== [[File:БИОТ-2019 Маска сварщика с подачей воздуха.jpg|thumb|right|310px|Комбинированное СИЗ сварщика, предусматривающее принудительную подачу отфильтрованного воздуха]] Для защиты лица и глаз широко используют сварочные щитки разной конструкции со [[:w:светофильтр|светофильтрами]], уменьшающие воздействие теплового и ультрафиолетового излучения на лицо и глаза, и защищающие их от раскалённых частиц металлов. СИЗ глаз также используют при очистке [[:w:Окалина|окалины]] (например очки). Существуют международные и национальные стандарты с требованиями к таким СИЗ, и к светофильтрам (в том числе с автоматическим затемнением)<ref name="СИЗ-сварка-2014" />. ==== Выбор и применение ==== [[File:Great Bridge Lock Replacement 2014 (12680435433).jpg|thumb|right|300px|Защита лица и глаз при сварке]] В довоенный период в СССР выпускались несколько видов защитных стёкол по затемнению (светофильтры "ТИС", класс 1: ток свыше 350 А; 2: 100-350 А и 3: до 100 А; классы 3, 4 и 5 для сильной, средней и слабой ацетиленовой сварки). Для оценки соответствия их прозрачности выполняемой работе советовали: "самое лучшее передать сомнительное стекло электросварщику, который и выяснит на работе, является ли стекло подходящим при соответствующем ампераже"<ref name="Шафранова-1937-6" />. Разработаны требования к выбору и применению СИЗ, закрепляемые на уровне национального законодательства, пример<ref name="очки-США" />. ==== Результат ==== В канадской провинции ([[:w:Альберта|Альберта]]) случаи травмирования глаз на рабочих местах чаще всего происходили у [[:w:Сварщик|сварщиков]], 21%. В основном это приводило к временной утрате трудоспособности (несколько дней), причина - попадание в глаза холодных частиц, обычно металлических 49%, неметаллических 14%; мусор 5%, раскалённых частиц 7%. 23% пострадало из-за интенсивного излучения. Каждый десятый не заметил случившееся сразу. Работники выполняли: обработку холодного металла 43%, сварка, резка или выдалбливали отверстие 24%, помогали другим работникам или смотрели, как они работают 16%. Чаще всего пострадавшие работали на "металлообрабатывающих" предприятиях или занимались сваркой листового металла. СИЗ глаз не использовали 77%<ref name="Reed-1989" />. Причины травмирования глаз сварщиков и работников других профессий, выполнявших сварочные работы в США, оказались схожи: 77,5% попадание в глаз частиц, и 27,8% воздействие [[:w:Ультрафиолетовое излучение|ультрафиолетового излучения]] (в этом исследовании на сварщиков реже, чем на не сварщиков, 20% и 41%). В большинстве случаев использовалось исправное оборудование. Результат был получен путём анализа базы данных страховой организации (среди более 530 тыс. случаев в 2000 г. травмы глаз у сварщиков составили 1353, у других работников, выполнявших сварку 822). В 57% случаев в момент травмирования велись сварочные работы, [[:w:Шлифование|шлифование]] или очистка (в 22% информация о выполнявшейся работе отсутствовала). Информация о применении СИЗ часто отсутствовала (86%), а из тех случаев, когда имелась, в момент травмирования СИЗ не использовали 7%, снимали или надевали 20%<ref name="Lombardi-2005" />. Среди 382 африканских сварщиков, занятых в "неформальном" секторе экономики, 3/4 имели личные СИЗ глаз (14% лицевые щитки, остальные - защитные очки; преимущественно нестандартные, "местного" производства, отчасти неэффективные). Но использовала их на практике лишь треть работников. При опросе они объяснили это тем, что СИЗ снижают [[:w:Производительность труда|производительность труда]] (большинство работает более 12 часов в день, среднемесячная зарплата порядка 100 долларов США), и неудобность СИЗ, и тем, что их использование увеличивает перегрев организма. Также указывали на кратковременность сварочной работы, низкую оценку уровня риска, нехватку времени и забывчивость. Результат: более 95% сварщиков сообщили, что за последний год у них был хотя бы один случай травмирования глаз. Риск травмирования глаз был ниже при использовании [[:w:Газовая сварка|газовой сварки]], обучении работника выполнению работы и применению СИЗ, и возрастал с ростом зарплаты<ref name="Гана-2020" />. В статье<ref name="Анисимова-2014" />, без ссылки на первоисточник, приведены некоторые статистические данные о заболеваниях глаз. В целом, все профзаболевания глаз составили 6,4% от профзаболеваний в РФ; а из них 85% были профессиональные заболевания органа зрения сварщиков: лучевая катаракта, буллезная керопатопатия, и другие. Сюда не входит травмирование глаз инородными предметами. По данным<ref name="Алексеева-1984" /> доля профзаболеваний глаз сварщиков меньше, в разных источниках 40-44%: снижение остроты зрения, рези, [[:w:ru:Электроофтальмия|покраснение глаз]], [[:w:ru:Катаракта|катаракту]], отёк и другие. Авторы отмечают, что при использовании мощных [[:w:Электрическая дуговая сварка|сварочных аппаратов]] ([[:w:судостроение|судостроение]]) эффективный отсос увеличивает оптическое воздействие на работника. Большая доля профзаболеваний глаз именно у [[:w:Сварщик|сварщиков]], составляющих небольшую часть всех работников, может объясняться несовершенством используемых средств защиты, в том числе индивидуальных. === СИЗ лица и глаз === [[File:Researcher wearing face shield.jpg|thumb|right|240px|Лицевой щиток]] Для защиты от летящих частиц; химических веществ, загрязняющих воздух в газообразном состоянии и в виде аэрозоля; лазерного и другого излучения используют очки, лицевые щитки и шлемы<ref name="МОТ-глаза" />. К причинам травмирования глаз относили<ref name="МЗ-1987" />: # '''Организационные''': неправильная организация труда, отсутствие правил безопасности или надзора за их выполнением, недостаточная трудовая дисциплина, некачественный инструктаж и плохое обучение безопасным приёмам работы, неудовлетворительное содержание рабочих мест. # '''Технические''': конструктивные недостатки оборудования, несоответствие технологии требованиям безопасности, недостаточная [[:w:автоматизация|автоматизация]], неисправности оборудования, инструментов, несовершенство [[:w:Средства коллективной защиты |средств коллективной защиты]]. # '''Санитарно-гигиенические''': не соответствие нормам температуры и влажности воздуха, плохое освещение (порядка четверти травм), повышенная запылённость и/или загазованность, загромождённость и теснота, повышенные [[:w:Производственный шум|шум]] и [[:w:Вибрационная болезнь|вибрация]], и другие факторы. # '''Индивидуальные''': несоответствие работника [[:w:Профессиональная ориентация|профессиональному отбору]], нарушение им дисциплины, [[:w:Алкогольное опьянение|употребление алкоголя]], наличие общих заболеваний, включая заболевания глаз (травмы у рабочих с дефектами зрения наблюдались примерно вдвое чаще), недостаток опыта/квалификации (40% у необученных и 1% у квалифицированных рабочих). ==== Научные исследования ==== Защитные очки могут уменьшать [[:w:поле зрения|поле зрения]], что может затруднять ориентирование в пространстве, выполнение производственных операций, способствовать развитию утомления и ухудшению самочувствия<ref name="Полоний-1980" />. Отличие от параллельности лучей, идущих от объекта к глазу, вызывают его напряжение и [[:w:Утомление|утомление]]<ref name="Голубева-1975" />. Искажения оптических СИЗ влияют на работников: могут снижаться пороги [[:w:Зрение_человека#Контрастная_чувствительность|контрастной]] и [[:w:Зрение_человека#Световая_чувствительность_человеческого_глаза|световой чувствительности]], уменьшаться показатели [[:w:остроты зрения|остроты зрения]], изменяться пространственное восприятие<ref name="МТПИЗЧ-21-1980" />. Испытания герметичных очков для защиты от газов проводят на манекене<ref name="ГОСТ-очки-309" />. У конкретного рабочего могут быть анатомические особенности, которые могут мешать добиться плотного прилегания обтюратора - что лабораторные сертификационные испытания не учитывают. Для сравнения, маски СИЗ органов дыхания проверяют на группе испытателей. В США и позднее в КНР провели широкомасштабные исследования для определения [[:w:ru:Антропометрия|антропометрических]] показателей работников, включавшие не только измерения размеров лиц и голов, но и трёхмерное сканирование - чтобы подобрать участников испытаний, соответствующих большинству работников<ref name="Антропометрия" />. Согласно<ref name="ГОСТ-очки-253" /> незапотевающие стёкла для защитных очков обозначаются "N" в конце маркировки. В условиях испытаний (водяная баня 50°С) они должны оставаться не запотевшими 8 секунд<ref name="ГОСТ-очки-253" />. В [https://miningwiki.ru/wiki/Технический_регламент_"О_безопасности_СИЗ" Техническом Регламенте] требования иные: за полчаса светопропускание должно снижаться не более чем на 10% при влажности 80%, метод измерения не указан (раздел 4.3, пункт 17<ref name="ТР-ТС" />). Но, по данным (стр. 24<ref name="Шафранова-1937" />) все виды закрытых очков имеют тенденцию к запотеванию. А при тяжёлой физической работе, присутствии раскалённого металла, искр, тепловом излучении ".. при специфических условиях этой группы работ '''стёкла всяких очков запотевают очень быстро'''; смазка против запотевания здесь мало помогает, так как стёкла покрываются потом, стекающим со лба рабочего. ". Попытка использовать 9 разных моделей очков в угольной шахте показала, что все закрытые очки запотевают за считанные минуты так, что их невозможно использовать; открытые могут запотевать за 10-20 минут. Единственная модель, в которой можно было работать 1-2 часа (С-15) не имели стёкол вообще, а состояли из мелкой металлической сетки (которую надо было периодически продувать из-за загрязнения пылью). Использование незапотевающих плёнок при большой запылённости в [[:w:Забой#Очистной_забой|очистных забоях]] привело к быстрому налипанию пыли на плёнку, и практически никакого положительного влияния они не давали. Часть рабочих начала использовать очки - кратковременно, при наибольшей опасности для глаз<ref name="шахты-1969" />. ==== Затруднения при использовании ==== Все защитные очки сужают нормальное [[:w:поле зрения|поле зрения]]. Из более чем полусотни моделей очков, предназначенных для защиты учащихся и подростков, и рабочих для работы у доменных, стекловаренных и нагревательных печей (при температурах до 1200, 1200-1500 и 1500-1800°С), [[:w:Прокатный стан|прокатных станов]], в кузнечных цехах, газо- и электросварке, газовой резке (средней и мощной), в строительстве, для персонала радиолокационных станций и лабораторий [[:w:ru:СВЧ_(значения)|СВЧ]], при работе с лазерами и люминесцентной дефектоскопии - лишь одна модель (ЗН16-90) могла использоваться вместе с корректирующими очками<ref name="Гаевая-1972" />. Оптические дефекты (царапины, сколы, неровности), ухудшение видимости - повышают утомляемость, вызывают головные боли, ухудшают самочувствие и остроту зрения, что снижает [[:w:Производительность труда|производительность труда]] и повышает риск травмирования. У закрытых герметичных (противодымных) очков может происходить очень быстрое запотевание стёкол, не позволяющее выполнять работу<ref name="Противогаз-глаза" />. В результате при работе с агрессивными веществами на Щёлковском химическом завода глаза рабочих в большинстве случаев были не защищены, и в 1964-1966 гг. до 75% повреждения глаз произошло из-за не применения этих СИЗ<ref name="очки-1970" />. При использовании закрытых защитных очков отмечались случаи запотевания стёкол, и другие недостатки, и что часть работников их не использовала<ref name="очки-1988" />. Для защиты глаз от [[:w:ru:Сантиметровые волны |радиоволн сверхвысоких частот]] разработали закрытые очки со стеклянными линзами с очень тонким, прозрачным металлическим покрытием. И у них при практическом применении отмечалось запотевание стёкол, мешавшее использованию<ref name="Денисенко-1981" />. Для сравнения, у защитных очков схожего назначения, для боковой защиты предусматривалась металлическая сетка, и они не предназначались для длительного использования - главным средством были экраны, изолировавшие источники излучения<ref name="СИЗ-1973-11" />. При высокой влажности воздуха и небольшой скорости его движения, запотевание очков (без не запотевающих плёнок) в подготовительных выработках через 1-2 минуты могло быть таким, что шахтёры не могли продолжать работать. Также их использованию мешали слабая [[:w:Освещённость|освещённость]] и загрязнение стёкол<ref name="Чистик-1969" />. Невозможность использовать закрытые очки привела к тому, что вместо них для защиты глаз от токсичных веществ использовали [[:w:противогаз|противогазы]]<ref name="Противогаз-глаза" />. Для того, чтобы не утомлять глаза использованием защитных очков, но, при необходимости, всегда иметь под рукой защиту для глаз от летящих частиц, шахтёры сами сделали каску с выдвигавшимся из-под неё щитком из органического стекла. В выдвинутом положении щиток находился на расстоянии 20 мм от лица, и потому не запотевал<ref name="БТП-09-1971" />. Поставщик СИЗ сообщила о возможности ошибок при выборе этих СИЗ; упомянула возможность запотевания стёкол закрытых очков, и наличии у некоторых моделей покрытия для уменьшения запотевания (причём в стандартизованной маркировке это не отражается); а также (для рабочих с ухудшившимся зрением) специальные защитные очки для ношения поверх корригирующих [[:w:Очки|очков]], которые могут быть неудобны<ref name="Луговая-2014" />. Также она упомянула, что все защитные очки, в большей или меньшей степени, дают искажение, которое может повлиять на работника (у очков 1 оптического класса оно меньше). Отмечались различные недостатки, мешающие использованию защитных очков: открытые очки защищают от ударов частиц только спереди; использование закрытых очков вместе с корректирующими невозможно, у части рабочих возникает неприятное ощущение из-за их давления на лицо, при непрямой вентиляции - не защищают от пыли (при работе с едкими веществами - недопустимы), но и непрямая вентиляция не гарантирует отсутствие запотевания; очки с прочными стёклами - тяжёлые, неудобные, могут сползать во время работы<ref name="Шафранова-1937" />. ==== Требования к СИЗ ==== Разработаны минимальные технические требования к таким СИЗ, национальные и международные, пример<ref name="очки-ANSI"/><ref name="очки-ISO-" />. Они выполняются изготовителями, и сертифицированные СИЗ поступают в продажу. При сертификации может проводиться проверка противозапотевающих покрытий. Но она проводится в строго определённых стандартизованных лабораторных условиях, в последних редакциях стандартов по СИЗ глаз предусмотрено тестирование не СИЗ в сборе, а изолированных стёкол. Такие проверки не дают никакой информации о риске запотевания при применении СИЗ на практике. Из-за полной бесполезности лабораторной проверки запотеваемости стёкол (изолированных) для оценки риска утраты оптических свойств в условиях реального применения, в Канаде при сертификации "антизапотевающие" покрытия не проверяют вообще<ref name="очки-Канада"/>. ==== Требования и рекомендации по выбору и применению ==== В США есть государственные требования к защите глаз и лиц работников<ref name="очки-США" />. В самих требованиях описаны лишь СИЗ при сварке, но указано, что для защиты от других [[:w:Вредный производственный фактор|производственных факторов]] следует выбирать СИЗ на основе стандарта, который сам по себе не обязателен для выполнения<ref name="очки-ANSI" />. Несмотря на то, что документ новый, и разработан с учётом выпуска широкого ассортимента защитных очков с покрытиями против запотевания, в нём часто рекомендуется защищать глаза так, как в СССР в 1942 году<ref name="Противогаз-глаза" /> - с помощью СИЗОД с полнолицевой маской. У таких масок вдыхаемый воздух сначала обдувает смотровое стекло, а потом входит в подмасочник и органы дыхания. Обдув значительно уменьшает запотевание панорамных стёкол даже зимой. Аналогичная рекомендация давалась и в довоенный период, для случаев защиты не только глаз, но и лица от большого числа быстролетящих частиц ("Случай V" стр. 23-24<ref name="Шафранова-1937" />). Требования (общего характера) есть в [[:w:ru:Северо-Западные территории |канадской провинции]]<ref name="Канада-глаза+" />, но юридически они менее "обязательны", чем требования законодательства. В Великобритании<ref name="очки-BS" />, Канаде<ref name="Канада-глаза" /> и Австралии<ref name="очки-AS" /> несколько десятилетий имеются рекомендации по выбору и использованию СИЗ глаз и лица, которые работодатели могут добровольно выполнять. Недавно появился и международный стандарт<ref name="очки-ISO" />. В таких требованиях, например<ref name="очки-США" />, указывается на необходимость подбора и тщательной подгонки СИЗ у каждого работника, особенно при использовании закрытых очков для защиты от химических веществ. Это схоже с тем, что при использовании СИЗ органов дыхания маска должно прилегать к лицу плотно, без зазоров. Но при использовании респираторов во всех развитых странах требуется подбирать маски индивидуально и затем [[:w:Проверка изолирующих свойств респираторов |приборами проверять]] - соответствуют ли они лицу не только по размеру, но и по форме, и проверять, насколько правильно и аккуратно умеет их одевать каждый работник. Разработаны и изучены средства для проведения таких замеров. А в требованиях к выбору и применению защитных очков нет ничего подобного. И неизвестно, как они будут защищать конкретного работника - с учётом разнообразия лиц людей, особенно в области носа. Из-за недопустимости подбора СИЗ глаз "по профессии" и даже по виду работ<ref name="Шафранова-1937-1" />, без учёта конкретных их особенностей, и индивидуальных особенностей работника, даны подробные рекомендации по выбору подходящих типов и моделей СИЗ. Отмечалось, что "работать в таких ''(закрытых - прим.)'' очках дольше 10-15 минут подряд очень тяжело", и при защите глаз от газов и особо вредной пыли рекомендовалось использовать фильтрующие СИЗ органов дыхания с маской, закрывающей глаза; шланговые и другие изолирующие СИЗОД<ref name="Шафранова-1937-4" />. Рекомендовалось<ref name="Шафранова-1937-7" />: # Перед выбором очень тщательно изучить все условия труда и характер работы, привлекая к этому [[:w:инженер|инженеров]], мастеров, представителей санинспекции, охраны труда и здравоохранения; # Выполнять контроль качества поступающих на предприятие СИЗ; # Выдавать СИЗ работникам только индивидуально; # Выяснять степень их удобности, что необходимо сделать для её повышения (подобрать другую модель, заменить другим типом с равной степенью защиты, внести изменения в конструкцию); # При запотевании, которое происходит у '''всех''' видов очков, особенно при работе на холоде, и когда рабочий потеет, рекомендовалось смазывать их обезвоженным натронным мылом, которое "стекло остаётся незапотевшим более или менее долгое время. ... в обычных условиях ... для очков типа шофёрских ... смазка отдаляет момент запотевания стёкол не 40-50 минут". А "герметичные закрытые без применения смазки запотевают через несколько секунд, а со смазкой выдерживают 10-15 мин.". # Мастер обязан обучить рабочих и следить за правильным и своевременным использованием СИЗ; # Рабочий должен следить за качеством и исправностью СИЗ, хранить их в футляре или завёрнутым в ткань/бумагу, перед работой протирать стёкла, после работы тщательно очищать, и своевременно использовать подходящие средства защиты. ==== Эффективность на практике ==== [[File:U.S. Air Force soldier uses a grinder to shape a metal part.jpg|thumb|right|300px|Защита лица и глаз при абразивной обработке металла]] По данным Диспансера условий труда [[:w:ru:Кралево (город)|г. Кралево]] основными причинами 5883 травм глаз были недостаточная [[:w:Внимание|внимательность]] рабочих (из-за [[:w:Утомление|усталости]]), неопытность молодых рабочих, и повышенная самоуверенность опытных. Всех бесплатно обеспечивали разнообразными защитными очками, с и без боковой защиты глаз, часть получала защитные щитки и электросварочные шлемы. И большинство рабочих "избегает их применения ''везде, где это возможно'', так как они ограничивают подвижность, в них неудобно работать, они вызывают усталость"<ref name="Бачанац-1997" />. Это согласуется с результатами исследований защитных очков и их практического применения, проведённых ВНИИ охраны труда ВЦСПС и Государственным [[:w:Национальный медицинский исследовательский центр глазных болезней имени Гельмгольца|НИИ глазных болезней им. Гельмгольца]]: очки могут использоваться только если они удобные; своевременное применение прямо зависит от сохранения остроты зрения и поля зрения. Также отмечалось, что длительное применение защитных очков вызывает головную боль и утомление зрения, вынуждающие отказываться от их использования<ref name="Очки-ГОСТ" />. Изучение обстоятельств травмирования глаз у 426 китайских больных показало, что в 21% случаев СИЗ работодателем не выдавались. Причин травм работников, которым выдавали СИЗ: недостатки СИЗ (60%) и отсутствие знаний и навыков по охране труда (40%). Поскольку большинство пострадавших не применяло СИЗ, авторы сделали вывод о необходимости их использования - в сочетании с правильным выбором достаточно надёжных изделий<ref name="глаза-стат-Ch" />. В 2016-2018 гг. была собрана информация о 1424 пациентах из 4 госпиталей в [[:w:ru:Тэгу|Тэгу]] (Южная Корея). Тяжёлые травмы глаз несколько чаще происходили у тех работников, которые не применяли СИЗ; но отличие не было [[:w:Статистическая значимость|статистически значимым]]. Авторы предположили, что СИЗ могли не соответствовать выполняемой работе и/или индивидуальным особенностям сотрудника. По виду работы, пострадавшие часто шлифовали или резали металл, сваривали его, работали с химикатами (29, 14 и 7%). СИЗ использовали 61 из 1341 пострадавших<ref name="Корея-2020" />. Из 500 участников исследования, проведённого в ОАЭ, и работавших на 95 небольших предприятиях, подавляющее большинство знало об опасности и о наличии доступных (в большинстве случаев) СИЗ. Но большинство рабочих не использовало их своевременно, или вовсе не применяло: снижение производительности труда, ухудшение остроты зрения, трудности с использованием в нагревающем микроклимате, неудобность СИЗ<ref name="глаза-стат-" />. По австралийским данным, полученным из отделений скорой помощи, больниц, и при выплате компенсаций рабочим<ref name="глаза-стат-AU" />, в сообщениях о травмировании глаз часто отсутствуют сведения об использовании или не применении СИЗ. Авторы были уверены, что СИЗ позволяют эффективно предотвращать травмы. Но, при наличии данных о применении СИЗ, оказалось: в [[:w:Виктория (штат)| Виктория]] отношение между использовавшими и не применявшими СИЗ в момент травы около 7:5; при сварочных работах, отношение между использовавшими и не применявшими СИЗ (или применявшими, но неправильно): 23:15; а в штатах [[:w:Квинсленд|Квинсленд]] и [[:w:Южная Австралия|Южная Австралия]] СИЗ применяли в 5 раз чаще, чем не использовали. Исходные данные были достоверны, и авторы оказались сильно удивлены этим результатом. Они отметили, что сообщения о травмировании глаз при использовании СИЗ публиковались и ранее. Чаще всего несчастные случаи происходили при [[:w:Абразивные материалы и абразивная обработка|абразивной обработке]], и сварке. В трёх провинциях, охваченных исследованием, проживало более половины населения страны. Из 1069 пациентов офтальмологической клиники в Калгари (Канада) треть использовала СИЗ<ref name="глаза-стат-Ca" />. В СССР ежегодно изготавливалось 13 млн. пар различных защитных очков, а в РСФСР около 10% случаев травм глаза происходило при использовании этих СИЗ<ref name="МЗ-1987" />. 9 из 10 травм происходили у работников-мужчин, по виду работы - при обработке металла (71,6%), в том числе 36% при ручной обработке, немеханизированных операциях. 55% - молодые рабочие (до 40 лет), 2/3 первично выходивших на инвалидность - жители деревни. Со ссылкой на Бюро трудовой статистики (''BLS''), [[:w:Управление по охране труда (OSHA)|Департамент условий труда]] (Минтруд США) сообщил, что из каждых 5 пострадавших двое использовали СИЗ глаз. При этом в 94% случаев химикат или летящий предмет попадал в глаз сбоку или снизу, что совпадает с наблюдением за результатами использования открытых очков (1937 г. с. 14<ref name="Шафранова-1937" />): "... очки открытого типа защищают глаза только спереди и лишь отчасти сбоку, а потому полной гарантии безопасности они не дают". Разрушение СИЗ случалось редко. Около 40% работников не имели представления о том, какие СИЗ должны применяться. В целом, в США регистрируют порядка тысячи травм глаз ежедневно<ref name="глаза-стат-US" />, в 2020 г. зарегистрировано 18 510 случаев временной утраты трудоспособности из-за травм глаз; в 2024 г. более 2 тысяч штрафов за нарушения требований к защите органов зрения работников<ref name="Очки-штрафы" />. === Первая помощь при травмах глаз и их профилактика === Во-первых, при подозрении на попадание в глаз осколка или другой травме следует незамедлительно обратиться к специалисту. При повреждении крупным предметом нельзя его извлекать самостоятельно. Для удаления мелких инородных частиц из [[:w:ru:Ферромагнетики|ферромагнитных]] металлов может использоваться [[:w:магнит|магнит]], для остальных может быть полезна промывка (есть специальные фонтанчики), при попадании химических веществ - промыть проточной водой<ref name="Гаевая-1972" />. При ожоге кислотами следует промывать глаз слабым раствором 1-2% раствором соды. При попадании щёлочи необходимо промывать слабым раствором [[:w:Борная кислота|борной кислоты]] (1 чайная ложка на стакан воды). Химические повреждения могут происходить и при попадании в глаза стройматериалов (штукатурка, цемент и [[:w:Известь (материал)|известь]] относятся к щелочной группе). При повреждении глаз [[:w:Ультрафиолетовое излучение|ультрафиолетовым излучением]], прямым или отражённым, может быть полезен холодный водяной компресс, закапывание в глаза рыбьего жира, вазелинового масла (жидкого жира). Главным средством профилактики травмирования глаз должно снова стать использование [[:w:средства коллективной защиты|средств коллективной защиты]] (улучшение технологии, автоматизация и механизация работ, [[:w:дистанционное управление|дистанционное управление]], защитные экраны из прозрачных материалов и сеток, и другие приспособления, [[:w:вентиляция|вентиляция]] и т.п.). Если избежать использования СИЗ не удалось, то "Необходимо учитывать, что эффективность применяемых средств защиты зависит не только от их выбора, но и от индивидуальной подгонки, а также правильного хранения. ... Выбор защитных очков, щитков, масок зависит в первую очередь от конкретных условий производственного процесса и его особенностей, характера повреждающих агентов, возможной опасности для глаз, длительности выполняемой операции ...<ref name="Гаевая-1972" />.". В числе мер, предупреждающих ранения глаз работников, главным является соблюдение требований техники безопасности<ref name="Профилактика-глаза-2018" />: # техническая грамотность сотрудников; # адекватная техническая оснащённость рабочих мест, отбраковка устаревших инструментов и оборудования; # наличие и правильное, своевременное применение эффективных [[:w:Средства коллективной защиты|средств коллективной защиты]], а также СИЗ; # нетерпимость к личной [[:w:Дисциплинированность|недисциплинированности]] (иногда она свойственна молодым работникам). === СИЗ глаз от лазерного излучения === [[File:Flickr - Official U.S. Navy Imagery - An electronics engineer at Naval Surface Warfare Center, Corona Division, prepares alignment of various optical components using eye-safe visible lasers..jpg|thumb|right|310px|Использование СИЗ глаз от лазерного излучения видимого диапазона]] ==== Требования к СИЗ ==== При [[:w:Безопасность лазеров|защите глаз от опасного лазерного излучения]] возникает ряд проблем. СИЗ должны достаточно хорошо пропускать электромагнитное излучение видимого диапазона, так, чтобы в них можно было работать; и одновременно они должны очень сильно ослаблять излучение на [[:w:Длина волны#Случай электромагнитной волны|длине волны]] лазерного оборудования. По данным руководства для инспекторов по охране труда ([[:w:OSHA|OSHA]]) в промышленности США используют порядка 17 разных ''основных'' типов [[:w:лазер|лазеров]] с разными длинами волн<ref name="инспектор-2022-l" />. А по данным<ref name="Пальцев-1976" /> уже в 1969 году в СССР было разработано 65 типов лазерного оборудования, использовавшего суммарно излучение с 357 разными длинами волн. В результате для многих видов лазеров СИЗ не были разработаны вообще<ref name="СИЗОС-1973-лазер" />. ==== Выбор СИЗ глаз от лазерного излучения ==== Рекомендации по выбору СИЗ глаз от лазерного излучения, и при настройке лазеров, есть в приложениях в стандартах<ref name="Лазеры-рекоменд" /><ref name="Лазеры-настройка-рекоменд" />. == Примечания == {{примечания|refs= <ref name="БМЭ-3изд-ТОМ-10">{{книга|автор= Шмелева В. М. Абдуллаева В.М, |часть= [http://бмэ.орг/index.php/КАТАРАКТА Катаракта] |часть ссылка= |ответственный=гл. ред. Б.В. Петровский|заглавие=Большая медицинская энциклопедия |издание=3 изд |место=Москва|издательство=Советская энциклопедия |год=1979 |том=10. [http://бмэ.орг/index.php/Категория:Том_10 Кабаков - Коалесценция] |томов=30 |страницы= |страниц=528 |тираж=150300}}</ref> <ref name="Lydahl-1984">{{Статья|автор=E. Lydah, B. Philipson.|заглавие=Infrared radiation and cataract. I. Epidemiologic investigation of iron- and steel-workers|год=1984|язык=en|издание=Acta Ophthalmologica|издательство=John Wiley & Sons, Inc|месяц=12|выпуск=6|pages=849-1024|volume=62||doi=10.1111/j.1755-3768.1984.tb08449.x|pmid=}} ISSN 1755-375X, {{PMID|6524321}}</ref> <ref name="МОТ-глаза">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =Ю.Г. Сорокин <small>(''руководитель Департамента условий и охраны труда, Минтруд РФ'')</small>; Жан-Виктор Груа <small>(''Директор Московского бюро МОТ'')</small>.|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[http://base.safework.ru/iloenc?d&nd=857400341&prevDoc=857400341&spack=110LogLength%3D0%26LogNumDoc%3D857400038%26listid%3D010000000100%26listpos%3D1%26lsz%3D7%26nd%3D857400038%26nh%3D1%26 Средства защиты глаз и лица]. В: Том 1; Раздел [http://base.safework.ru/iloenc?d&nd=857400005&prevDoc=857000002 IV], Глава [http://base.safework.ru/iloenc?d&nd=857400038&prevDoc=857400346 31. Средства индивидуальной защиты] |автор=Кикузи Кимура |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|isbn=|серия= Охрана труда}} [https://www.iloencyclopaedia.org/part-iv-66769/personal-protection-59388 ''Eye and Face Protectors'']</ref> <ref name="БМЭ-Воронцова">{{книга|автор= Воронцова Е.И.|часть= [http://бмэ.орг/index.php/СВАРКА Сварка, гигиена труда] |часть ссылка= |ответственный=гл. ред. Б.В. Петровский|заглавие=Большая медицинская энциклопедия |издание=3 изд |место=Москва| издательство=Советская энциклопедия |год=1984 |том=23. [http://бмэ.орг/index.php/Категория:Том_23 Сахароза - Сосудистый тонус] |томов=30 |страницы= |страниц=544 |тираж=150 800}}</ref> <ref name="МОТ-сварка">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =Ю.Г. Сорокин <small>(''руководитель Департамента условий и охраны труда, Минтруд РФ'')</small>; Жан-Виктор Груа <small>(''Директор Московского бюро МОТ'')</small>.|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[http://base.safework.ru/iloenc?d&nd=857200685&prevDoc=857200685&spack=110LogLength%3D0%26LogNumDoc%3D857200672%26listid%3D010000000100%26listpos%3D2%26lsz%3D9%26nd%3D857200672%26nh%3D1%26 Сварка и огневая резка]. В: Том 3; Раздел [http://base.safework.ru/iloenc?d&nd=857200805&prevDoc=857000002 XIII], Глава [http://base.safework.ru/iloenc?d&nd=857200648&prevDoc=857200685 82. Технология металлов и металлообрабатывающая промышленность] |автор=Филип А. Платкоу, Г.С. Линдон |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|isbn=|серия= Охрана труда}}</ref> <ref name="СИЗ-1986-2">{{Книга|автор=Сосенков Ю.Н., Клавдиенко А.С., Каминский С.Л.|заглавие=Испытание автономного пневмошлема в комплекте с переносным источником воздухоснабжения при выполнении электросварочных работ |ответственный=Бутова Т.Н. отв. ред|год=1986|часть=Пути совершенствования автономных комплектов|место=Черкассы|издательство=ВНИИТЭХИМ |страницы=12-13|страниц=105|серия=Тезисы докладов Всесоюзной конференции, Северодвинск, октябрь 1986 г.|тираж=300 |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731670742&archive=&start_from=&ucat=&}}</ref> <ref name="Найман-1961-">{{Книга|автор=Найман И.М.|заглавие=Защита глаз на производстве|год=1961|часть=Защита глаз вспомогательных рабочих. В: Глава III. Защита глаз от лучистой энергии, раздел : Средства защиты лица и глаз при электросварочных работах|издание=2-ое изд., перераб. и дополн|место=Москва|издательство=Профиздат|страницы=181-183|страниц=288|тираж=7000}}</ref> <ref name="Электроофтальмия-2010">{{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1742903361&archive=&start_from=&ucat=&|автор=С. Х. Чурмантаева, Д.М. Вагопова, М.П. Обухова, Л.Р. Каримова, Л.В. Гирфанова, С.Р. Кадырова, Д.Р. Исхакова|заглавие=Профессиональные заболевания электросварщиков: пособие для врачей|ответственный=Министерство здравоохранения Республики Башкортостан|год=2010|часть=5. Заболевания органа зрения у электросварщиков|место=Уфа|издательство=Федеральное государственное учреждение науки "Уфимский научно-исследовательский институт медицины труда и экологии человека" Роспотребнадзора|страницы=19-26|страниц=30|isbn=978-5-9613-0158-8|тираж=100}}</ref> <ref name="Найман-1961">{{Книга|автор=Найман И.М.|заглавие=Защита глаз на производстве|год=1961|часть=Щитки и маски с автоматическими приспособлениями. В: Глава III. Защита глаз от лучистой энергии, раздел : Средства защиты лица и глаз при электросварочных работах|издание=2-ое изд., перераб. и дополн|место=Москва|издательство=Профиздат|страницы=175-179|страниц=288|тираж=7000}}</ref> <ref name="Автозатемнение-1988">{{Книга|автор=Гаврилова Л.М.|заглавие=Научно-технический прогресс и проблемы гигиены труда|ответственный=[https://ru.wikipedia.org/wiki/Кундиев,_Юрий_Ильич Кундиев Ю.И.] отв. ред|год=1988|часть=Результаты экспериментальных и производственных исследований по сравнительной оценке средств индивидуальной защиты органа зрения сварщика|издание=Министерство здравоохранения УССР|место=Киев|издательство=Киевский НИИ гигиены труда и профзаболеваний|страницы=52-54|страниц=184|серия=Тезисы докладов республиканской научно-практической конференции|тираж=750}}</ref> <ref name="Reed-1989">{{Статья|автор=Michael R. Reed, Ronald M. Dufresne, Donna Suggent, Brian C. Alleyne|заглавие=Welder Eye Injuries|год=1989|язык=en|автор издания=American Occupational Medical Association|место=Baltimore, Maryland|издание=Journal of Occupational Medicine|издательство=Wolters Kluwer Health, Inc.|месяц=12|выпуск=12|pages=1003-1006|volume=31|issn=|doi=10.1097/00043764-198912000-00014|pmid= }} ISSN 1076-2752, {{PMID|2533251}}</ref> <ref name="Lombardi-2005">{{Статья|ссылка=https://www.researchgate.net/publication/7809599_Welding_related_occupational_eye_injuries_A_narrative_analysis|автор=Lombardi D.A., Pannala R., Sorock G.S., Wellman H., Courtney T.K., Verma S., Smith G.S.|заглавие=Welding related occupational eye injuries: a narrative analysis|год=2005|язык=en|автор издания=International Society for Child and Adolescent Injury Prevention|место=London|издание=Injury prevention|издательство=MJ Pub. Group|месяц=3|выпуск=3|pages=174–179|volume=11|issn=|doi=10.1136/ip.2004.007088|pmid=|pmc=}} ISSN 1353-8047, PMC PMC1730216, {{PMID|15933411}}</ref> <ref name="Гана-2020">{{Статья|ссылка=https://www.researchgate.net/publication/344284840_Prevalence_and_Factors_Influencing_Eye_Injuries_among_Welders_in_Accra_Ghana|автор=Karl Kafui Kwaku Tetteh, Richard Owusu, Wisdom Kudzo Axame|заглавие=Prevalence and Factors Influencing Eye Injuries among Welders in Accra, Ghana|год=2020|язык=en|автор издания=Cairo : Hindawi Pub. Corp.|место=Egypt|издание=Advances in preventive medicine|издательство=John Wiley & Sons, Inc.|месяц=9|число=16|выпуск=3|pages=2170247|issn=|doi=10.1155/2020/2170247|pmid=|pmc=}} ISSN 2090-3499, PMC PMC7516735, {{PMID|33014472}}</ref> <ref name="Корея-2020">{{Статья|автор=Jae Yun Ahn, Hyun Wook Ryoo, Jung Bae Park, Sungbae Moon, Jae Wan Cho, Dong Ho Park, Won Kee Lee, Jung Ho Kim, Sang Chan Jin, Kyung Woo Lee & Jong-Yeon Kim|заглавие=Epidemiologic Characteristics of Work-related Eye Injuries and Risk Factors Associated with Severe Eye Injuries: A Registry-based Multicentre Study|год=2020|язык=en|автор издания=International Society of Geographical and Epidemiological Ophthalmology|место=London|издание=phthalmic Epidemiology|издательство=Taylor & Francis|месяц=4|выпуск=2|pages=105-114|volume=27|issn=|doi=10.1080/09286586.2019.1683868|pmid=}} ISSN 0928-6586, {{PMID|31672074}}</ref> <ref name="Шафранова-1937-6">{{Книга|автор=Шафранова А.С.|заглавие=Индивидуальная защита глаз рабочего на производстве|ответственный=ВЦСПС, Московский научно-исследовательский институт охраны труда|год=1937|часть=6. Защита глаз от действия лучистой энергии|место=Москва|издательство=Профиздат|страницы=33-35, 40|страниц=48|тираж=15300|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1738063241&archive=&start_from=&ucat=&}} [https://files.library.by/dl/files/СИЗ%20глаз%201937%20%2048%20с.pdf PDF]</ref> <ref name="СИЗ-сварка-2014">{{Книга|ссылка=https://meganorm.ru/Index2/1/4293774/4293774117.htm |автор=ОАО "ВНИИ сертификации"|заглавие=ГОСТ 12.4.254-2013 ССБТ Средства индивидуальной защиты глаз и лица при сварке и аналогичных процессах. Общие технические условия|год=2014|место=Москва|издательство=Стандартинформ|страниц=31|серия=МКС 13.340.20; EN 175:1997 Equipment for eye and face protection during welding and allied processes + EN 379:2003 Automatic welding filter|тираж=91}} [https://meganorm.ru/Data2/1/4293774/4293774117.pdf PDF]</ref> <ref name="Анисимова-2014">{{Статья|ссылка=https://cyberleninka.ru/article/n/klinicheskie-effekty-regulyatora-energeticheskogo-obmena-pri-korrektsii-narusheniy-slezoproduktsii-professionalnogo-geneza/viewer |автор=Анисимова С. Г., Мазина Н. К., Абрамова Т.|заглавие=Клинические эффекты регулятора энергетического обмена при коррекции нарушений слезопродукции профессионального генеза|год=2014|автор издания=ФГУН "Уфимский НИИ медицины труда и экологии человека" Роспотребнадзора|издание=Медицинский вестник Башкортостана|издательство=Издательство "ГБОУ ВПО БГМУ",|месяц=2|том=9|номер=2|страницы=163-169|issn=}} ISSN 1999-6209, [https://www.mvb-bsmu.ru/files/journals/2_2014.pdf PDF]</ref> <ref name="Алексеева-1984">{{Книга|автор=Алексеева И.С.|заглавие=Гигиена и безопасность труда при электросварочных и плазменных работах в судостроении|ответственный=Алексеева И.С., Норкин Ю.И.|год=1984|часть=Глава 2. Условия труда и мероприятия по их улучшению при основных сварочных процессах|место=Ленинград|издательство=Судостроение|страницы=39|страниц=112|тираж=6100}}</ref> <ref name="МЗ-1987">{{Книга|автор=Гундорова Р.А., Гришина В.С., Южаков А.М., Травкин А.Г., Валева Р.Г., Киселёва О.А., Денисенко О.Н., Леванов В.Я.|заглавие=Профилактика травм органа зрения. Применение средств индивидуальной защиты|ответственный=Лукьянчикова Л.С. , Панов В.Г. (Министерство здравоохранения РСФСР)|год=1987|место=Москва|страниц=21|серия=Методические рекомендации|тираж=500}}</ref> <ref name="очки-1970">{{Статья|автор=Гаевая Л.А., Фомина Н.И.|заглавие=Новый тип очков - моноблок|год=1970|ответственный=Всесоюзный центральный научно-исследовательский институт охраны труда|место=Москва|издание=Научные работы институтов охраны труда ВЦСПС|издательство=Профиздат|том=65|страницы=95-96}}</ref> <ref name="очки-1988">{{Книга|автор=Денисенко О.Н., Рогальский Л.М., Коротева А.Н.|заглавие=Совершенствование охраны труда в народном хозяйстве Средней Азии. Всесоюзная научно-практическая конференция, 29-31 марта 1988 г.|ответственный=Бульда Б.В., Искандеров Т.И. (ред.), Алиев М.А. (отв. за выпуск)|год=1988|часть=Новые очки для защиты глаз работающих с пестицидами в сельском хозяйстве|место=Ташкент|издательство=ВЦСПС|том=1|страницы=178-179|страниц=238|серия=тезисы докладов|тираж=500}}</ref> <ref name="СИЗ-1973-11">{{Книга|автор=Белявских К.С., Марченко Б.С.|заглавие=Пути совершенствования средств индивидуальной защиты работающих на производстве|ответственный=Цуцков М.Е., Городинский С.М., Смирнов В.Ф|год=1973|часть=Разработка и внедрение радиозащитных открытых очков |место=Москва|издательство=ВЦНИИОТ ВЦСПС|страницы=185-189|страниц=286|серия=материалы всесоюзного совещания|тираж=3000 |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731670742&archive=&start_from=&ucat=&}}</ref> <ref name="ТР-ТС">{{Книга|ссылка=https://www.novotest.ru/tr-ts/019-2011/tr-ts-019-2011.pdf|автор=Российская Федерация (Министерство здравоохранения и социального развития).|заглавие=Технический Регламент Таможенного Союза ТР ТС 019/2011 О безопасности средств индивидуальной защиты|ответственный=утв. Решением Комиссии Таможенного Cоюза от 9 декабря 2011 г. N 878|год=2011|место=Москва|страниц=167}}</ref> <ref name="Денисенко-1981">{{Книга|автор=Денисенко О.Н., Плиско Т.А., Безрукова А.А., Фомина Н.И.|заглавие=Технический прогресс и охрана труда|ответственный=Цуцков М.Е. (ред.)|год=1981|часть=К разработке индивидуальной защиты глаз от излучения СВЧ|место=Москва|издательство=Профиздат|страницы=42-43|страниц=148|серия=сборник научных работ институтов охраны труда ВЦСПС|тираж=5000}}</ref> <ref name="Чистик-1969">{{статья|автор=Чистик И.Я.|заглавие= Защитные очки для подземных рабочих угольных шахт|автор издания=Государственный Комитет по надзору за безопасным ведением работ в промышленности и горному надзору при Совете Министров СССР|издание=Безопасность труда в промышленности|ссылка=https://btpnadzor.ru/vypuski/1969/6 |место=Москва|издательство=|год=1969|номер=6|страницы=10-11|issn=}} ISSN 0409-2961</ref> <ref name="Луговая-2014">{{Статья|ссылка= http://lib.rgotups.ru/JournalsContent2014/SpravochnikSpecialistapoOhraneTruda_05.pdf|автор=Луговая Е.П.|заглавие=Правильный подбор защитных очков для предотвращения травм органов зрения|год=2014|место=Москва|издание=Справочник специалиста по охране труда|издательство=ЗАО "МЦФЭР"|месяц=5|номер=5|страницы=42-50|issn=}} ISSN 1727-6608</ref> <ref name="Противогаз-глаза">{{Статья|ссылка=https://cyberleninka.ru/article/n/himicheskie-porazheniya-glaz-ih-profilaktika-i-lechenie-obzor |автор=Каплан Ю.Д. |заглавие=Химические поражения глаз, их профилактика и лечение (обзор)|год=1942|издание=Гигиена и санитария|месяц=2|номер=1-2|страницы=40-46|issn=|}} ISSN 0016-9900</ref> <ref name="Шафранова-1937-1">{{Книга|автор=Шафранова А.С.|заглавие=Индивидуальная защита глаз рабочего на производстве|ответственный=ВЦСПС, Московский научно-исследовательский институт охраны труда|год=1937|часть=Предисловие; 1. Защита глаз на производстве|место=Москва|издательство=Профиздат|страницы=4; 7-8|страниц=48|тираж=15300|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1738063241&archive=&start_from=&ucat=&}} [https://files.library.by/dl/files/СИЗ%20глаз%201937%20%2048%20с.pdf PDF] Цитаты: "ФЗМК и общественные инспектора по охране труда должны взять под особый контроль всю систему выписки и назначения рабочим очков и других приспособлений. Очень часто эти назначения производятся формально-бюрократически, неправильно, не по глазам рабочего, что вместо пользы даёт только вред. В этих случаях рабочие отказываются носить выданные очки и по существу работают без защитных приспособлений. Защитные приспособления должны помогать рабочим, а не стеснять их, не мешать работе." с. 4; "'''Почему же рабочие так часто отказываются от ношения защитных очков?''' Всякий предмет, надеваемый на лицо человека, так или иначе стесняет его; и обычно, чем лучшую защиту дают те или иные очки, тем больше неудобств они причиняют. Понятно, что рабочий, уже привыкший работать без очков, возражает против них, так как ему приходится приспосабливаться к новым условиям и '''он боится снижения уже достигнутой производительности труда.''' " с. 7-8.</ref> <ref name="Шафранова-1937-4">{{Книга|автор=Шафранова А.С.|заглавие=Индивидуальная защита глаз рабочего на производстве|ответственный=ВЦСПС, Московский научно-исследовательский институт охраны труда|год=1937|часть=4. Защита глаз от пыли|место=Москва|издательство=Профиздат|страницы=14; 23-20|страниц=48|тираж=15300|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1738063241&archive=&start_from=&ucat=&}} [https://files.library.by/dl/files/СИЗ%20глаз%201937%20%2048%20с.pdf PDF]</ref> <ref name="Шафранова-1937-7">{{Книга|автор=Шафранова А.С.|заглавие=Индивидуальная защита глаз рабочего на производстве|ответственный=ВЦСПС, Московский научно-исследовательский институт охраны труда|год=1937|часть=7. Свабжение очками, правила применения и хранения их|место=Москва|издательство=Профиздат|страницы=44-48|страниц=48|тираж=15300|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1738063241&archive=&start_from=&ucat=&}} [https://files.library.by/dl/files/СИЗ%20глаз%201937%20%2048%20с.pdf PDF]</ref> <ref name="Бачанац-1997">{{Статья|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1748444042&archive=&start_from=&ucat=&|автор=Бачанац М.|заглавие=Профилактика офтальмокониоза у рабочих ФВК Кралево|год=1997|место=Москва|издание=Медицина труда и промышленная экология|издательство=НИИ медицины труда РАМН|месяц=4|номер=4|страницы=37-38|issn=}} ISSN 1026-9428</ref> <ref name="Очки-ГОСТ">{{статья|автор=И.М. Найман, А.В. Рославцев.|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1751206333&archive=&start_from=&ucat=& |заглавие= О государственном стандарте на средства индивидуальной защиты глаз |издание=Гигиена труда и профессиональные заболевания |издательство=НИИ медицины труда РАМН |год=1960 |номер=5|месяц=5 |issn=|страницы=56-58 }} ISSN 0016-9919</ref> <ref name="ГОСТ-очки-253">{{Книга|автор=ОАО «Всероссийский научно-исследовательский институт сертификации».|заглавие=ГОСТ 12.4.253-2013. Средства индивидуальном защиты глаз. Общие технические требования|год=2019|место=Москва|издательство=Стандартинформ|страниц=39|серия=ЕН 166-2002|тираж=1}} [https://meganorm.ru/Data2/1/4293774/4293774119.pdf PDF]</ref> <ref name="ГОСТ-очки-309">{{Книга|ссылка=https://meganorm.ru/Index2/1/4293748/4293748660.htm |автор=ОАО «Всероссийский научно-исследовательский институт сертификации»|заглавие=ГОСТ 12.4.309.2-2016. Средства индивидуальной защиты глаз. Методы испытаний оптических и неоптических параметров|год=2017|место=Москва|издательство=Стандартинформ|страниц=51|серия=EN 167:2002, EN 168:2002|тираж=30}} [https://meganorm.ru/Data2/1/4293748/4293748660.pdf PDF]</ref> <ref name="шахты-1969">{{Книга|автор=Чистик Иван Яковлевич.|заглавие=Защитные очки в профилактике повреждений глаз у подземных рабочих угольных шахт. Диссертация на соискание учёной степени кандидата медицинских наук|ответственный=Р.А. Гундорова, А.В. Рославцев (науч. руковод.)|год=1969|часть=2. Индивидуальные средства защиты глаз у подземных рабочих, в: Комплексные мероприятия, направленные на снижение повреждений глаз у подземных рабочих.|место=Москва|издательство=Московский НИИ глазных болезней им. Гельмгольца|страницы=119-138|страниц=211}}</ref> <ref name="Полоний-1980">{{Книга|автор=Н.Б. Борисов, [[:w:ru:Ильин, Леонид Андреевич|Л.А. Ильин]], У.Я. Маргулис, Г.М. Пархоменко, В.Т. Хрущ.|заглавие=Радиационная безопасность при работе с полонием-210|ответственный=И.В. Петрянов ред|год=1980|часть=7. Средства индивидуальной защиты, в: Глава 6. Гигиена труда при работе с полонием|место=Москва|издательство=Атомиздат|страницы=172-180|страниц=262|тираж=1300}}</ref> <ref name="МТПИЗЧ-21-1980">{{Книга|автор=Л.С. Урмахер, Л.И. Лурье, А.Н. Карцев.|заглавие=Медико-технические проблемы индивидуальной защиты человека|ответственный=В.С. Кощеев ред|год=1980|часть=К разработке нового государственного стандарта на метод определения остроты зрения при использовании средств индивидуальной защиты|издание=Выпуск 21|место=Москва|издательство=Институт биофизики|страницы=97-104|страниц=180|серия=сборник научных трудов}}</ref> <ref name="Голубева-1975">{{Книга|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731671835&archive=&start_from=&ucat=& |автор=Голубева И.А.|заглавие=Проблемы индивидуальной защиты человека. Часть 2|ответственный=[[:w:ru:Городинский, Семён Михайлович|С.М. Городинский]] (ред.)|год=1975|часть= Вопросы физиолого-гигиенического нормирования оптико-технических характеристик средств индивидуальной защиты |место=Москва|издательство=ВНИИ медицинской и медико-технической информации|страницы=38-58|страниц=104|серия=научный обзор|тираж=1500}}</ref> <ref name="очки-США">{{Книга|ссылка=https://www.govinfo.gov/content/pkg/CFR-2009-title29-vol5/pdf/CFR-2009-title29-vol5-sec1910-133.pdf|автор=US OSHA|заглавие=OSHA Standard 29 CFR 1910.133 Eye and face protection|год=2009|язык=en|место=Washington, DC|издательство=Occupational Safety and Health Administration}}</ref> <ref name="очки-ANSI">{{Книга|ссылка=https://safetyequipment.org/wp-content/uploads/2022/12/Eye-and-Face-Selection-Guide-tool.pdf|автор=Z87 Committee on Safety Standards for Eye Protection, International Safety Equipment Association.|заглавие=ANSI/ISEA Z87.1-2020. Occupational and Educational Personal Eye and Face Protection Devices|ответственный=American National Standards Institute|год=2020|часть=Annex J. Eye and Face Selection Guide (informative)|язык=en|место=Arlington, Virginia|allpages=60}}</ref> <ref name="Антропометрия">{{Статья|автор=Zhuang Z., Bradtmiller B., & Shaffer R.E.|заглавие=New respirator fit test panels representing the current U.S. civilian work force|год=2007|язык=en|автор издания=American Industrial Hygiene Association and ACGIH|издание=Occupational and Environmental Hygiene|издательство=Taylor & Francis|месяц=9|выпуск=9|pages=647–659|volume=4|issn=|doi=10.1080/15459620701497538|pmid=}} ISSN 1545-9624, {{PMID|17613722}}, публикации по теме [https://www.cdc.gov/niosh/docket/archive/pdfs/niosh-036/0036-062607-zhuang_pres.pdf 1] [https://nap.nationalacademies.org/read/11815/chapter/1#xii 2]</ref> <ref name="Канада-глаза+">{{Книга|ссылка=https://www.wscc.nt.ca/documents/personal-protective-equipment-eye-and-face-protection |автор=Workers’ Safety & Compensation Commission|заглавие=Eye and face protection|ответственный=Canadian Centre for Occupational Health and Safety (CCOHS)|год=2015|язык=en|место=Yellowknife|издательство=WSCC|allpages=20|серия=Code of Practice - Personal Protective Equipment}} [https://www.wscc.nt.ca/sites/default/files/documents/PPE%20Eye%20and%20Face%20Protection%20Code%20of%20Practice%2C%20May%2031%2C%202016%20-%20%20EN%20-%20NT.pdf ''PDF'']</ref> <ref name="Шафранова-1937">{{Книга|автор=Шафранова А.С.|заглавие=Индивидуальная защита глаз рабочего на производстве|ответственный=ВЦСПС, Московский научно-исследовательский институт охраны труда|год=1937|часть=3. Защита глаз от отлетающих твёрдых частиц|место=Москва|издательство=Профиздат|страницы=14; 23-24|страниц=48|тираж=15300|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1738063241&archive=&start_from=&ucat=&}} [https://files.library.by/dl/files/СИЗ%20глаз%201937%20%2048%20с.pdf PDF]</ref> <ref name="очки-BS">{{Книга|ссылка=https://middleware.accord.bsigroup.com/pdf-preview?path=Preview%2F000000000019994460.pdf&inline=true&_gl=1*2nj6h*_gcl_au*MTIyOTAwODgyNS4xNzMwOTk0NTc4*_ga*NTMwMTEwNjUxLjE3MzA5OTQ1Nzg.*_ga_RWDQ3VY9NQ*MTczMDk5NDU3Ny4xLjEuMTczMDk5NjQ3My4wLjAuMA..|автор=Technical Committee PH/2 Eye protection|заглавие=BS 7028:1999. Eye protection for industrial and other uses. Guidance on selection, use and maintenance|год=1999|язык=en|издание=2nd ed|место=London|издательство=British Standards Institution|allpages=28|серия=13.340.20 Head protective equipment|isbn=0 580 33047 8}}</ref> <ref name="Канада-глаза">{{Книга|автор=Canadian Standards Association.|заглавие=CSA Z94.3.1, Guideline for selection, use, and care of eye and face protectors|год=2016|язык=en|издание=2nd ed|место=Toronto, Ontario|издательство=CSA Group|allpages=31}} '''Копия''' рекомендаций стандарта по выбору СИЗ глаз и лица есть в Правилах по охране труда {{Книга|ссылка= https://www.wscc.nt.ca/sites/default/files/documents/PPE%20Eye%20and%20Face%20Protection%20Code%20of%20Practice%2C%20May%2031%2C%202016%20-%20%20EN%20-%20NT.pdf|автор=Chief Safety Officer, Workers’ Safety and Compensation Commission|заглавие=Eye and Face Protection|год=2015|часть=5.5 Classes of protectors|язык=en|место=Yellowknife - Inuvik; Northwest Territories & Nunavut|издательство=WSCC|pages=12-13|allpages=20|серия=Personal Protective Equipment - Codes of Practice}}</ref> <ref name="очки-AS">{{Книга|автор=Committee SF-006.|заглавие=AS/NZS 1336:2014. Eye and face protection - Guidelines|год=2014|язык=en|издание=5th ed|место=Sydney, New South Wales|издательство=Standards Australia|allpages=35|серия=13.340.20 Head protective equipment|isbn=978 1 74342 770 5}}</ref> <ref name="очки-ISO">{{Книга|ссылка=https://cdn.standards.iteh.ai/samples/74267/d4ab512a32124c7d8a7bf37274537fcf/ISO-19734-2021.pdf|автор=Technical Committee ISO/TC 94/SC 6|заглавие=ISO 19734:2021. Eye and face protection — Guidance on selection, use and maintenance|год=2021|язык=en|место=Geneva, Switzerland|издательство=International Organization for Standardization|allpages=50|серия=13.340.20 Head protective equipment}}</ref> <ref name="очки-ISO-">{{Книга|ссылка=https://www.iso.org/standard/84835.html|автор=Technical Committee TC 94/SC 6|заглавие=ISO 16321-1:2021/Amd.1:2024. Eye and face protection for occupational use Part 1: General requirements|место=Geneva, Switzerland|издательство=International Organization for Standardization|allpages=14|серия=ICS 13.340.20}}</ref> <ref name="очки-Канада">{{Книга |автор=Chou B.R. et al (Technical Committee on Eye and Face Protection) |заглавие=CSA standard Z94.3-15. Eye and face protectors |ответственный=Canadian Standards Association |год=2015 |язык=en |издание=8th edition |место=Toronto (Ontario, Canada) |издательство=CSA Group |allpages=91 |isbn=978-1-77139-938-8}}</ref> <ref name="глаза-стат-AU">{{Книга|автор=Tim Driscoll, Louise Flood and James Harrison.|заглавие=Work-related eye injuries in Australia|ответственный=Australian Safety and Compensation Council|год=2008|часть=3.10. Personal protective equipment|язык=en|издательство=Australian Government|pages=18-19|allpages=39|isbn=978-0-642-32756-7|ссылка=https://www.safeworkaustralia.gov.au/system/files/documents/1702/workrelatedeyeinjuriesaustralia_2008_pdf.pdf}}</ref> <ref name="БТП-09-1971">{{статья|автор=Г. Терещенко, А. Захаров, Глушаков.|заглавие= Каска с щитком для защиты глаз |ссылка= |автор издания=Государственный Комитет по надзору за безопасным ведением работ в промышленности и горному надзору при Совете Министров СССР|издание=Безопасность труда в промышленности|место=Москва|издательство=ЗАО "Алмаз-Пресс"|год=1971|номер=9|страницы=51|issn=}} ISSN 0409-2961</ref> <ref name="глаза-стат-Ch">{{Статья|ссылка=https://injuryprevention.bmj.com/content/27/6/521|автор=Fei Sun, Yongdong Zhou, Liqun Dong, Haofang Qin.|заглавие=Relationship between the use and type of eye protection and work-related corneal and conjunctival foreign body injuries|год=2021|язык=en|автор издания=Society for Advancement of Violence and Injury Research (SAVIR)|издание=Injury Prevention|издательство=BMJ Publishing Group Ltd|выпуск=6|pages=521-526|volume=27|issn=|doi=10.1136/injuryprev-2020-043958|pmid=}} ISSN 1353-8047, {{PMID|33443032}}</ref> <ref name="глаза-стат-">{{Статья|ссылка=https://injepijournal.biomedcentral.com/articles/10.1186/s40621-020-00280-z|автор=T. AlMahmoud, I. Elkonaisi, M. Grivna, F. Abu-Zidan.|заглавие=Personal protective eyewear usage among industrial workers in small-scale enterprises|год=2020|язык=en|издание=Injury Epidemiology|издательство=BioMed Central Ltd (Springer Nature)|pages=54|volume=7|issn=|doi=10.1186/s40621-020-00280-z|pmid=|pmc=}} ISSN 2197-1714, PMC PMC7507252, {{PMID|32958044}}</ref> <ref name="глаза-стат-Ca">{{Статья|автор=Helena Zakrzewski, Helen Chung, Emi Sanders, Christopher Hanson, Bryce Ford.|заглавие=Evaluation of occupational ocular trauma: are we doing enough to promote eye safety in the workplace?|год=2017|язык=en|автор издания=Canadian Ophthalmological Society|издание=Canadian Journal of Ophthalmology|месяц=8|выпуск=4|pages=338-342|volume=52|issn=|doi=10.1016/j.jcjo.2016.11.034}} ISSN 0008-4182</ref> <ref name="глаза-стат-US">{{Книга|ссылка=https://www.elcosh.org/document/1616/d000152/Eye+Protection+in+the+Workplace.html |автор=California Occupational Safety and Health Administration|заглавие=Eye protection in the workplace|ответственный=U.S. Department of Labor|год=1993|язык=en|место=California|allpages=2}} [https://www.elcosh.org/record/document/1616/d000152.pdf ''PDF'']</ref> <ref name="Очки-штрафы">{{Статья|ссылка=https://ohsonline.com/Articles/2024/11/19/Beyond-the-Goggles-Navigating-Eye-and-Face-Protection.aspx?admgarea=ht.PPE|автор=Cindy Pauley.|заглавие=Beyond the Goggles: Navigating Eye and Face Protection|год=2024|язык=en|место=Los Angeles, California|издание=Occupational Health and Safety|издательство=1105 Media Inc.|тип=журнал|месяц=11|число=19|}} ISSN 0362-4064</ref> <ref name="Гаевая-1972">{{Книга|автор=Гаевая Л.А.|заглавие=Средства индивидуальной защиты глаз и лица на производстве|год=1972|издание=Всесоюзный центральный научно-исследовательский институт охраны труда (ВЦНИИОТ)|место=Москва|издательство=ВЦНИИОТ ВЦСПС|страниц=124|серия=Справочник|тираж=5000}}</ref> <ref name="Профилактика-глаза-2018">{{Книга|ссылка=https://www.geotar.ru/lots/NF0008024.html|автор=Л.К. Мошетова, С.А. Кочергин, И.Б. Максимов, А.В. Степанов|заглавие=Офтальмология|ответственный=под ред. С.Э. Аветисова, Е.А. Егорова, Л.К. Мошетовой, В.В. Нероева, Х.П. Тахчиди|год=2018|часть=Профилактика (в: Раздел III. Клинические рекомендации по заболеваниям и состояниям; Глава 36. Травмы глаза и его придаточного аппарата)|издание=2-е изд|место=Москва|издательство=ГЭОТАР-Медиа|страницы=866, 874|страниц=904|серия=Национальные руководства|isbn=978-5-9704-4449-8|тираж=3000}}</ref> <ref name="Лазеры-рекоменд">{{Книга|ссылка=https://meganorm.ru/mega_doc/norm/gost_gosudarstvennyj-standart/13/gost_EN_207-2021_mezhgosudarstvennyy_standart_sistema.html|автор=ООО "МОНИТОРИНГ"|заглавие=ГОСТ EN 207-2021. ССБТ Средства индивидуальной защиты глаз. очки для защиты от лазерного излучения. Общие технические требования. Методы испытаний|год=2022|часть=Приложение B. Рекомендации по применению очков для защиты от лазерного излучения|место=Москва|издательство=ФГУП "Стандартинформ"|страниц=29}}</ref> <ref name="Лазеры-настройка-рекоменд">{{Книга|ссылка=https://files.stroyinf.ru/Data2/1/4293767/4293767899.pdf?ysclid=m8lj9hx7fh388979709|автор=ФГУП «ВНИИМ им. Д.И. Менделеева»|заглавие=ГOCT EN 208-2014. ССБТ Средства защиты глаз при работе по настройке лазеров и лазерных систем. Общие технические требования, методы испытаний, маркировка|год=2015|часть=Приложение В (справочное). Рекомендации по применению очков для защиты от лазерного излучения при юстировке лазеров и лазерных устройств|место=Москва|издательство=ФГУП "Стандартинформ"|страницы=12-14|страниц=19}}</ref> <ref name="Пальцев-1976">{{Книга |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1751551910&archive=&start_from=&ucat=& |автор=Пальцев Ю.Н., Кацуба В.А., Максимова Л.И., Солонников А.Н, Каюмов Х.М. |заглавие=Всесоюзная конференция "Пути повышения качества и эффективности средств индивидуальной защиты и совершенствования методов их оценки" |ответственный=Семёнов А.П., Городинский С.М., Романова И.Г., Цуцков М.Е., Гуда В.А., Леоничева В.Д. (редколлегия) |год=1976 |часть=Гигиенические требования к средствам индивидуальной защиты от лазерных излучений |издание=Всесоюзный центральный совет профсоюзов (ВЦСПС) |место=Москва |издательство=Государственный Комитет Совета Министров СССР по науке и технике |страницы=126-128 |страниц=179 |серия=Тезисы докладов, г. Тбилиси, 13-15 октября 1976 г. |тираж=700}}</ref> <ref name="инспектор-2022-l">Table III:6-1. Wavelengths of '''most common''' lasers. In: US OSHA. [https://www.osha.gov/otm/section-3-health-hazards/chapter-6 Laser Hazards]. OSHA Technical Manual (OTM) Section III: Chapter 6 ''(англ.).'' www.osha.gov. Occupational Safety and Health Administration (6 июля 2022)</ref> <ref name="СИЗОС-1973-лазер">{{Книга|автор=Азатьян А.Д.|заглавие=Пути совершенствования средств индивидуальной защиты работающих на производстве|ответственный=Цуцков М.Е., Городинский С.М., Смирнов В.Ф|год=1973|часть=Очки для защиты от лазерного излучения. Требования, перспективы развития и производства |место=Москва|издательство=ВЦНИИОТ ВЦСПС |страницы=165—170 |страниц=286|серия=материалы всесоюзного совещания|тираж=3000 |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731670155&archive=&start_from=&ucat=& }}</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] mtan40h3om3yynfxfq919ca9oh82bvf Средства индивидуальной защиты (обзорная лекция)/СИЗ головы 0 35744 270422 268994 2026-10-27T07:05:52Z Jcb 79968 270422 wikitext text/x-wiki [[File:Mijnwerker 1947 02-00-1947 18935.jpg|thumb|right|300px|Шахтёр в каске]] '''Средства индивидуальной защиты головы''' могут использоваться при опасности её механического травмирования, при повышенной или пониженной температуре воздуха, риске воздействия кислот, щелочей, расплавленного металла, поражения электрическим током, и опасном воздействии других производственных факторов<ref name="МОТ-каски" />. В отношении защиты от ударов, существуют 4 вида СИЗ головы: # Защитные каскетки, для защиты от ударов головой о неподвижные предметы. # Каски защитные, предназначены для защиты от ударов только сверху. # Высокоэффективные защитные каски, для защиты от ударов сверху, сбоку, сзади и спереди. # Новые каски, уменьшающие самое опасное (угловое) ускорение головы при ударах. === Научные исследования === Экспериментальное изучение последствий ударов по голове позволило сформулировать требования к способности касок ослаблять вертикальные удары падающих на голову предметов<ref name="Громов-1976" />. Исследования [[:w:ru:Государственный Макеевский научно-исследовательский институт по безопасности работ в горной промышленности|МакНИИ]] показали, что при боковом ударе каски не обеспечивают требуемую защиту, и что для поглощения энергии сильных и боковых ударов желательно использовать дополнительную демпфирующую прокладку - помимо обычной подвески<ref name="СИЗ-1973-5" />. Для этого может использоваться, например, прокладка из наполненных воздухом "пузырьков"<ref name="Каски+" />, или пластиковых сотовых ячеек<ref name="Каски++" />. В Южной Корее сравнивали смертность и тяжесть черепно-мозговых травм у рабочих, пострадавших при падениях в 2010—2012 гг., всего 1298 пациентов. Каски использовали 45 % (584 рабочих). Среди упавших без каски доля черепно-мозговых травм была заметно выше (8,7 % и 4,6 %). При учёте высоты падения, и высоте 4 м и выше, каски никакого эффекта не давали. Доля смертельных исходов существенно не отличалась (2,9 % без каски, 3,1 % в каске) при любой высоте падения. Среди не применявших каски доля прошедших обучение охране труда была вдвое меньше (35,2 и 73,5 %)<ref name="Коррея-каски-2016" />. По данным<ref name="новые-каски" /> риск сильного сотрясения мозга заметно возрастает в тех случаях, когда удар по каске не центральный (вызывающий лишь линейные ускорение), а такой, который вызывает одновременно и поворот. При ударах, вызывающих чисто линейное ускорение, травмирование часто происходит лишь тогда, когда удар настолько сильный, что происходит разрушение костей. Мозг, как вода, практически несжимаем, и при линейных ускорениях взаимного перемещения его частей друг относительно друга не происходит. В результате такое воздействие часто не приводит к серьёзным травмам. Если возникает и [[:w:ru:|угловое ускорение]], то ситуация резко изменяется. Вращательное движение головы стремиться увлечь за собой периферийные части головного мозга, а они, и центральная часть мозга, по инерции стремится остаться неподвижными. Части мозга стремятся сместиться и относительно неровной внутренней поверхности черепа, и друг относительно друга, что значительно увеличивает опасность. Стремление сместиться создаёт касательные напряжения, которые создают риск разрывов тканей, нервов и сосудов, и соответственно опасность диффузного [[:w:ru:Аксон|аксонального]] повреждения центральной нервной системы<ref name="Коновалов-2" />. Обычная подвеска касок не уменьшает передачу вращательного движения на голову, что увеличивает риск<ref name="вращ-гол-24" />. Разработаны новые СИЗ головы: если удар стремиться вращать каску, подвеска позволяет ей повернутся относительно головы (в некоторой степени), что ослабляет передаваемые голове «вращающие» силы (подобно тому, как линейное смещение оболочки каски относительно подвески ослабляет прямой удар). На всех [[:w:ru:Рабочее место|рабочих местах]] случаи травмирования падающими сверху предметами составляют не самую большую долю, чаще удары по голове происходят при падениях и спотыканиях, ударах головы о предметы, а также из-за дорожно-транспортных происшествий. В [[:w:ru:Имперский колледж Лондона|Имперском колледже]] смоделировали удары головы при спотыканиях, падениях вперёд и назад, более 1600 возможных случаев<ref name="Каски-моделирование" />. Результаты показали, что обычные каски (без защиты от боковых ударов) нередко неспособны не только смягчить удар, но даже не закрывают место удара на поверхности головы. Последнее согласуется с результатами, полученными в Европейском Союзе: в строительной отрасли за период 2014-2018 гг. большинство травм головы было связано с падением работников, в том числе и при отсутствии перепада высоты (спотыкание о лежащие на полу кабели и т.п.). 49,1% случаев черепно-мозговых травм в Швеции (из 249) и 61,4% в ФРГ (из 11428) приводили к поверхностным ранам, т.е. удар приходился на не защищённую каской часть головы<ref name="ЕС-стат-21" />. Исследования показали, что летом, в солнечные дни, температура воздуха под каской может быть значительно выше температуры окружающего воздуха. Это ухудшает самочувствие работников, снижает производительность<ref name="Каски-перегрев" /> и качество труда, повышает риск [[:w:ru:Тепловой удар|теплового удара]]. Систематичное использование касок может стать причиной головной боли у части работников<ref name="Каски-Канада-боль" />. [[File:Mine helmet 2.jpg|thumb|right|300px|Такой амортизатор смягчает лишь удары сверху]] === Требования к СИЗ === Для использования работниками в США каски должны соответствовать требованиям<ref name="Каски-США-" />. Они включают в себя СИЗ с защитой от удара только сверху, и с защитой от ударов сверху и сбоку. По электроизолирующим свойствам различают не изолирующие СИЗ и два вида изолирующих, предназначенных для работы с электроустановками с низким и высоким напряжением. В Канаде в одном стандарте собраны и требования к СИЗ головы, и рекомендации по их выбору и применению<ref name="Каски-Канада" />, документ схож с американским<ref name="Каски-США-" />. Последнее издание стандарта Австралии дополнено требованиями к шлемам "тип 4", которые должны защищать и от ударов сбоку и сзади<ref name="Каски-Австралия" />. Стандарт Европейского Союза 2012 г., и гармонизированный с ним ГОСТ РФ<ref name="Каски-ЕС+РФ" /> предусматривает только защиту от ударов сверху. В ЕС также есть стандарты предусматривающие защиту от ударов сбоку (для работы на высоте<ref name="Каски-ЕС-2" />, и с улучшенной защитой<ref name="Каски-ЕС-1" /><ref name="Каски-ГОСТ-2" />). Но в последнем издании стандарта ЕС появился "тип 2": каски, защищающие от слабых ударов спереди, сбоку и сзади<ref name="Каски-ЕС-5" />. Также опубликовано второе издание стандарта<ref name="Каски-ЕС-э" /> с требованиями к каскам для электриков. Он предусматривает 4 вида касок, которые испытывают при разных напряжениях (от 2,5 до 40 кВ) и они могут использоваться при работе с оборудованием при напряжении, соответственно, от 0,5 до 17 кВ. Поскольку не центральные удары, сопровождающиеся как линейным, так и вращательным движением, могут быть более опасны, в ЕС разработан стандарт для испытаний касок для оценки опасности при таких ударах<ref name="Каски-ЕС-3" />, исключительно схожий со стандартом<ref name="Каски-US" />. ГОСТ<ref name="Каски-ЕС+РФ" /> включает требование: каска должна ослаблять чисто вертикальный, центральный удар груза 5 кг, падающего с высоты 1 метр, до 5 000 ньютон (в США 3,6 кг; 1,52 м, 4450 Н<ref name="Каски-США-" />). Таким образом ни в одной из стран до 2022 г. не было никаких требований к СИЗ головы, учитывающие их способность уменьшать передачу вращательного движения - хотя давно известно, что именно оно представляет значительную опасность во многих случаях. Требования к работодателю по выбору именно таких касок - отсутствуют. Поэтому, и из-за большей стоимости, новые модели используются нечасто. В части требований к защите от ударов необходимо учесть, что у касок обычной конструкции (внешняя прочная оболочка и амортизатор внутри) есть ограничения. При ограниченном максимальном допустимом усилии, передаваемом голове во время удара, поглощаемая амортизатором энергия зависит от того, насколько он может деформироваться, то есть от расстояния от прочного корпуса до головы. Для поглощения сильных ударов его дистанцию необходимо увеличить. А при сильном возрастании каска становится такой громоздкой и неудобной, что ей не будут пользоваться вообще. Поэтому и изготовители, и разработчики требований к СИЗ идут на компромисс - но не предупреждают об этом потребителя в полной мере. Так, новые требования к каскам для мотоциклистов<ref name="Каски-ООН" /> предусматривают увеличение скорости удара при испытании до 8,5 м/с. В то же время в городских условиях допускается движение со скоростью 60 км/ч (16,7 м/с). При такой скорости энергия удара будет в 3,8 раз больше, чем при сертификации - но покупателям заявляют, что лишь сертифицированные СИЗ "обеспечивают адекватную защиту". Положительным свойством последней редакции стандарта стало испытание при ударах, приводящих голову во вращение. [[File:Blue Grass Chemical Agent-Destruction Pilot Plant Control and Support Building (9969535664).jpg|thumb|right|300px|Каска с полями - на химическом предприятии]] === Требования и рекомендации по выбору и использованию === В Канаде в одном стандарте собраны и требования к СИЗ головы, и рекомендации по их выбору и применению<ref name="Каски-Канада" />. В случае, если риски разных ударов не оценивались совсем, при работе на стройках, и во всех остальных случаях (кроме тех, когда работодатель показал, что опасность боковых ударов незначительна) необходимо использовать каски с защитой от боковых ударов. СИЗ Опубликованы советы специалистов<ref name="Каски-Канада-уч" />. В соответствии с Директивой ЕС<ref name="Директива-ЕС-СИЗ" /><ref name="Каски-EU" /> все проблемы, связанные с оценкой риска, выбором соответствующего риску средства защиты головы, а также обеспечение совместимости с другими СИЗ (органов дыхания, слуха и т.п.) целиком возлагаются на работодателя. Каски должны приобретаться им за свой счёт и бесплатно выдаваться работникам. В Директиве в конце приведён перечень видов работ и областей деятельности, где могут требоваться разные СИЗ, включая СИЗ головы. В США требования по охране труда в разных отраслях включают в себя использование СИЗ головы<ref name="Каски-США" />. Работодатели должны использовать лишь сертифицированные СИЗ. Также указано, что они должны выполнять требования стандарта [[:w:ru:Американский национальный институт стандартов|''ANSI'']], где есть некоторые советы по использованию этих СИЗ<ref name="Каски-США-" />. Учтя статистические данные за 2020 г. Департамент условий и охраны труда (''[[:w:OSHA|OSHA]]'', 6% несчастных случаев без смертельного исхода из-за травм головы при ударах, падениях, спотыканиях и т.п.) пришёл к выводу о необходимости перехода от касок к шлемам во многих отраслях. Решение пока не воплотилось в требования закона, а является рекомендацией - вместе с программой действий по: оценке риска травм головы, выбора, применения и ухода за СИЗ головы. Новые шлемы изготавливают не из пластика, а [[:w:ru:Композитный материал#Полимерные композиционные материалы (ПКМ)|композиционных материалов]], они легче и лучше защищают от ударов, особенно боковых<ref name="шлемы-2023" />. С другой стороны, среди работающих в строительстве шлемы многим не нравятся, особенно опытным рабочим (внешний вид, неудобность)<ref name="шлемы-2021" />. Правительство Гонконга требует, чтобы работодатели учитывали возможность боковых ударов при выборе касок, и чтобы на стройках использовали именно шлемы, обеспечивающие защиту и от таких ударов<ref name="Каски-Гонк" />. Значительное внимание к сбережению здоровья молодёжи школьного возраста побудило американских специалистов внести изменения в требования к СИЗ головы. Несмотря на отсутствие чётких и однозначных критериев опасности вращательного движения, отсутствие общего мнения специалистов о границе опасности углового ускорения - в стандарте<ref name="Каски-2025" />, как и в<ref name="Каски-ООН" /> впервые в мире предусмотрено измерение углового ускорения при ударе, вызывающем вращение макета головы, и установлены требования к его ослаблению. === Результаты применения === Со ссылкой на Бюро трудовой статистики (''BLS'') сообщали, что при использовании 6 млн. касок в 2019 г. зарегистрировано 18 тыс. черепно-мозговых травм<ref name="новые-каски" />, что по данным [[:w:OSHA|OSHA]] от ударов падающих предметов погибает порядка тысячи рабочих (и 6 из 7 погибших не использовали каски)<ref name="Каски-не-используют" />. Разработаны рекомендации для выбора касок для строителей<ref name="Каски-выбор" />. В Великобритании менее чем за год зарегистрировано более 348 тыс. случаев оказания медицинской помощи работникам с черепно-мозговыми травмами; но опросы показывают, что примерно в половине случаев рабочие не сообщают о ударах по голове руководителям, и возможно, проблема гораздо серьёзнее, чем это показывает статистика<ref name="Каски-моделирование" />. [[File:F1 fireman helmet.jpg|thumb|right|300px|СИЗ головы пожарника, с выдвижным экраном для защиты глаз]] === Канадский опыт === Значительный рост регистрируемого травматизма головы работников<ref name="Каски-Канада-травмы-2" /> (порядка 3,7-8 раз)<ref name="Каски-Канада-травмы" /> побудил ассоциацию крупных строительных компаний добровольно и по собственной инициативе начать переход от касок к шлемам (защищающим и от боковых ударов). Аналогично, последняя редакция 2024 г. стандарта с требованиями к выбору СИЗ головы<ref name="Каски-Канада" /> обязывает использовать каски с защитой от боковых ударов (кроме случаев, когда работодатель покажет незначительность этой опасности). Однако канадские законодатели, в тех же самых условиях, изменили требования иначе - разрешив вообще не применять СИЗ головы в условиях, когда риск низкий<ref name="Каски-Канада-поправки" />. Причины такого парадоксального изменения две: работники из Индии, сикхи, не хотят отказываться от религиозного головного убора (тюрбана), что мешает их найму на стройки и т.п.; а специалистом известно, что каски - самый ненадёжный вид защиты головы от травм. В рекомендациях по профилактике травм головы отмечается, что значительная их доля происходит из-за падений споткнувшихся работников при отсутствии перепада высоты. Соответственно, рекомендуется обратить внимание на используемую обувь, на лежащие на полу провода и т.п., и лишь после этого (пункт № 7<ref name="Каски-Канада-советы" />) советуют использовать каски. Т.е. для снижения риска травм стараются в первую очередь уменьшить саму опасность, и лишь когда это сложно сделать - используют хотя и ненадёжные, но улучшенные СИЗ головы. == Примечания == {{примечания|refs= <ref name="МОТ-каски">{{Книга|ссылка=http://base.safework.ru/iloenc|ответственный =[https://miningwiki.ru/wiki/Ассоциация_СИЗ#Кадры Ю.Г. Сорокин] <small>(''руководитель Департамента условий и охраны труда, Минтруд РФ'')</small>; Жан-Виктор Груа <small>(''Директор Московского бюро МОТ'')</small>|заглавие=Энциклопедия по безопасности и охране труда|год=2001|часть=[http://base.safework.ru/iloenc?d&nd=857400343&prevDoc=857400343&spack=110LogLength%3D0%26LogNumDoc%3D857400038%26listid%3D010000000100%26listpos%3D3%26lsz%3D7%26nd%3D857400038%26nh%3D1%26 Средства защиты головы]. В: Том 1; Раздел [http://base.safework.ru/iloenc?d&nd=857400005&prevDoc=857000002 IV], Глава [http://base.safework.ru/iloenc?d&nd=857400038&prevDoc=857400346 31. Средства индивидуальной защиты] |автор=Изабель Балти и Ален Майер |ссылка часть=|издание=4-е изд|место=Москва|издательство=Международная организация труда; Министерство труда и социального развития РФ|страницы= |страниц=1278|серия= Охрана труда}}</ref> <ref name="Громов-1976">{{Книга |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1751551910&archive=&start_from=&ucat=& |автор=Громов А.П., Пырлина Н.П., Потапов В.И., Карцев А.Н., Салтыкова О.Ф., Корсаков С.А., Живодеров Н.Н., Дербоглав В.В., Проценков М.Г., Ковалевская Р.А. |заглавие=Всесоюзная конференция "Пути повышения качества и эффективности средств индивидуальной защиты и совершенствования методов их оценки" |ответственный=Семёнов А.П., Городинский С.М., Романова И.Г., Цуцков М.Е., Гуда В.А., Леоничева В.Д. (редколлегия) |год=1976 |часть=Биомеханическое обоснование требований к защитной каске |издание=Всесоюзный центральный совет профсоюзов (ВЦСПС) |место=Москва |издательство=Государственный Комитет Совета Министров СССР по науке и технике |страницы=116-119 |страниц=179 |серия=Тезисы докладов, г. Тбилиси, 13-15 октября 1976 г. |тираж=700}}</ref> <ref name="СИЗ-1973-5">{{Книга|автор=Трубников Е.Г. |заглавие=Пути совершенствования средств индивидуальной защиты работающих на производстве |ответственный=Цуцков М.Е., Городинский С.М., Смирнов В.Ф|год=1973|часть=Разработка и совершенствование средств защиты головы (каски)|место=Москва|издательство=ВЦНИИОТ ВЦСПС |страницы=56-59|страниц=286|серия=материалы всесоюзного совещания|тираж=3000 |ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1731670742&archive=&start_from=&ucat=&}}</ref> <ref name="Коррея-каски-2016">{{Статья|ссылка=https://www.researchgate.net/publication/309601350_Preventive_Effects_of_Safety_Helmets_on_Traumatic_Brain_Injury_after_Work-Related_Falls|автор=Sang Chul Kim, Young Sun Ro, Sang Do Shin, Joo Yeong Kim|заглавие=Preventive Effects of Safety Helmets on Traumatic Brain Injury after Work-Related Falls|год=2016|язык=en|место=Basel, Switzerland|издание=International Journal of Environmental Research and Public Health|издательство=MDPI (Multidisciplinary Digital Publishing Institute)|выпуск=12|pages=1063|volume=13|issn=|doi=10.3390/ijerph13111063|pmid=|pmc=}} ISSN 1661-7827, {{PMID|27801877}}, PMC PMC5129273.</ref> <ref name="новые-каски">''EHS Daily Advisor''. [https://ehsdailyadvisor.blr.com/resource/is-your-safety-helmet-protecting-against-dangerous-rotational-forces-2/ Is Your Safety Helmet Protecting Against Dangerous Rotational Forces?] <small>(англ.)</small>. ''ehsdailyadvisor.blr.com.'' Brentwood, TN: Business & Legal Resources (BLR) LLC. Дата обращения: 15 ноября 2024.</ref> <ref name="Коновалов-2">{{Книга|ссылка=https://vk.com/doc37102412_430448681?hash=9Z3yOg0sU44IJP6oGLfGFYblGy2rix0D9Un25z6diks&api=1&no_preview=1|автор=Потапов А.А., Лихтерман Л.Б., Касумова С.Ю., Чабулов А., Гайтур Э.И.|заглавие=Клиническое руководство по черепно-мозговой травме.|ответственный=Коновалов А.Н., Лихтерман Л.Б., Потапов А.А. ред.|год=2001|часть=Глава 20. Диффузные аксональные повреждения головного мозга|место=Москва|издательство=ИД «Энциклопедия интернешнл», «Антидор»|том=II. Острый период черепно-мозговой травмы: хирургия, анестезия, интенсивная терапия, клинические формы|страницы=426-428|страниц=675|isbn=5-900833-13-5}}</ref> <!-- Комментарий --> {{Cite web|url=https://ehsdailyadvisor.blr.com/resource/is-your-safety-helmet-protecting-against-dangerous-rotational-forces-2/|title=Is Your Safety Helmet Protecting Against Dangerous Rotational Forces?|lang=en|author=EHS Daily Advisor|website=ehsdailyadvisor.blr.com|location=Brentwood, TN|publisher=Business & Legal Resources (BLR) LLC|access-date=2024-11-15}} <ref name="шлемы-2023">{{Книга|ссылка=https://www.osha.gov/sites/default/files/publications/safety_helmet_shib.pdf|автор=US Occupational Safety and Health Administration|заглавие=Head Protection: Safety Helmets in the Workplace|год=2023|язык=en|издательство=U.S. Department of Labor|allpages=5|серия=Safety and Health Information Bulletin SHIB 3-6-2024}}</ref> <ref name="шлемы-2021">{{Статья|ссылка=https://digitalcommons.calpoly.edu/cgi/viewcontent.cgi?article=1542&context=cmsp|автор=Matthew R. Langbehn|заглавие=Workers Head Protection Preferences in Construction|год=2021|язык=en|автор издания=DigitalCommons@CalPoly|место=California, US|издание=Construction Management|издательство=California Polytechnic State University|pages=11}}</ref> <ref name="вращ-гол-24">{{Статья|ссылка=https://www.researchgate.net/publication/263935897_Why_Most_Traumatic_Brain_Injuries_are_Not_Caused_by_Linear_Acceleration_but_Skull_Fractures_are|автор=Svein Kleiven|заглавие=Why Most Traumatic Brain Injuries are Not Caused by Linear Acceleration but Skull Fractures are|год=2013|язык=en|издание=Frontiers in Bioengineering and Biotechnology|месяц=11|число=7|выпуск=15|pages=1-5|volume=1|issn=|doi=10.3389/fbioe.2013.00015|pmid=|pmc=}} ISSN 2296-4185, {{PMID|25022321}}, PMC PMC4090913.</ref> <ref name="Каски+">{{Статья|ссылка=https://pmc.ncbi.nlm.nih.gov/articles/PMC8006905/|автор=John Z. Wu, Christopher S. Pan, Mahmood Ronaghi, Bryan M. Wimer, Uwe Reischl|заглавие=Application of polyethylene air-bubble cushions to improve the shock absorption performance of Type I construction helmets for repeated impacts|год=2021|язык=en|место=New York|издание=Bio-medical materials and engineering|издательство=Pergamon Press|месяц=1|выпуск=1|pages=1-14|volume=32|issn=|doi=10.3233/BME-201132|pmid=|pmc=}} ISSN 0959-2989, {{PMID|33252060}}, PMC PMC8006905.</ref> <ref name="Каски-не-используют">{{Статья|ссылка=https://ohsonline.com/Articles/2021/06/01/Watch-for-Falling-Objects-PPE-to-Protect-You-on-the-Job-Site.aspx?Page=2|автор=David Ivey|заглавие=Watch for Falling Objects: PPE to Protect You on the Jobsite|год=2021|язык=en|место=Los Angeles, California|издание=Occupational Health and Safety|издательство=1105 Media Inc.|тип=журнал|месяц=6|число=1|issn=}} ISSN 0362-4064</ref> <ref name="Каски-выбор">{{Книга|ссылка=https://www.cpwr.com/wp-content/uploads/FS-Selecting_Head_Protection.pdf|автор=The Center for Construction Research and Training|заглавие=Selecting Head Protection for Construction Work|год=2024|язык=en|издание=2nd ed|allpages=10}}</ref> <!-- Комментарий --> "Каски++">{{Cite web|url=https://www.wbur.org/npr/1121903266/how-a-new-hard-hat-technology-can-protect-workers-better-from-concussion|title=How a new hard hat technology can protect workers better from concussion|lang=en|author=Jon Hamilton|website=WBUR wbur.org|subtitle=NPR News|date=2022-09-09|location=Boston, MA}} <ref name="Каски++">''Jon Hamilton.'' [https://www.wbur.org/npr/1121903266/how-a-new-hard-hat-technology-can-protect-workers-better-from-concussion How a new hard hat technology can protect workers better from concussion]. NPR News <small>(англ.)</small>. ''WBUR wbur.org'' Boston, MA. (9 сентября 2022). </ref> <ref name="Каски-моделирование">{{Статья|ссылка=https://www.researchgate.net/publication/368306335_Head_Impact_Location_Speed_and_Angle_from_Falls_and_Trips_in_the_Workplace|автор=Xiancheng Yu, Claire E. Baker & Mazdak Ghajari.|заглавие=Head Impact Location, Speed and Angle from Falls and Trips in the Workplace|год=2024|язык=en|автор издания=Biomedical Engineering Society.|издание=Annals of Biomedical Engineering|издательство=Springer Nature|месяц=10|выпуск=6|pages=687–2702|volume=52|issn=|doi=10.1007/s10439-023-03146-9|pmid=|pmc=}} ISSN 0090-6964, {{PMID|36745294}}, PMC PMC11402836.</ref> <ref name="Каски-Канада">{{Книга|автор=CSA.|заглавие=CSA Z94.1-15 (R2024) Industrial protective headwear - Performance, selection, care, and use|часть=5. Selection, care, and use of headwear|pages=13-19|год=2015|язык=en|издание=6th ed|место=Toronto, Ontario, Canada|издательство=Canadian Standards Association|allpages=56|серия=ICS Codes 13.340.20 Head protective equipment}}</ref> <ref name="Каски-ЕС+РФ">{{Книга|ссылка=https://meganorm.ru/Index/80/80718.htm |автор=Частное учреждение Федерации независимых профсоюзов "НИИОТ"|заглавие=ГОСТ EN 397-2020 ССБТ. Средства индивидуальной защиты головы. Каски защитные. Общие технические требования. Методы испытаний|год=2020|место=Москва|издательство=Стандартингформ|страниц=25|серия=[http://db.csstgc.com.cn/userfiles/4b146a65dc7d43558bc74a1d018e8d5d/files/teckSolution/2024/08/BS%20EN%20397-2012%206_6%206_7.pdf EN 397:2012+A1:2012]|тираж=1}} [https://meganorm.ru/Data/807/80718.pdf PDF]</ref> <ref name="Каски-ЕС-5">{{Книга |ссылка=https://standards.iteh.ai/catalog/standards/cen/c02ba288-d5ac-4324-a8dc-8d977de65b0c/en-397-2025-ac-2025 |автор=Technical Committee CEN/TC 158 “Head protection’ |заглавие=EN 397:2025 Industrial protective helmets |год=2025 |язык=en |издание=5th ed |место=Brussels |издательство=European Committee for Standardization |allpages=55 |серия=ICS 13.340.20}}</ref> <ref name="Каски-ЕС-э">{{Книга |ссылка=https://standards.iteh.ai/catalog/standards/clc/0b050787-38c5-4d96-a2de-5132f2868f09/en-50365-2023?srsltid=AfmBOoqb_B9-iF0mV4rD8HFua5PVFvy5etMwwJxMJmtCk9B7GzQ_7U5E |автор=CLC/TC 78 “Equipment and tools for live working“ |заглавие=EN 50365:2023 Live Working - Electrically insulating helmets for use on low and medium voltage installations |год=2023 |язык=en |издание=2nd ed |место=Brussels |издательство=European Committee for Standardization |allpages=24 |серия=ICS 13.260 Protection against electric shock. Live working, 13.340.20 Head protective equipment}}</ref> <ref name="Каски-ООН">{{Книга |ссылка=https://unece.org/transport/documents/2021/08/standards/un-regulation-no-22-rev5-06-series |автор=The United Nations Economic Commission for Europe (UNECE) |заглавие=Правила No 22 ООН. Единообразные предписания, касающиеся официального утверждения защитных шлемов и их смотровых козырьков для водителей и пассажиров мотоциклов и мопедов |ответственный=Организация Объединённых Наций |год=2021 |издание=6 изд |издательство=OON |страницы=https://unece.org/sites/default/files/2025-05/R022r5r.pdf |всего страниц=135 |серия=E/ECE/324/Rev.1/Add.21/Rev.5, E/ECE/TRANS/505/Rev.1/Add.21/Rev.5}}</ref> <ref name="Каски-ЕС-1">{{Книга|ссылка=https://standards.iteh.ai/catalog/standards/cen/f78a2d6e-3c4a-420d-9581-bfbafe948f48/en-14052-2012a1-2012 |автор= WG 1 "Industrial safety helmets" in: Technical Committee CEN/TC 158 "Head protection"|заглавие=EN 14052:2012 High performance industrial helmets|год=2012|язык=en|место=Brussels|издательство=European Committee for Standardization|серия=ICS 13.340.20 Head protective equipment|allpages=25}} </ref> <ref name="Каски-ЕС-2">{{Книга|ссылка=https://standards.iteh.ai/catalog/standards/cen/1d77e417-72d1-4c8a-9735-c579e710f673/en-12492-2012?srsltid=AfmBOopiZWfeCyWaHS3qEsjjZ9Pt47GXnxc4Pxz5O6x7RLqkiXGF2BVV|автор=Technical Committee CEN/TC 158 "Head protection"|заглавие=EN 12492:2012 Mountaineering equipment - Helmets for mountaineers - Safety requirements and test methods|год=2012|язык=en|место=Brussels|издательство=European Committee for Standardization|серия=ICS 13.340.20 ; 97.220.4|allpages=25}} </ref> <ref name="Каски-ЕС-3">{{Книга|ссылка= https://standards.iteh.ai/catalog/standards/cen/0fceba9b-d0eb-4001-a71e-af8ef63cc4f7/en-17950-2024 |автор= WG 11 "Headforms and test methods" in: Technical Committee CEN/TC 158 "Head protection"|заглавие=EN 17950:2024 Protective helmets - Test methods - Shock absorption including measuring rotational kinematics|год=2024|язык=en|место=Brussels|издательство=European Committee for Standardization|серия=ICS 13.340.20 Head protective equipment|allpages=17}} </ref> <ref name="Каски-US">{{Книга |автор=[[:w:ASTM International|Subcommittee F08.53 in ASTM International]] |заглавие=ASTM F3555-22. Standard Test Method for Measuring Impact Attenuation Characteristics of Helmets Under Induced Rotational Loading Using an Inclined Anvil |год=2022 |язык=en |место=West Conshohocken, Pennsylvania |издательство=American Society for Testing and Materials |allpages=7 |серия=ICS Code: 13.340.20 |doi=10.1520/F3555-22}}</ref> <ref name="Каски-ГОСТ-2">{{Книга|ссылка=https://meganorm.ru/Index2/1/4293762/4293762915.htm |автор=Рабочая группа подкомитета ПК 7|заглавие=ГОСТ EN 14052-2015 ССБТ. Высокоэффективные защитные каски. Общие технические требования. Методы испытаний|ответственный=Технический комитет ТК 320 СИЗ|год=2016|место=Москва|издательство=Стандартинформ|страниц=20|тираж=37}} [https://meganorm.ru/Data2/1/4293762/4293762915.pdf PDF]</ref> <ref name="Каски-Австралия">{{Книга|ссылка=https://www.standards.govt.nz/shop/asnzs-18012024|автор=Joint Technical Committee SF-018 "Occupational Protective Helmets"|заглавие=AS/NZS 1801:2024 Occupational Protective Helmets|год=2024|язык=en|издание=4th ed|место=Sydney|издательство=Standards Australia Limited & Standards New Zealand|allpages=42|серия=ICS 13.340.20 Head protective equipment|isbn=978-1-77972-549-3}}</ref> <ref name="Директива-ЕС-СИЗ">{{Статья|ссылка=https://eur-lex.europa.eu/legal-content/en/TXT/?uri=CELEX:31989L0656|автор=The Council President J. P. Soisson|заглавие=COUNCIL DIRECTIVE of 30 November 1989 on the minimum health and safety requirements for the use by workers of personal protective equipment at the workplace (third individual directive within the meaning of Article 16 ( 1 ) of Directive 89/ 391 /EEC)|год=1989|ответственный=The Council of the European Communities|язык=en|автор издания=European Union|издание=Official Journal of the European Communities - Legislation|тип=official journal|месяц=12|число=12|выпуск=No L 393|pages=18-28}}</ref> <ref name="Каски-EU">{{Cite web|url=https://oshwiki.osha.europa.eu/en/themes/protective-helmets-requirements-and-selection|title=Protective helmets – requirements and selection|lang=en|last=Marcin Jachowicz, Karla Van den Broek.|website=oshwiki.osha.europa.eu|publisher=European Agency for Safety and Health at Work}} (Prevention and control strategies - Personal Protective Equipment). (26 августа 2020). Дата обращения: 6 декабря 2024</ref> <ref name="Каски-Канада-уч">{{Книга|ссылка=https://www.lu530.com/wp-content/uploads/2015/05/M029_S4.pdf |автор=IHSA|заглавие=Construction Health and Safety Manual|год=2010|часть=Chapter 12. [https://www.ihsa.ca/rtf/health_safety_manual/pdfs/equipment/Head_Protection.pdf Head protection]|язык=en|издание=2nd ed|место=Mississauga, Ontario|издательство=Infrastructure Health & Safety Association|pages=12-1 - 12-2|isbn=978-0-919465-54-1}} [https://www.ihsa.ca/Resources/Health_Safety_Manual.aspx Head protection]</ref> <ref name="Каски-2025">{{Книга |автор=[[:w:en:National Operating Committee on Standards for Athletic Equipment|National Operating Committee on Standards for Athletic Equipment]] |ссылка= https://nocsae.org/nd006-standard-performance-specification-for-newly-manufactured-youth-football-helmets/ |заглавие=NOCSAE DOC (ND) 006 – 23m25a. Standard Performance Specification for Newly Manufactured Youth Football Helmets |год=2025 |часть=7. Test Requirements |язык=en |место=Overland Park, Kansas |издательство=NOCSAE |pages=6 |allpages=12}}</ref> <ref name="ЕС-стат-21">{{Статья|ссылка=https://www.researchgate.net/publication/348617629_Work-related_traumatic_brain_injury_in_the_construction_industry_in_Sweden_and_Germany?_tp=eyJjb250ZXh0Ijp7ImZpcnN0UGFnZSI6InB1YmxpY2F0aW9uIiwicGFnZSI6InNlYXJjaCIsInBvc2l0aW9uIjoicGFnZUhlYWRlciJ9fQ|автор=Karin Brolin, Daniel Lanner, Peter Halldin|заглавие=Work-related traumatic brain injury in the construction industry in Sweden and Germany|год=2021|язык=en|издание=Safety Science|издательство=Elsevier B.V.|месяц=4|выпуск=4|pages=105147|volume=136|issn=|doi=10.1016/j.ssci.2020.105147}} ISSN 0925-7535</ref> <ref name="Каски-США">{{Книга|ссылка=https://www.ecfr.gov/current/title-29/subtitle-B/chapter-XVII/part-1910|заглавие=Occupational Safety and Health Standards|год=2012|часть=[https://www.osha.gov/laws-regs/regulations/standardnumber/1910/1910.135 1910.135 - Head protection]|язык=en|место=Washington, DC|издательство=Occupational Safety and Health Administration|volume=1910 Subpart I - Personal Protective Equipment}}</ref> <ref name="Каски-США-"> ''Brad Kelechava''. [https://blog.ansi.org/ansi-isea-z89-1-industrial-head-protection/ ANSI Z89.1 – Industrial Head Protection] <small>(англ.)</small>. ''blog.ansi.org.'' American National Standards Institute (29 июня 2016). Дата обращения: 3 декабря 2024.</ref> <ref name="Каски-Гонк">{{Книга|ссылка=https://www.labour.gov.hk/eng/public/content2_8c.htm|автор=The Government of the Hong Kong Special Administrative Region of the PRC - Occupational Safety and Health Branch|заглавие=Guidance Notes on the Selection, Use and Maintenance of Safety Helmets|год=2018|часть=6.1 Factors in Selection. In: 6. Selection of Safety Helmets -|язык=en|место=Hong Kong|издательство=Occupational Safety and Health Branch, Labour Department|pages=11|allpages=29|серия=Occupational Safety > Part C : Guidance Notes}} [https://www.labour.gov.hk/eng/public/os/C/GN_on_helmet_eng.pdf PDF]</ref> <!-- Комментарий --> {{Cite web|url=https://blog.ansi.org/ansi-isea-z89-1-industrial-head-protection/|title=ANSI Z89.1 – Industrial Head Protection|lang=en|author=Brad Kelechava|website=blog.ansi.org|date=2016-06-29|publisher=American National Standards Institute|access-date=2024-12-03}} <!-- Комментарий --> -Канада-травмы"> {{Cite web|url=https://www.thesafetymag.com/ca/topics/safety-and-ppe/3-things-to-know-about-head-protection/405677|title=3 Things to know about head protection|lang=en|author=Maia Foulis|website=Canadian Occupational Safety thesafetymag.com|description=Topics - Safety and PPE|date=2022-05-01|location=Toronto, Ontario|publisher=KM Business Information Canada Ltd.|access-date=2024-12-17}}</ref> <ref name="Каски-Канада-травмы">{{Cite web|url=https://www.thesafetymag.com/ca/topics/safety-and-ppe/3-things-to-know-about-head-protection/405677|title=3 Things to know about head protection|lang=en|last=Maia Foulis|website=Canadian Occupational Safety thesafetymag.com|description=Topics - Safety and PPE|year=2022-05-01|location=Toronto, Ontario|publisher=KM Business Information Canada Ltd.|access-date=2024-12-17}}</ref> <ref name="Каски-Канада-травмы-2">{{Статья|ссылка=https://injuryprevention.bmj.com/content/24/Suppl_2/A182.2|автор=Fahra Rajabali, Belinda Gabbe, Shelina Babul, Ian Pike.|заглавие=PW 1803 The costs of head injury in british columbia, canada|год=2018|язык=en|автор издания=Society for Advancement of Violence and Injury Research (SAVIR)|издание=Injury Prevention|издательство=BMJ Publishing Group Ltd.|месяц=11|выпуск=Suppl 2|pages=A182|volume=24|issn=}} ISSN 1353-8047</ref> <ref name="Каски-перегрев">{{Книга|автор=Дементьева Л. Н., Брунштейн И. П., Малошенко А. Л., Мужипов Р. Н.|заглавие=Гигиена труда в промышленном строительстве|ссылка=https://library.by/portalus/modules/medecine/readme.php?subaction=showfull&id=1752142867&archive=&start_from=&ucat=&|ответственный=Каспаров А.А. и Серебряный Л.А. ред|год=1987|часть=Гигиеническая оценка защитной каски строителя в условиях жаркого климата|издание=выпуск 32|место=Москва|издательство=НИИ гигиены труда и профессиональных заболеваний АМН СССР|страницы=125-133|страниц=143|серия=Сборник научных трудов}}</ref> <!-- Комментарий --> -Канада-боль"> {{Cite web|url=https://www.thesafetymag.com/ca/topics/safety-and-ppe/hard-hats-and-headaches-a-real-pain/183809|title=Hard hats and headaches: A real pain?|lang=en|author=Stefan Dubowski|website=Canadian Occupational Safety thesafetymag.com|description=Topics - Safety and PPE|date=2015-01-07|location=Toronto, Ontario|publisher=KM Business Information Canada Ltd.|access-date=2024-12-17}}</ref> <ref name="Каски-Канада-боль"> {{Cite web|url=https://www.thesafetymag.com/ca/topics/safety-and-ppe/hard-hats-and-headaches-a-real-pain/183809|title=Hard hats and headaches: A real pain?|lang=en|last=Stefan Dubowski|website=Canadian Occupational Safety thesafetymag.com|description=Topics - Safety and PPE|year=2015-01-07|location=Toronto, Ontario|publisher=KM Business Information Canada Ltd.|access-date=2024-12-17}}</ref> <!-- Комментарий --> "Каски-Канада-поправки">{{Cite web|url=https://www.worksafebc.com/en/resources/law-policy/discussion-papers/bod-approves-2020-amendments-ohsr-apr21/part-8-safety-headgear|title=Board of Directors approves the 2020 amendments to the Occupational Health and Safety Regulation|lang=en|website=WorkSafeBC worksafebc.com|subtitle=Part 8 – Safety headgear|date=2021|location=Vancouver, British Columbia|access-date=2024-12-17}}</ref> <ref name="Каски-Канада-поправки">{{Cite web|url=https://www.worksafebc.com/en/resources/law-policy/discussion-papers/bod-approves-2020-amendments-ohsr-apr21/part-8-safety-headgear|title=Board of Directors approves the 2020 amendments to the Occupational Health and Safety Regulation|lang=en|website=WorkSafeBC worksafebc.com|subtitle=Part 8 – Safety headgear|year=2021|location=Vancouver, British Columbia|access-date=2024-12-17}}</ref> <ref name="Каски-Канада-советы">{{Cite web|url=https://www.canadianmetalworking.com/canadianmetalworking/blog/healthsafety/get-a-head-start-on-preventing-workplace-concussions|title=Get a head start on preventing workplace concussions|lang=en|last=Canadian Centre for Occupational Health and Safety.|website=Canadian Metalworking (блог журнала) canadianmetalworking.com|subtitle=Start by identifying and removing hazards that can lead to a head injury|location=Canada|publisher=FMA Communications Canada, Inc}} (29 мая 2024). Дата обращения: 18 декабря 2024.</ref> <!-- Комментарий --> name="Каски-Канада-советы">{{Cite web|url= https://www.canadianmetalworking.com/canadianmetalworking/blog/healthsafety/get-a-head-start-on-preventing-workplace-concussions |title=Get a head start on preventing workplace concussions|lang=en|author=Canadian Centre for Occupational Health and Safety|website=Canadian Metalworking (блог журнала) canadianmetalworking.com|subtitle=Start by identifying and removing hazards that can lead to a head injury|location=Canada|publisher=FMA Communications Canada, Inc.|access-date=2024-12-18|year=2024}}</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] {{Stub}} mdhivru39hzdgloz3vgchfes9f44kdt Средства индивидуальной защиты (обзорная лекция)/СИЗ кожи от химических веществ 0 35745 270423 269661 2026-10-27T07:06:12Z Jcb 79968 270423 wikitext text/x-wiki [[File:СИЗ-кожи-2.jpg|thumb|right|310px|Примеры СИЗ кожи]] Для защиты организма от воздействия токсичных веществ через кожу используют защитную одежду, перчатки и специальную обувь, к которым предъявляются определённые требования, и их выполнение проверяется при сертификационных испытаниях. В целом, СИЗ кожи могут изготавливаться для одноразового или многократного применения. == Научные исследования == === Степень и продолжительность защиты === Отличие условий, в которых проводятся испытания перчаток для защиты от химикатов, от условий их реального применения, может привести к недооценке опасности, и переоценке защитных свойств этих СИЗ<ref name="КЗ-кожи-" />. По данным<ref name="КЗ-кожи" /> использование результатов европейских сертификационных испытаний для прогнозирования защиты работников даёт чрезмерно оптимистичный результат, не соответствующий реальности даже при своевременном применении СИЗ. Например, определение проникания токсичных веществ через материал проводится в статических условиях, а на [[:w:ru:Рабочее место|рабочих местах]] люди двигаются, материал СИЗ изгибается, и его защитные свойства ухудшаются — что не учитывает методика тестирования. Температура перчаток близка к температуре тела, а испытания проводят при комнатной температуре, из-за отличия проницаемость может отличаться вдвое. Испытания проводят при воздействии токсичных веществ однократно, а на [[:w:ru:Рабочее место|рабочих местах]] эти СИЗ часто используют много раз. Поэтому может происходить постепенная «миграция» молекул химикатов, проникших при первом применении в наружный слой полимеров. В статье показано, что степень проникания вредного вещества через материал СИЗ и доза воздействия этого вещества на организм могут значительно отличаться. В целом, авторы предложили оценивать эффект от использования СИЗ на основе замеров у работников; и с учётом качества программ их использования (включающих выбор, организацию применения, обучение работников и т. п.). При отсутствии задокументированных программ предложено считать уровень защиты нулевым, при наличии — наименьшие коэффициенты защиты (например, для перчаток КЗ = 6). === Возможный перегрев организма === При повышенной температуре воздуха на рабочем месте, интенсивном тепловом излучении, выполнении тяжёлой физической физической работы (или сочетании этих и других факторов) ухудшение теплоотдачи может привести к перегреву организма работника, опасному для его жизни и здоровья. При носке обычной повседневной одежды в атмосфере с невысокой относительной влажностью эффективным способом [[:w:терморегуляция |терморегуляции]] является испарение пота<ref name="NIOSH-2016" />. Например, по данным<ref name="Величковский-1958" /> рабочий, обслуживающий электропечи, при температуре летом 45-50 °С, мог терять за смену 8 часов от 3,8 до 11,2 кг. Соответственно, использование газонепроницаемых материалов может создать опасность перегрева, мешая естественному способу терморегулирования. Для профилактики и смягчения этой проблемы предлагались и изучались разные способы<ref name="NIOSH-2016" />. Например, испытания подачи охлаждённого воздуха в надетое под одежду воздухораспределительное устройство показали, что за 12 часов не произошло существенного снижения работоспособности и ухудшения самочувствия. Достоинством устройства является очень небольшая масса (0,45 кг), а недостатком - необходимость подключения его к источнику-кондиционеру с помощью шланга (изделие предназначалось для танкистов). При использовании изолирующих костюмов в [[:w:Министерство среднего машиностроения СССР|атомной промышленности СССР]] мог использоваться другой способ - вблизи рабочего места оборудовали водопровод, а работник надевал поверх изолирующего СИЗ одноразовую тканевую одежду, которая периодически смачивалась. Испарение воды с мокрой ткани снаружи газонепроницаемого СИЗ "имитировало" испарение пота, нормализовало температуру тела, а снижение эффекта при использовании разновидности этой защитной одежды, закрывавшей меньшую часть тела, могло отчасти компенсироваться за счёт применения ткани, удерживающей больше воды<ref name="Саливон-1970" />. Но защите жизни и здоровья очень небольших групп исключительно высококвалифицированных специалистов, космонавтов, лётчиков, подводников, работников атомной промышленности и т.п., уделяется гораздо больше внимания, чем профилактике профзаболеваний у более многочисленных работников других отраслей народного хозяйства; и для последних СИЗ от перегрева могут не разрабатываться совсем. == Проблемы выбора СИЗ кожи и обеспечения их своевременной замены == В отношении уровня и продолжительности защиты СИЗ одной из важнейших проблем может стать отсутствие или значительная [[:w:Неопределённость|неопределённость]] исходной информации для выбора подходящего изделия. В американском руководстве для государственных инспекторов по охране труда дана классификация СИЗ кожи по степеням защиты, и рекомендации по их выбору. Вместе с тем, на основании большого накопленного практического опыта, авторы отмечают наличие значительной неопределённости в отношении оценки способности этих СИЗ защищать работника. Конкретно, многие компании производят разные СИЗ, используя разные материалы и [[:w:ru:Технология|технологии]], а затем успешно их сертифицируют, т.к. изделия соответствуют требованиям. Однако испытания проводятся по очень небольшому количеству вредных веществ, и в строго определённых, конкретных и стабильных лабораторных условиях. А условия на [[:w:ru:Рабочее место|рабочих местах]] иные, и очень разнообразные; как поведут себя СИЗ при воздействии множества вредных веществ, не использовавшихся при тестировании, заранее предсказать сложно. Хуже того, из-за использования разными производителями разных материалов и технологий, даже результаты экспериментов, проведённых на одной модели, нельзя использовать для оценки защитных свойств другой модели (т.к. при её изготовлении могли использоваться не точно такие же материалы / технологии)<ref name="OSHA-2022+s" />. Некоторые примеры такого разнообразия приводятся в таблице ниже. {| class="wikitable collapsible " style="text-align:center" ! colspan=7 | Период времени (часы), за который некоторые вещества могут проникать сквозь некоторые изолирующие материалы, используемые для изготовления перчаток. Источник: таблица 4<ref name="IS-2002" /> |- ! rowspan=2 | Вещество !! colspan=6 | Изолирующий материал СИЗ |- | [[:w:Резина|Натуральная резина]] | [[:w:Хлоропреновый каучук|Неопрен]] | [[:w:Хлоропреновый каучук| Неопрен]] + [[:w:Резина|натуральная резина]] | [[:w:Нитрилы| Нитрил]] | [[:w:Поливинилхлорид| Поливинилхлорид]] | [[:w:Поливиниловый спирт| Поливиниловый спирт]] |- | [[:w:Хлороформ | Хлороформ]] || от 0,01 до 0,05 || от 0,01 до 0,36 || от 0,05 до 0,11 || от 0,07 до 0,3 || около 0,01 || более 6 |- | [[:w:Метанол |Метанол ]] || от 0,02 до 6 || от 0,25 до более 8 || от 0,1 до 1,1 || от 0,18 до 3,2 || от 0,02 до 6 || от 0,02 до 0,04 |- | [[:w:Ацетон |Ацетон ]] || от 0,02 до более 3 || от 0,04 до более 1 || от 0,05 до 0,43 || от 0,07 до 0,3 || от менее 0,02 до 0,3 || от 0,07 до более 4 |- | [[:w:Бензол |Бензол ]] || от 0,01 до 0,18 || от 0,02 до 3,1 || около 0,05 || от 0,07 до 1 || от менее 0,01 до 0,5 || от 0,05 до более 33 |} [[File:Шланговый респиратор с полнолицевой маской.JPG|thumb|right|310px|Защита кожи при распылении краски сжатым воздухом]] В ЕС разработан стандарт с общими указаниями по выбору СИЗ — защитной одежды<ref name="ХимЗащОдежда-2017" />. В разделе, относящемся к сертификационному тестированию, для большинства методов указано, что они не дают никакого представления о степени и длительности защиты на практике. Возможно, из-за этого в общих указаниях лишь упоминают, что при выборе СИЗ кожи следует учитывать их срок службы при воздействии конкретного вещества - без каких-то подробностей<ref name="HAZWOPER" />. Но определение этого срока может быть очень сложной задачей. В справочных изданиях, например<ref name="Forsberg-2020" /> приводятся минимальные ожидаемые сроки сохранения защитных свойств разных материалов при воздействии разных химических веществ, и предлагается выбирать подходящую химзащитную одежду на основе этой информации. Значительная неопределённость защитных свойств кожи, их зависимость от условий применения и выполняемой работы, может помешать их правильному выбору и использованию. Специалисты советуют как можно тщательнее искать исходные данные для оценки защитных свойств СИЗ кожи, и максимально критично оценивать информацию, предоставляемую поставщиками. Последние часто сообщают лишь то, сколько времени сохранялась непроницаемость при воздействии определённого вещества. С точки зрения эффективной защиты работников будет правильно не ограничиваться лишь этой информацией, а выяснить у поставщика/изготовителя температуру и способ испытаний, и др., пример ниже. {| class="wikitable collapsible collapsed" style="text-align:left" ! Специалисты советуют узнать у поставщика СИЗ<ref name="Perkins-1989" /> : |- | 1. Какое химическое вещество использовалось для испытания непроницаемого материала, в какой форме и при какой концентрации. |- | 2. Способ испытаний материала. |- | 3. Температура, при которой проводилось испытание (с ростом температуры проницаемость обычно увеличивается). |- | 4. Концентрация, при которой метод испытаний и оборудование позволяли обнаружить проникание вредного вещества. |- | 5. Источник информации, например, название химической лаборатории, проводившей тестирование; или что данные получены изготовителем при проведении испытаний самостоятельно. |- | 6. Период времени, через который обнаруживалось проникание вредного вещества; или длительность эксперимента - если к его окончанию проникание не обнаруживалось. |- | 7. [[:w:Массообмен|Массоперенос]], установившаяся (постоянная) скорость проникания вредного вещества через изолирующий материал - если при проведении измерений будет достигнуто состояние стабильной скорости проникания. Если такое состояние не будет достигнуто - максимальная скорость проникания. |- | 8. Используется ли при обнаружении вредного вещества, проникшего через изолирующий материал, среда-носитель, перемещающаяся от материала к детектору непрерывно (т.е. заменяемая новыми, свежими и не загрязнёнными порциями), или рециркулирующая (движущаяся от детектора к материалу и от материала к детектору по кругу). |- | 9. При применении первого способа, указанного в п. 8 выше, какая минимальная скорость проникания могла быть измерена при использовавшемся оборудовании и методе замеров. |- | 10. При применении второго способа, указанного в п. 8 выше, и не обнаружении проникания вредного вещества за период измерений, минимальная скорость проникания, выраженная как отношение: (порог чувствительности, т.е. минимальная обнаруживаемая концентрация) × (площадь образца материала) / (объём среды-носителя на момент окончания измерений) |- | 11. Если время проникания является средним значением (при многократных измерениях), какое было стандартное отклонение от среднего значения. [[:w:Национальная ассоциация противопожарной защиты|NFPA]] требует от поставщиков сообщать минимальное и максимальное время проникания. |- | 12. Как часто измерялась концентрация вредного вещества, проникшего через материал. Например, если замеры проводились каждые полчаса, и было получено время проникания 32 минуты, то точность такой информации может быть низкой. Специалисты советуют сообщать такое время проникания, когда проводился последний замер, ещё не обнаруживший проникание - непосредственно перед обнаружением. |} Однако во многих случаях необходимая информация может быть недоступна, например из-за того, что испытания для конкретного сочетания ''( изолирующий материал - вредное вещество - условия воздействия )'' не проводились; проводились, но неизвестны поставщику; информация может быть коммерческой или служебной тайной<ref name="ACGIH-1987" />. Таким образом, определение срока службы может быть непростой задачей, а использование лишь небольшого количества (вполне точной и достоверной) информации, часто предоставляемой поставщиками, может привести к грубым ошибкам и сильной недооценке риска. Также может быть важно учесть и другие свойства СИЗ, например устойчивость к механическим повреждениям, степень дискомфорта при применении, способность защищать от низких или высоких температур. Специалисты по [[:w:профессиональные заболевания|профессиональным заболеваниям]] из [[:w:Американская ассоциация государственных промышленных гигиенистов |ACGIH]] рекомендуют шире использовать биологический мониторинг для оценки фактического воздействия химических веществ на организм. В США это юридически обязательно при работе со [[:w:Отравления свинцом|свинцом]], [[:w:Кадмий|кадмием]] и [[:w:Бензол|бензолом]]. Разработаны методы измерений и "[[:w:ПДКр.з.#Биологические ПДК|биологические ПДК]]" для примерно 59 вредных веществ и их групп<ref name="TLV+BEI-2025" />. В РФ конкретных требований и рекомендаций специалистов по выбору СИЗ кожи от химических веществ нет, стандарт<ref name="ХимЗащОдежда-2017" /> не переведён, разработка и внедрение биомониторинга ведётся крайне медленно<ref name="Орлова-2010" />. == Примечания == {{примечания|refs= <ref name="КЗ-кожи-">{{Статья|автор=J.W. Cherrie, S. Semple, D. Brouwer|заглавие=Gloves and Dermal Exposure to Chemicals: Proposals for Evaluating Workplace Effectiveness|год=2004|язык=en|издание=The Annals of Occupational Hygiene|издательство=Oxford University Press|месяц=10|выпуск=7|pages=607–615|volume=48|doi=10.1093/annhyg/meh060}} ISSN 2398-7308, {{PMID|15388512}}.</ref> <ref name="КЗ-кожи">{{Статья|автор=Derk H. Brouwer, Hans Marquart, Joop J. van Hemmen|заглавие=Proposal for an Approach with Default Values for the Protection Offered by PPE, Under European New or Existing Substance Regulations|год=2001|язык=en|автор издания=British Occupational Hygiene Society|издание=Annals of Occupational Hygiene|издательство=Oxford University Press|месяц=10|выпуск=7|pages=543-553|volume=45|issn=|doi=10.1016/S0003-4878(01)00021-7|pmid=}} ISSN 2398-7308, {{PMID|11583656}}.</ref> <ref name="OSHA-2022+s">{{Cite web|url=https://www.osha.gov/otm/section-8-ppe/chapter-1|title=Chapter 1. Chemical Protective Clothing |last= US OSHA|website=www.osha.gov|subtitle=OSHA [https://www.osha.gov/otm/ Technical Manual] (OTM). Section VIII |publisher=Occupational Safety and Health Administration|lang=en}} (6 июля 2022). Дата обращения: 24 октября 2024.</ref> <ref name="NIOSH-2016">{{Книга|автор=Бренда Джеклич; Джон Уильямс; Кристин Мусолин; Айто Кока; Юнг-Хюн Ким; Нина Тёрнер и др|заглавие=NIOSH criteria for a recommended standard: occupational exposure to heat and hot environments|ссылка=https://www.cdc.gov/niosh/docs/2016-106/|ответственный=John Howard, MD|издание=3 ed|место=Cincinnati, Ohio|издательство=U.S. Department of Health and Human Services, Centers for Disease Control and Prevention, National Institute for Occupational Safety and Health|год=2016|allpages=192|серия=DHHS (NIOSH) Publication No. 2016-106|archive-date=2021-12-30|archive-url=https://web.archive.org/web/20211230163015/https://www.cdc.gov/niosh/docs/2016-106/}} Есть перевод: [[:Файл:NIOSH Жара перевод 05.07.2018 wiki+++.pdf|PDF]] [[b:ru:Защита работников от нагревающего микроклимата|Wiki]]</ref> <ref name="Величковский-1958">{{Книга |автор=[[:w:Величковский, Борис Тихонович| Величковский Б.Т.]], Власова В.Н. |заглавие=Вопросы гигиены труда, профпатологии и промышленной токсикологии |ответственный=Редакционная коллегия: Михайлов В.А. и другие |год=1958 |часть=Силикоз и его профилактика у рабочих, занятых на электроплавке кремния. В: II Вопросы пылевой патологии |место=Свердловск |издательство=Свердловский научно-исследовательский институт гигиены труда и профпатологии |том=3, часть 1 |страницы=155-166 |всего страниц=201 |серия=Министерство здравоохранения РСФСР |тираж=1100}}</ref> <ref name="Саливон-1970">''Саливов С.Г.'' [https://cyberleninka.ru/article/n/o-zavisimosti-ohlazhdayuschego-effekta-ot-vlagoemkosti-i-konstruktsii-ekrana/viewer О зависимости охлаждающего эффекта от влагоёмкости и конструкции экрана] // Гигиена и санитария. — Москва, 1970. — № 6. — С. 22-26. — ISSN 0016-9900</ref> <ref name="ХимЗащОдежда-2017">{{Книга |автор=CEN/TC 162/WG 3 - Protective clothing against chemicals, infective agents and radioactive contamination |заглавие=PD CEN/TR 15419:2017 Protective clothing - Guidelines for selection, use, care and maintenance of chemical protective clothing |ответственный=European Committee for Standardization (CEN) |год=2017 |часть=4.6 Garment material selection criteria (definition of CPC material criteria) |язык=en |издание=2nd ed |место=Brussels, Belgium |издательство=British Standards Institution |pages=13-17 |allpages=49 |серия=ICS 13.340.10 Protective clothing |isbn=978 0 580 98705 2}}</ref> <ref name="HAZWOPER">{{Книга |ссылка=https://www.local49training.org/wp-content/uploads/40-Hour-HAZWOPER-Student-Manual.pdf |автор=Barbara A. McCabe et al |заглавие=40-Hour HAZWOPER Student Manual |ответственный=International Union of Operating Engineers’ (IUOE) ’ National Training Fund (NTF) |год=2017 |место=Beaver, WV |allpages=543 |серия=National HAZMAT Program.}}</ref> <ref name="Forsberg-2020">{{Книга |автор=Krister Forsberg, Ann Van den Borre, James P. Zeigler |заглавие=Quick Selection Guide to Chemical Protective Clothing |год=2020 |язык=en |издание= 7th ed |место=Hoboken, NJ |издательство=John Wiley & Sons, Inc. |allpages=308 |isbn=978-1119650553}}</ref> <ref name="IS-2002">{{Книга |ссылка= https://dn760001.eu.archive.org/0/items/gov.in.is.15071.2002/is.15071.2002.pdf |автор=Shri K.C. Gupta et al |заглавие=Indian Standard IS 15071:2002. Chemical Protective Clothing Specification |ответственный=lndustrial Safety Sectional Committee, CHD 08 |год=2002 |оригинал=British Standard BS 7184:1989 ‘Recommendations for selection, use and maintenance of chemical protective clothing’ |язык=en |место=New Delhi |издательство=Bureau of Indian Standards |allpages=23 |серия=ICS 13.340.10}}</ref> <ref name="ACGIH-1987">{{Книга |автор=A.D. Schwope et al |заглавие=Guidelines for the Selection of Chemical Protective Clothing |ответственный=Arthur D. Little, Inc |год=1987 |язык=en |издание=3rd ed |место=Cincinnati, Ohio |издательство=American Conference of Governmental Industrial Hygienists |allpages=587 |volume=I Field Guide; and Vol. II Technical and Reference Manual |серия=ACGIH Signature Publication}}</ref> <ref name="Perkins-1989">{{Книга |ссылка= https://dl.astm.org/stps/book/472/Chemical-Protective-Clothing-Performance-in |автор=R.A. Janke |заглавие=Chemical Protective Clothing Performance in Chemical Emergency Response |часть= Understanding and using chemical permeation data in the selection of chemical protective clothing |ответственный=J.O. Stull, J.L. Perkins eds |издание= American Society for Testing and Materials |год=1989 |язык=en |место=Baltimore, MD |издательство=ASTM International |allpages=279 |isbn=978-0-8031-1297-1 |серия= ASTM Selected Technical Papers STP1037-EB |doi= 10.1520/STP1037-EB}}</ref> <ref name="TLV+BEI-2025">{{Книга |автор=Nancy B. Hopf et al |заглавие=2025 TLV and BEI Based on the Documentation of the Threshold Limit Values for Chemical Substances and Physical Agents |год=2025 |часть=2025 Biological Exposure Indices Adopted by ACGIH with Intended Changes |язык=en |место=Cincinnati, Ohio |издательство=American Conference of Governmental Industrial Hygienists |pages=103-124 |allpages=302 |серия=ACGIH Signature Publication |isbn=978-1-60726-173-5}}</ref> <ref name="Орлова-2010">{{Статья |автор=Орлова О.И., Савельева Е.И., Радилов А.С., Бабаков В.Н., Войтенко Н.Г |заглавие=Применение биомониторинга для оценки характера и тяжести воздействия химического фактора |год=2010 |месяц=12 |автор издания=НИИ медицины труда РАН |место=Москва |издание=Медицина труда и промышленная экология |номер=12 |страницы=28-32 |ссылка=https://cyberleninka.ru/article/n/primenenie-biomonitoringa-dlya-otsenki-haraktera-i-tyazhesti-vozdeystviya-himicheskogo-faktora|issn=}} ISSN 1026-9428</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] {{Stub}} 80q7tqleyk0kbr0j9bogvg0ghxcl716 Средства индивидуальной защиты (обзорная лекция)/СИЗ рук 0 35746 270427 269662 2026-10-27T07:09:06Z Jcb 79968 270427 wikitext text/x-wiki [[File:Kevlar gloves.jpg|thumb|right|300px|Перчатки из прочного [[:w:Кевлар|кевлара]].]] Разрабатываются и используются средства индивидуальной защиты рук от разных вредных и опасных производственных факторов (порезов, вибрации, повышенной и/или пониженной температуры, электрического тока, кислот, щелочей и др.). К СИЗ рук относят не только рукавицы, перчатки, наладонники, вачаги, но и [[дерматологические средства защиты]] (мази, пасты, кремы)<ref name="СИЗ-2005-104" />. [[File:Condenser Water Supply is Welded by Monaco (8268314628).jpg|thumb|right|300px|Перчатки для [[:w:Сварка|сварочных работ]], устойчивы к прожиганию искрами]] == СИЗ рук от вибраций == Результаты измерений с помощью [[:w:ru:Виброметр|портативного акселерометра]] показали, что эластичное покрытие рукояток вибрирующего инструмента и использование виброзащитных перчаток (2 модели) заметно уменьшили вибрационные ускорения, передаваемые на руку. Авторы посоветовали шире использовать портативное измерительное оборудование для оценки риска у рабочих, использующих вибрирующие ручные инструменты<ref name="виб+" />. Выполнение такого предложения позволит, в том числе, учесть возможное значительное изменение вибрационной скорости инструмента, происходящее при его систематичном использовании. Например, у пневматической шлифовальной машины ПШТ виброскорости ручки и шейки в начале эксплуатации и через полгода составляли 0,09 и 0,69 см/с на частоте 2 кГц<ref name="виб-инстр" />. [[:w:Управление по охране труда Великобритании (HSE)|Британское управление по охране труда]] считает<ref name="виб-HSE" />, что виброзащитные перчатки эффективны лишь при защите от высокочастотных колебаний, а при средне- и низкочастотных они неэффективны. Работодателям рекомендуют: * Исходить из того, что виброзащитные перчатки неэффективны, кроме случаев, когда есть результаты измерений в конкретных условиях, доказывающие обратное; * Искать пути снижения воздействия вибрации на работника (безопасный инструмент и т.п.); * При работе в холодную погоду для предотвращения ухудшения кровообращения следует держать руки сухими и в тепле, для чего могут пригодиться подходящие перчатки. Отдел охраны труда правительства штата Вашингтон<ref name="виб-US" /> также предупреждает о том, что виброозащитные перчатки могут быть эффективны лишь при высокочастотной вибрации, при том, что средне- и низкочастотные вибрации - опаснее. Кроме того, читателей предупреждают, что использование "толстых" виброзащитных перчаток (как показала практика) может увеличить риск травмирования работников, которым может быть сложнее работать в таких средствах защиты. == СИЗ рук от перегрева == Результаты исследования перчаток у 135 работниц, работавших в контакте с оборудованием и изделиями при температуре 30-80°С показали недостаточную эффективность. Перед обеденным перерывом температура кожи в подперчаточном пространстве возросла на 4,4°С, от 27 до 63% работниц жаловались на недостаточную эффективность СИЗ и неприятные ощущения<ref name="Денисов-2013" />. [[File:Butyl rubber gloves.JPG|thumb|right|300px|Перчатки из [[:w:Бутилкаучук|бутилкаучука]] газо- и влагонепроницаемы, обладают хорошими электроизолирующими свойствами, но не очень эластичны]] == СИЗ рук от химических веществ == Защитные свойства перчаток, высококачественных и сертифицированных, могут очень сильно зависеть от конкретного исполнения и условий применения. Сколько-нибудь точное прогнозирование степени и длительности защиты работника на основании результатов сертификационных испытаний при воздействии небольшого числа вредных веществ в строго определённых контролируемых лабораторных условиях невозможно. Из-за использования разными производителями разных технологий для изготовления перчаток из одного и того же материала, фактические защитные свойства у таких (сертифицированных) СИЗ разных моделей могут значительно отличаться. См. подробное описание в: [[Средства индивидуальной защиты (обзорная лекция)/СИЗ кожи от химических веществ|средства защиты кожи от химических веществ]]. == СИЗ рук от механических повреждений == Для защиты от порезов могут использоваться перчатки из прочных волокон, а при опасности сильных ударов - перчатки из маленьких металлических колец. Такие СИЗ могут надёжно защищать руки от ударов острыми предметами. Однако испытания разных моделей этих СИЗ на предприятиях показало, что их применение не всегда даёт лишь положительный эффект. Некоторые модели оказалось трудно очищать и дезинфицировать после загрязнения кровью и другими органическими материалами<ref name="Гущина-10-2-4" />. == Намокание, запотевание, снижение прочности и очистка == Рукавицы и перчатки из ткани могут быстро намокать, а в резиновых руки потеют<ref name="Гущина-2-4" />. Кожаные перчатки в этом отношении лучше, а использование резиновых не всегда может быть оправдано. При работе с кислотами, щелочами, растворителями и спиртами резина может набухать и терять прочность. СИЗ из синтетических материалов значительно лучше и прочнее, служат дольше - но руки в них потеют. В некоторых случаях может быть полезно надевать под них трикотажные перчатки.<ref name="СИЗ-2005-104" />. По данным<ref name="Гущина-7-1" /> после использования кислотозащитных перчаток в течение 10 смен их прочность снизилась на треть, произошло набухание полимера на 16%, и возросла кислотопроницаемость с 0 до 0,65 ед. pH. Воздействие ксилола на материал СКС-30НРКП привело к снижению прочности в 6,9 раз за 72 часа. Т.е. непроницаемые для токсичного вещества СИЗ могут разрушаться из-за механического воздействия при снижении прочности материала. Полноценная очистка СИЗ может оказаться невыполнимой из-за проникания молекул токсичного вещества вглубь материала СИЗ<ref name="Гущина-7-1" />. Если очистка будет выполняться при повышенной температуре, проникание может ускориться и усилиться. == Выбор СИЗ рук и длительность их применения == Разработаны международные рекомендации по выбору СИЗ рук при защите от различных вредных и опасных производственных факторов<ref name="ИСО-руки-выбор" />. В РФ допустимая максимальная продолжительность использования СИЗ рук не установлена; рекомендуемые специалистами<ref>{{Книга |автор=Файнбург Г.З., Порываев А.А. |заглавие=Процедуры обеспечения средствами индивидуальной защиты и ухода за ними. Учебное пособие |год=2025 |часть=Глава 7. Типичные вопросы и ответы по обеспечению средствами индивидуальной защиты |издание=2-е издание |место=Пермь |издательство=Издательство Пермского национального политехнического университета |страницы=91 |всего страниц=176 |серия=За достойный и безопасный труд. Выпуск 4 |isbn=978-5-398-03317-5 |тираж=50}}</ref> ограничения приводятся ниже. {| class="wikitable collapsible " style="text-align:center" ! Вид работы || Рекомендуемая продолжительность непрерывного применения |- | Медицинские процедуры || Один раз |- | Санитарная обработка || до 1 часа |- | Уборка и дезинфекция || до 2 часов |- | Работа с опасными веществами || до 4 часов |- | Кулинарные работы || до 2 часов |} == Примечания == {{примечания|refs= <ref name="СИЗ-2005-104">{{книга|автор=Файнбург Г.З., Овсянкин А.Д. |часть= 4.5 Средства защиты рук |заглавие=Использование средств индивидуальной защиты от неблагоприятного воздействия производственной среды |издание=7 изд., исправленное и дополненное |место= Пермь |издательство= Отдел публикаций Пермского областного центра охраны труда на базе [[:w:Пермский государственный университет| ПГТУ]]|год=2005 |страницы= 104-109 |всего страниц= 212|isbn= 5-88151-360-6 |серия= Рекомендовано Департаментом условий и охраны труда Минтруда России в качестве учебного пособия для обучения и проверки знаний работников по охране труда, включая обучение отдельных категорий застрахованных |ответственный=Рецензенты Радостев М.А. ''<small>(ЗАО «Пермь-Восток-Сервис»)</small>'', ктн Коротаев В.Ф. ''<small>(Пермский государственный технический университет)</small>''|тираж=1900|}}</ref> <ref name="виб+">{{Статья|ссылка=https://academic.oup.com/joh/article/54/3/250/7270356?login=false |автор=Matija Milosevic, Kristiina M Valter McConville|заглавие=Evaluation of protective gloves and working techniques for reducing hand-arm vibration exposure in the workplace|год=2012|язык=en|автор издания=Japan Society for Occupational Health|издание=Journal of Occupational Health|издательство=Oxford University Press|месяц=4|число=19|выпуск=3|pages=250-253|volume=54|issn=|doi=10.1539/joh.11-0176-br|pmid=}} ISSN 1348-9585, {{PMID|22790528}}. [https://academic.oup.com/joh/article-pdf/54/3/250/51956136/joh2054003011.pdf PDF]</ref> <ref name="виб-инстр">{{Книга|автор=Садчикова И.П., Смирнов В.Г.|заглавие=Безопасность труда|ответственный=Цуцков М.Е.|год=1978|часть=Динамика изменения вибрационных характеристик ручного инструмента в процессе эксплуатации|место=Москва|издательство=Профиздат|страницы=77-78|страниц=120|серия=Сборник научных работ институтов охраны труда ВЦСПС|тираж=5000}}</ref> <ref name="виб-HSE">{{Книга|ссылка=https://www.hse.gov.uk/pubns/books/hsg170.htm |автор=Health and Safety Executive|заглавие=Vibration solutions: Practical ways to reduce the risk of hand-arm vibration injury|ответственный=HSE|год=1997|часть=Gloves|язык=en|место=Richmond, Surrey|издательство=Crown|pages=11|allpages=107|серия=HSG170|isbn=978 0 7176 0954 3}} [https://www.hse.gov.uk/pubns/priced/hsg170.pdf PDF]</ref> <ref name="виб-US">''Division of Occupational Safety and Health''. [https://lni.wa.gov/safety-health/_docs/DoAntiVibrationGlovesPreventVibrationRelatedInjuries.pdf Do anti-vibration gloves prevent vibration-related injuries?] <small>(англ.)</small>. ''lni.wa.gov''. Washington, District of Columbia: Washington State Department of Labor & Industries. Дата обращения: 2 ноября 2024.</ref> <!-- Комментарий -->{{Cite web|url=https://lni.wa.gov/safety-health/_docs/DoAntiVibrationGlovesPreventVibrationRelatedInjuries.pdf|title=Do anti-vibration gloves prevent vibration-related injuries?|lang=en|author=Division of Occupational Safety and Health|website=lni.wa.gov|location=Washington, District of Columbia|publisher=Washington State Department of Labor & Industries|access-date=2024-11-02}} <ref name="Денисов-2013">{{Статья|ссылка=https://cyberleninka.ru/article/n/problema-realnoy-effektivnosti-individualnoy-zaschity-i-privnosimyy-risk-dlya-zdorovya-rabotnikov-obzor-literatury/viewer|автор=Денисов Э.И., Морозова Т.В., Аденинская Е.Е., Курьеров Н.Н.|заглавие=Проблема реальной эффективности индивидуальной защиты и привносимый риск для здоровья работников (обзор литературы)|год=2013|автор издания=НИИ медицины труда РАН|издание=Медицина труда и промышленная экология|месяц=8|номер=8|страницы=18-25|issn=|pmid=}} ISSN 1026-9428, {{PMID|24006620}}.</ref> <ref name="ИСО-руки-выбор">{{Книга|ссылка= https://standards.iteh.ai/catalog/standards/iso/595b9063-b055-4b86-95d3-424cb3eb4337/iso-tr-8546-2022 |автор=Technical Committee ISO/TC 94/SC 13 Protective clothing.|заглавие=ISO/TR 8546:2022 Hand protection — Guidance for selection and use|год=2022|язык=en|место=Geneva, Switzerland|издательство=International Organization for Standardization|allpages=31|серия=ISC 13.340.40 Hand and arm protection }}</ref> <ref name="Гущина-10-2-4">{{Книга |автор=Гущина Татьяна Викторовна |заглавие=Методология разработки и испытаний средств индивидуальной защиты |ответственный=рецензенты Киричек А.В., Шарупич Т.С. |год=2007 |часть=10.2.4 Эксплуатационные испытания защитных перчаток. В: 10 Производственная апробация средств индивидуальной защиты в условиях АПК, разработка рекомендаций. 10.2 Проведение производственных испытаний |место=Орёл |издательство=Издательство ОрёлГАУ |страницы=279 |всего страниц=330 |серия=Монография |тираж=100}} цитата:''"При эксплуатации армированных перчаток на Донецком мясокомбинате были выявлены негативные последствия: через полгода их применения у работников начались кожаные заболевания рук. ... Результаты исследований показали, что применяемый режим дезинфекции не пригоден для обработки данного вида изделий."''.</ref> <ref name="Гущина-2-4">{{Книга |автор=Гущина Татьяна Викторовна |заглавие=Методология разработки и испытаний средств индивидуальной защиты |ответственный=рецензенты Киричек А.В., Шарупич Т.С. |год=2007 |часть=2.4 Выращивание птицы промышленным способом. В: 2 Условия эксплуатации средств индивидуальной защиты и состояние производственного травматизма на агропромышленных предприятиях |место=Орёл |издательство=Издательство ОрёлГАУ |страницы=31 |всего страниц=330 |серия=Монография |тираж=100}}</ref> <ref name="Гущина-7-1">{{Книга |автор=Гущина Татьяна Викторовна |заглавие=Методология разработки и испытаний средств индивидуальной защиты |ответственный=рецензенты Киричек А.В., Шарупич Т.С. |год=2007 |часть=7.1 Условия безопасного применения агрохимикатов в сельском хозяйстве. В: 7 Обеспечение безопасности при применении средств защиты растений |место=Орёл |издательство=Издательство ОрёлГАУ |страницы=31 |всего страниц=330 |серия=Монография |тираж=100}}</ref> }} [[Категория:Средства индивидуальной защиты (обзорная лекция)]] {{Stub}} 0q1lsm42zvmyfykbzdzbg92n87kep1g Шаблон:ISBN 10 35914 270414 2026-10-27T06:55:53Z Jcb 79968 Новая страница: «<includeonly>[[Speciale:RicercaISBN/{{{1}}}|ISBN {{{1}}}]]</includeonly><noinclude>» 270414 wikitext text/x-wiki <includeonly>[[Speciale:RicercaISBN/{{{1}}}|ISBN {{{1}}}]]</includeonly><noinclude> 25b0siugrti6gb042pe5sx10npo9yjf Шаблон:PMID 10 35915 270416 2026-10-27T07:01:11Z Jcb 79968 Новая страница: «<includeonly>[https://www.ncbi.nlm.nih.gov/pubmed/{{{1}}} PMID {{{1}}}]</includeonly><noinclude>Use ''<nowiki>{{PMID|9733676}}</nowiki>'' instead of ''<nowiki>PMID 9733676</nowiki>'', to replace the deprecated magic links for sustainable code.</noinclude>» 270416 wikitext text/x-wiki <includeonly>[https://www.ncbi.nlm.nih.gov/pubmed/{{{1}}} PMID {{{1}}}]</includeonly><noinclude>Use ''<nowiki>{{PMID|9733676}}</nowiki>'' instead of ''<nowiki>PMID 9733676</nowiki>'', to replace the deprecated magic links for sustainable code.</noinclude> qxsv9inyk6exmdmx98zw1y0c8gi67n2 Шаблон:RFC 10 35916 270428 2026-10-27T07:10:31Z Jcb 79968 Новая страница: «<includeonly>[https://datatracker.ietf.org/doc/html/rfc{{{1}}} RFC&nbsp;{{{1}}}]</includeonly>» 270428 wikitext text/x-wiki <includeonly>[https://datatracker.ietf.org/doc/html/rfc{{{1}}} RFC&nbsp;{{{1}}}]</includeonly> ljegpqixl8x3qu5u73cf4ism6vgfnkd