library.md
1> **Источник:** https://python-all.ru/2.7/faq/library.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [Часто задаваемые вопросы по библиотекам и расширениям](https://python-all.ru/2.7/faq/library.html#id1)89Содержание1011- [FAQ по библиотекам и расширениям](https://python-all.ru/2.7/faq/library.html#library-and-extension-faq)1213 - [Общие вопросы по библиотекам](https://python-all.ru/2.7/faq/library.html#general-library-questions)1415 - [Как найти модуль или приложение для выполнения задачи X?](https://python-all.ru/2.7/faq/library.html#how-do-i-find-a-module-or-application-to-perform-task-x)16 - [Где находится исходный файл math.py (socket.py, regex.py и т.д.)?](https://python-all.ru/2.7/faq/library.html#where-is-the-math-py-socket-py-regex-py-etc-source-file)17 - [Как сделать скрипт Python исполняемым в Unix?](https://python-all.ru/2.7/faq/library.html#how-do-i-make-a-python-script-executable-on-unix)18 - [Существует ли пакет curses/termcap для Python?](https://python-all.ru/2.7/faq/library.html#is-there-a-curses-termcap-package-for-python)19 - [Есть ли в Python эквивалент onexit() из C?](https://python-all.ru/2.7/faq/library.html#is-there-an-equivalent-to-c-s-onexit-in-python)20 - [Почему не работают мои обработчики сигналов?](https://python-all.ru/2.7/faq/library.html#why-don-t-my-signal-handlers-work)21 - [Типовые задачи](https://python-all.ru/2.7/faq/library.html#common-tasks)2223 - [Как протестировать программу или компонент Python?](https://python-all.ru/2.7/faq/library.html#how-do-i-test-a-python-program-or-component)24 - [Как создать документацию из строк документации?](https://python-all.ru/2.7/faq/library.html#how-do-i-create-documentation-from-doc-strings)25 - [Как получить одиночное нажатие клавиши?](https://python-all.ru/2.7/faq/library.html#how-do-i-get-a-single-keypress-at-a-time)26 - [Потоки](https://python-all.ru/2.7/faq/library.html#threads)2728 - [Как программировать с использованием потоков?](https://python-all.ru/2.7/faq/library.html#how-do-i-program-using-threads)29 - [Ни один из моих потоков не запускается: почему?](https://python-all.ru/2.7/faq/library.html#none-of-my-threads-seem-to-run-why)30 - [Как распределить работу между несколькими рабочими потоками?](https://python-all.ru/2.7/faq/library.html#how-do-i-parcel-out-work-among-a-bunch-of-worker-threads)31 - [Какие виды изменения глобальных значений являются потокобезопасными?](https://python-all.ru/2.7/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe)32 - [Нельзя ли избавиться от глобальной блокировки интерпретатора (GIL)?](https://python-all.ru/2.7/faq/library.html#can-t-we-get-rid-of-the-global-interpreter-lock)33 - [Ввод и вывод](https://python-all.ru/2.7/faq/library.html#input-and-output)3435 - [Как удалить файл? (И другие вопросы о файлах…)](https://python-all.ru/2.7/faq/library.html#how-do-i-delete-a-file-and-other-file-questions)36 - [Как скопировать файл?](https://python-all.ru/2.7/faq/library.html#how-do-i-copy-a-file)37 - [Как читать (или записывать) двоичные данные?](https://python-all.ru/2.7/faq/library.html#how-do-i-read-or-write-binary-data)38 - [Не удаётся использовать os.read() на канале, созданном с помощью os.popen(); почему?](https://python-all.ru/2.7/faq/library.html#i-can-t-seem-to-use-os-read-on-a-pipe-created-with-os-popen-why)39 - [Как запустить подпроцесс с каналами, подключёнными и ко входу, и к выходу?](https://python-all.ru/2.7/faq/library.html#how-do-i-run-a-subprocess-with-pipes-connected-to-both-input-and-output)40 - [Как получить доступ к последовательному порту (RS232)?](https://python-all.ru/2.7/faq/library.html#how-do-i-access-the-serial-rs232-port)41 - [Почему закрытие sys.stdout (stdin, stderr) на самом деле не закрывает его?](https://python-all.ru/2.7/faq/library.html#why-doesn-t-closing-sys-stdout-stdin-stderr-really-close-it)42 - [Сетевое и интернет-программирование](https://python-all.ru/2.7/faq/library.html#network-internet-programming)4344 - [Какие существуют инструменты для работы с WWW в Python?](https://python-all.ru/2.7/faq/library.html#what-www-tools-are-there-for-python)45 - [Как имитировать отправку CGI-формы (METHOD=POST)?](https://python-all.ru/2.7/faq/library.html#how-can-i-mimic-cgi-form-submission-method-post)46 - [Какой модуль использовать для генерации HTML?](https://python-all.ru/2.7/faq/library.html#what-module-should-i-use-to-help-with-generating-html)47 - [Как отправить письмо из скрипта Python?](https://python-all.ru/2.7/faq/library.html#how-do-i-send-mail-from-a-python-script)48 - [Как избежать блокировки в методе connect() сокета?](https://python-all.ru/2.7/faq/library.html#how-do-i-avoid-blocking-in-the-connect-method-of-a-socket)49 - [Базы данных](https://python-all.ru/2.7/faq/library.html#databases)5051 - [Существуют ли интерфейсы к пакетам баз данных в Python?](https://python-all.ru/2.7/faq/library.html#are-there-any-interfaces-to-database-packages-in-python)52 - [Как реализовать постоянные объекты в Python?](https://python-all.ru/2.7/faq/library.html#how-do-you-implement-persistent-objects-in-python)53 - [Почему cPickle такой медленный?](https://python-all.ru/2.7/faq/library.html#why-is-cpickle-so-slow)54 - [Если моя программа аварийно завершается с открытой базой данных bsddb (или anydbm), она повреждается. Почему?](https://python-all.ru/2.7/faq/library.html#if-my-program-crashes-with-a-bsddb-or-anydbm-database-open-it-gets-corrupted-how-come)55 - [Я попытался открыть файл Berkeley DB, но bsddb выдаёт bsddb.error: (22, 'Invalid argument'). Помогите! Как восстановить данные?](https://python-all.ru/2.7/faq/library.html#i-tried-to-open-berkeley-db-file-but-bsddb-produces-bsddb-error-22-invalid-argument-help-how-can-i-restore-my-data)56 - [Математика и численные методы](https://python-all.ru/2.7/faq/library.html#mathematics-and-numerics)5758 - [Как генерировать случайные числа в Python?](https://python-all.ru/2.7/faq/library.html#how-do-i-generate-random-numbers-in-python)5960## [Общие вопросы по библиотекам](https://python-all.ru/2.7/faq/library.html#id2)6162### [Как найти модуль или приложение для выполнения задачи X?](https://python-all.ru/2.7/faq/library.html#id3)6364Проверьте [справочник библиотеки](https://python-all.ru/2.7/library/index.html#library-index), чтобы узнать, есть ли подходящий модуль в стандартной библиотеке. (Со временем вы запомните, что входит в стандартную библиотеку, и сможете пропустить этот шаг.)6566Для сторонних пакетов выполните поиск в [Python Package Index](https://python-all.ru/2.7/faq/library.html) или воспользуйтесь [Google](https://python-all.ru/2.7/faq/library.html) или другой поисковой системой. Обычно поиск по «Python» с одним-двумя ключевыми словами по вашей теме находит что-нибудь полезное.6768### [Где находится исходный файл math.py (socket.py, regex.py и т. д.)?](https://python-all.ru/2.7/faq/library.html#id4)6970Если не удаётся найти исходный файл модуля, возможно, он встроенный или динамически загружаемый модуль, реализованный на C, C++ или другом компилируемом языке. В этом случае исходного файла может не быть, или он находится, например, в `mathmodule.c`, где-то в каталоге с исходниками на C (не на Python Path).7172В Python существует (как минимум) три вида модулей:73741. модули, написанные на Python (.py);752. модули, написанные на C и динамически загружаемые (.dll, .pyd, .so, .sl и т. д.);763. модули, написанные на C и связанные с интерпретатором; чтобы получить их список, введите:7778 ```python79 import sys80 print sys.builtin_module_names81 ```8283### [Как сделать скрипт Python исполняемым в Unix?](https://python-all.ru/2.7/faq/library.html#id5)8485Нужно сделать две вещи: установить исполняемый режим для файла скрипта и убедиться, что первая строка начинается с `#!`, за которым следует путь к интерпретатору Python.8687Первое выполняется командой `chmod +x scriptfile` или, возможно, `chmod 755 scriptfile`.8889Второе можно сделать несколькими способами. Самый простой – написать9091```python92#!/usr/local/bin/python93```9495в самой первой строке файла, указав путь к установленному на вашей платформе интерпретатору Python.9697Если вы хотите, чтобы скрипт не зависел от расположения интерпретатора Python, используйте программу **env**. Почти все варианты Unix поддерживают следующее, при условии, что интерпретатор Python находится в каталоге, входящем в `PATH` пользователя:9899```python100#!/usr/bin/env python101```102103*Не* делайте этого для CGI-скриптов. Переменная `PATH` для CGI-скриптов часто очень ограничена, поэтому нужно указывать полный абсолютный путь к интерпретатору.104105Иногда окружение пользователя настолько переполнено, что программа **/usr/bin/env** завершается с ошибкой; или программы env вообще нет. В таком случае можно попробовать следующий трюк (благодаря Алексу Резински):106107```python108#! /bin/sh109""":"110exec python $0 ${1+"$@"}111"""112```113114Небольшой недостаток в том, что при этом определяется строка документации \_\_doc\_\_ скрипта. Однако это можно исправить, добавив115116```python117__doc__ = """...Whatever..."""118```119120### [Существует ли пакет curses/termcap для Python?](https://python-all.ru/2.7/faq/library.html#id6)121122Для Unix-подобных систем в стандартном дистрибутиве Python есть модуль curses в поддиректории [Modules](https://python-all.ru/src/2.7/Modules), но он не компилируется по умолчанию. (Обратите внимание: в дистрибутиве для Windows его нет – модуля curses для Windows не существует.)123124Модуль [`curses`](https://python-all.ru/2.7/library/curses.html#module-curses) поддерживает базовые возможности curses, а также многие дополнительные функции из ncurses и SYSV curses, такие как цвет, поддержка альтернативных наборов символов, подокна и поддержка мыши. Это означает, что модуль несовместим с операционными системами, где есть только BSD curses, но сейчас, похоже, нет поддерживаемых ОС, попадающих в эту категорию.125126Для Windows: используйте [модуль consolelib](https://python-all.ru/2.7/faq/library.html).127128### [Есть ли в Python аналог onexit() из C?](https://python-all.ru/2.7/faq/library.html#id7)129130Модуль [`atexit`](https://python-all.ru/2.7/library/atexit.html#module-atexit) предоставляет функцию register, похожую на `onexit()` из C.131132### [Почему не работают мои обработчики сигналов?](https://python-all.ru/2.7/faq/library.html#id8)133134Самая распространённая проблема – обработчик сигнала объявлен с неправильным списком аргументов. Он вызывается как135136```python137handler(signum, frame)138```139140поэтому он должен быть объявлен с двумя аргументами:141142```python143def handler(signum, frame):144 ...145```146147## [Типовые задачи](https://python-all.ru/2.7/faq/library.html#id9)148149### [Как тестировать программу или компонент Python?](https://python-all.ru/2.7/faq/library.html#id10)150151В состав Python входят две тестовые платформы. Модуль [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) находит примеры в строках документации модуля и запускает их, сравнивая вывод с ожидаемым выводом, указанным в строке документации.152153Модуль [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) – это более продвинутая тестовая платформа, созданная по образцу тестовых платформ Java и Smalltalk.154155Чтобы упростить тестирование, используйте в программе хорошую модульную архитектуру. Почти вся функциональность должна быть инкапсулирована в функции или методы классов – и это иногда неожиданно и приятно ускоряет работу программы (потому что доступ к локальным переменным быстрее, чем к глобальным). Кроме того, программа не должна зависеть от изменения глобальных переменных, поскольку это сильно усложняет тестирование.156157«Глобальная основная логика» вашей программы может быть такой же простой, как158159```python160if __name__ == "__main__":161 main_logic()162```163164в конце главного модуля программы.165166Когда программа организована как управляемая коллекция функций и поведений классов, следует написать тестовые функции, которые проверяют эти поведения. Тестовый набор, автоматизирующий последовательность тестов, можно связать с каждым модулем. Это звучит как большая работа, но, поскольку Python так краток и гибок, это оказывается удивительно легко. Писать код становится гораздо приятнее и веселее, если создавать тестовые функции параллельно с «рабочим кодом», поскольку это позволяет раньше находить ошибки и даже проектные недостатки.167168«Вспомогательные модули», не предназначенные для роли главного модуля программы, могут включать самопроверку модуля.169170```python171if __name__ == "__main__":172 self_test()173```174175Даже программы, взаимодействующие со сложными внешними интерфейсами, могут быть протестированы в отсутствие этих интерфейсов с помощью «фиктивных» интерфейсов, реализованных на Python.176177### [Как создавать документацию из строк документации?](https://python-all.ru/2.7/faq/library.html#id11)178179Модуль [`pydoc`](https://python-all.ru/2.7/library/pydoc.html#module-pydoc) может создавать HTML из строк документации в исходном коде Python. Альтернативой для создания API-документации исключительно по docstrings является [epydoc](https://python-all.ru/2.7/faq/library.html). [Sphinx](https://python-all.ru/2.7/faq/library.html) также может включать содержимое docstring.180181### [Как получить нажатие одной клавиши за раз?](https://python-all.ru/2.7/faq/library.html#id12)182183Для Unix-подобных систем есть несколько решений. Проще всего это сделать с помощью curses, но curses – довольно объёмный модуль, который нужно изучать. Вот решение без curses:184185```python186import termios, fcntl, sys, os187fd = sys.stdin.fileno()188189oldterm = termios.tcgetattr(fd)190newattr = termios.tcgetattr(fd)191newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO192termios.tcsetattr(fd, termios.TCSANOW, newattr)193194oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)195fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)196197try:198 while 1:199 try:200 c = sys.stdin.read(1)201 print "Got character", repr(c)202 except IOError: pass203finally:204 termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)205 fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)206```207208Для работы всего этого понадобятся модули [`termios`](https://python-all.ru/2.7/library/termios.html#module-termios) и [`fcntl`](https://python-all.ru/2.7/library/fcntl.html#module-fcntl), и я проверял это только на Linux, хотя должно работать и в других системах. В этом коде символы читаются и выводятся по одному.209210[`termios.tcsetattr()`](https://python-all.ru/2.7/library/termios.html#termios.tcsetattr) отключает эхо-вывод stdin и отключает канонический режим. `fcntl.fnctl()` используется для получения флагов файлового дескриптора stdin и их изменения для неблокирующего режима. Поскольку чтение из пустого stdin вызывает [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError), эта ошибка перехватывается и игнорируется.211212## [Потоки](https://python-all.ru/2.7/faq/library.html#id13)213214### [Как программировать с помощью потоков?](https://python-all.ru/2.7/faq/library.html#id14)215216Обязательно используйте модуль [`threading`](https://python-all.ru/2.7/library/threading.html#module-threading), а не модуль [`thread`](https://python-all.ru/2.7/library/thread.html#module-thread). Модуль [`threading`](https://python-all.ru/2.7/library/threading.html#module-threading) создаёт удобные абстракции поверх низкоуровневых примитивов, предоставляемых модулем [`thread`](https://python-all.ru/2.7/library/thread.html#module-thread).217218У Aahz есть набор слайдов из его руководства по многопоточности, которые могут быть полезны; см. [http://www.pythoncraft.com/OSCON2001/](https://python-all.ru/2.7/faq/library.html).219220### [Почему ни один из моих потоков не выполняется?](https://python-all.ru/2.7/faq/library.html#id15)221222Как только главный поток завершается, все потоки уничтожаются. Главный поток выполняется слишком быстро, не давая потокам времени на работу.223224Простое исправление – добавить в конец программы задержку, достаточно длинную для завершения всех потоков:225226```python227import threading, time228229def thread_task(name, n):230 for i in range(n): print name, i231232for i in range(10):233 T = threading.Thread(target=thread_task, args=(str(i), i))234 T.start()235236time.sleep(10) # <----------------------------!237```238239Но теперь (на многих платформах) потоки не выполняются параллельно, а, похоже, выполняются последовательно, один за другим! Причина в том, что планировщик потоков ОС не запускает новый поток, пока предыдущий не заблокирован.240241Простое исправление – добавить небольшую задержку в начало функции run:242243```python244def thread_task(name, n):245 time.sleep(0.001) # <---------------------!246 for i in range(n): print name, i247248for i in range(10):249 T = threading.Thread(target=thread_task, args=(str(i), i))250 T.start()251252time.sleep(10)253```254255Вместо попыток угадать подходящее значение задержки для [`time.sleep()`](https://python-all.ru/2.7/library/time.html#time.sleep) лучше использовать какой-нибудь семафорный механизм. Одна из идей – использовать модуль [`Queue`](https://python-all.ru/2.7/library/queue.html#module-Queue) для создания объекта очереди, позволить каждому потоку добавлять токен в очередь по завершении, а главному потоку – читать из очереди столько токенов, сколько потоков.256257### [Как распределить работу между несколькими рабочими потоками?](https://python-all.ru/2.7/faq/library.html#id16)258259Используйте модуль [`Queue`](https://python-all.ru/2.7/library/queue.html#module-Queue) для создания очереди со списком заданий. Класс [`Queue`](https://python-all.ru/2.7/library/queue.html#Queue.Queue) ведёт список объектов и имеет метод `.put(obj)`, добавляющий элементы в очередь, и метод `.get()`, возвращающий их. Класс сам позаботится о блокировках, необходимых, чтобы каждое задание было выдано ровно один раз.260261Вот простой пример:262263```python264import threading, Queue, time265266# Рабочий поток забирает задания из очереди. Когда очередь пуста, он267# предполагает, что больше работы не будет, и завершается.268# (На практике рабочие потоки работают до принудительного завершения.)269def worker():270 print 'Running worker'271 time.sleep(0.1)272 while True:273 try:274 arg = q.get(block=False)275 except Queue.Empty:276 print 'Worker', threading.currentThread(),277 print 'queue empty'278 break279 else:280 print 'Worker', threading.currentThread(),281 print 'running with argument', arg282 time.sleep(0.5)283284# Создать очередь285q = Queue.Queue()286287# Запустить пул из 5 рабочих потоков288for i in range(5):289 t = threading.Thread(target=worker, name='worker %i' % (i+1))290 t.start()291292# Начать добавление заданий в очередь293for i in range(50):294 q.put(i)295296# Дать потокам время на выполнение297print 'Main thread sleeping'298time.sleep(5)299```300301При запуске это выдаст следующий вывод:302303```text304Running worker305Running worker306Running worker307Running worker308Running worker309Main thread sleeping310Worker <Thread(worker 1, started)> running with argument 0311Worker <Thread(worker 2, started)> running with argument 1312Worker <Thread(worker 3, started)> running with argument 2313Worker <Thread(worker 4, started)> running with argument 3314Worker <Thread(worker 5, started)> running with argument 4315Worker <Thread(worker 1, started)> running with argument 5316...317```318319Обратитесь к документации модуля за подробностями; класс [`Queue`](https://python-all.ru/2.7/library/queue.html#Queue.Queue) предоставляет многофункциональный интерфейс.320321### [Какие виды изменения глобальных значений потокобезопасны?](https://python-all.ru/2.7/faq/library.html#id17)322323Внутри Python используется [глобальная блокировка интерпретатора](https://python-all.ru/2.7/glossary.html#term-global-interpreter-lock) (GIL), чтобы гарантировать, что в виртуальной машине Python в каждый момент времени выполняется только один поток. В общем случае Python переключается между потоками только между инструкциями байт-кода; частоту переключений можно задать через [`sys.setcheckinterval()`](https://python-all.ru/2.7/library/sys.html#sys.setcheckinterval). Каждая инструкция байт-кода, а значит, и весь код на C, выполняемый для этой инструкции, является атомарным с точки зрения программы на Python.324325Теоретически это означает, что точный учёт требует точного понимания реализации байткода виртуальной машины Python. На практике это означает, что операции над совместно используемыми переменными встроенных типов (int, list, dict и т.д.), которые «выглядят атомарными», действительно атомарны.326327Например, следующие операции атомарны (L, L1, L2 – списки, D, D1, D2 – словари, x, y – объекты, i, j – целые числа):328329```python330L.append(x)331L1.extend(L2)332x = L[i]333x = L.pop()334L1[i:j] = L2335L.sort()336x = y337x.field = y338D[x] = y339D1.update(D2)340D.keys()341```342343А эти – нет:344345```python346i = i+1347L.append(L[-1])348L[i] = L[j]349D[x] = D[x] + 1350```351352Операции, заменяющие другие объекты, могут вызывать метод [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) этих объектов, когда счётчик ссылок достигает нуля, и это может повлиять на другие вещи. Особенно это касается массовых обновлений словарей и списков. Если есть сомнения, используйте мьютекс!353354### [Нельзя ли избавиться от глобальной блокировки интерпретатора?](https://python-all.ru/2.7/faq/library.html#id18)355356[Глобальная блокировка интерпретатора](https://python-all.ru/2.7/glossary.html#term-global-interpreter-lock) (GIL) часто считается помехой для развёртывания Python на высокопроизводительных многопроцессорных серверных машинах, поскольку многопоточная программа на Python фактически использует только один процессор из-за требования, что (почти) весь код Python может выполняться только при удерживаемом GIL.357358Во времена Python 1.5 Грег Штайн (Greg Stein) реализовал обширный набор патчей (патчи «free threading»), который удалял GIL и заменял его мелкозернистой блокировкой. К сожалению, даже в Windows (где блокировки очень эффективны) это приводило к тому, что обычный код на Python работал примерно вдвое медленнее, чем интерпретатор с GIL. В Linux падение производительности было ещё больше, потому что блокировки pthread не так эффективны.359360С тех пор идея избавиться от GIL время от времени всплывала, но никто не нашёл способа справиться с ожидаемым замедлением, а пользователям, не использующим потоки, вряд ли понравится, если их код будет работать вдвое медленнее. Набор патчей Грега (Greg) для свободной многопоточности не поддерживался для более поздних версий Python.361362Это не значит, что вы не можете эффективно использовать Python на многоядерных машинах! Просто нужно творчески подойти к разделению работы между несколькими *процессами*, а не несколькими *потоками*. Разумное использование расширений на C также поможет; если использовать расширение C для выполнения длительной задачи, расширение может освободить GIL, пока поток выполнения находится в C-коде, и позволить другим потокам выполнить некоторую работу.363364Высказывались предложения сделать GIL блокировкой на уровне состояния интерпретатора, а не глобальной; тогда интерпретаторы не смогли бы обмениваться объектами. К сожалению, это тоже вряд ли произойдёт. Это потребовало бы огромного объёма работы, поскольку многие реализации объектов в настоящее время используют глобальное состояние. Например, небольшие целые числа и короткие строки кэшируются; эти кэши пришлось бы перенести в состояние интерпретатора. Другие типы объектов имеют свои собственные списки свободной памяти; эти списки также пришлось бы перенести. И так далее.365366И я сомневаюсь, что это вообще можно сделать за конечное время, потому что та же проблема существует и для сторонних расширений. Скорее всего, сторонние расширения пишутся быстрее, чем вы успеваете переделывать их для хранения всего глобального состояния в состоянии интерпретатора.367368И наконец, если у вас есть несколько интерпретаторов, не разделяющих состояние, что вы выигрываете по сравнению с запуском каждого интерпретатора в отдельном процессе?369370## [Ввод и вывод](https://python-all.ru/2.7/faq/library.html#id19)371372### [Как удалить файл? (И другие вопросы о файлах…)](https://python-all.ru/2.7/faq/library.html#id20)373374Используйте `os.remove(filename)` или `os.unlink(filename)`; документацию смотрите в модуле [`os`](https://python-all.ru/2.7/library/os.html#module-os). Эти две функции идентичны; `unlink()` – просто имя системного вызова Unix для этой функции.375376Чтобы удалить каталог, используйте [`os.rmdir()`](https://python-all.ru/2.7/library/os.html#os.rmdir); для создания используйте [`os.mkdir()`](https://python-all.ru/2.7/library/os.html#os.mkdir). `os.makedirs(path)` создаст все промежуточные каталоги в `path`, которые не существуют. `os.removedirs(path)` удалит промежуточные каталоги, если они пусты; если нужно удалить всё дерево каталогов и его содержимое, используйте [`shutil.rmtree()`](https://python-all.ru/2.7/library/shutil.html#shutil.rmtree).377378Чтобы переименовать файл, используйте `os.rename(old_path, new_path)`.379380Чтобы урезать файл, откройте его с помощью `f = open(filename, "r+")` и используйте `f.truncate(offset)`; смещение по умолчанию равно текущей позиции. Также есть `os.ftruncate(fd, offset)` для файлов, открытых с помощью [`os.open()`](https://python-all.ru/2.7/library/os.html#os.open), где *fd* – это файловый дескриптор (небольшое целое число).381382Модуль [`shutil`](https://python-all.ru/2.7/library/shutil.html#module-shutil) также содержит ряд функций для работы с файлами, включая [`copyfile()`](https://python-all.ru/2.7/library/shutil.html#shutil.copyfile), [`copytree()`](https://python-all.ru/2.7/library/shutil.html#shutil.copytree) и [`rmtree()`](https://python-all.ru/2.7/library/shutil.html#shutil.rmtree).383384### [Как скопировать файл?](https://python-all.ru/2.7/faq/library.html#id21)385386Модуль [`shutil`](https://python-all.ru/2.7/library/shutil.html#module-shutil) содержит функцию [`copyfile()`](https://python-all.ru/2.7/library/shutil.html#shutil.copyfile). Обратите внимание, что на MacOS 9 она не копирует вилку ресурсов и информацию Finder.387388### [Как читать (или записывать) двоичные данные?](https://python-all.ru/2.7/faq/library.html#id22)389390Для чтения или записи сложных двоичных форматов данных лучше всего использовать модуль [`struct`](https://python-all.ru/2.7/library/struct.html#module-struct). Он позволяет взять строку, содержащую двоичные данные (обычно числа), и преобразовать её в объекты Python; и наоборот.391392Например, следующий код читает из файла два 2-байтовых целых числа и одно 4-байтовое целое число в формате big-endian:393394```python395import struct396397f = open(filename, "rb") # Открыть в бинарном режиме для переносимости398s = f.read(8)399x, y, z = struct.unpack(">hhl", s)400```401402Символ ‘\>’ в строке формата указывает на порядок байтов big-endian; буква ‘h’ читает одно «короткое целое» (2 байта), а ‘l’ – одно «длинное целое» (4 байта) из строки.403404Для данных, которые являются более регулярными (например, однородный список целых или чисел с плавающей запятой), можно также использовать модуль [`array`](https://python-all.ru/2.7/library/array.html#module-array).405406### [Не удаётся использовать os.read() для канала, созданного с помощью os.popen(); почему?](https://python-all.ru/2.7/faq/library.html#id23)407408[`os.read()`](https://python-all.ru/2.7/library/os.html#os.read) – это низкоуровневая функция, которая принимает файловый дескриптор – небольшое целое число, представляющее открытый файл. [`os.popen()`](https://python-all.ru/2.7/library/os.html#os.popen) создаёт высокоуровневый файловый объект того же типа, что возвращается встроенной функцией [`open()`](https://python-all.ru/2.7/library/functions.html#open). Таким образом, чтобы прочитать *n* байт из канала *p*, созданного с помощью [`os.popen()`](https://python-all.ru/2.7/library/os.html#os.popen), нужно использовать `p.read(n)`.409410### [Как запустить подпроцесс с каналами, подключёнными и ко входу, и к выходу?](https://python-all.ru/2.7/faq/library.html#id24)411412Используйте модуль [`popen2`](https://python-all.ru/2.7/library/popen2.html#module-popen2). Например:413414```python415import popen2416fromchild, tochild = popen2.popen2("command")417tochild.write("input\n")418tochild.flush()419output = fromchild.readline()420```421422Предупреждение: в общем случае так делать не стоит, потому что легко возникает взаимоблокировка (deadlock), когда ваш процесс заблокирован в ожидании вывода дочернего процесса, а дочерний процесс заблокирован в ожидании ввода от вас. Это может произойти, если родитель ожидает от дочернего процесса больше текста, чем тот выводит, или если данные застревают в буферах stdio из-за отсутствия сброса. Родительский процесс на Python, конечно, может явно сбросить данные, отправляемые дочернему процессу перед чтением любого вывода, но если дочерний процесс – простая программа на C, она может быть написана так, что никогда явно не сбрасывает свой вывод, даже если работает в интерактивном режиме, так как сброс обычно происходит автоматически.423424Обратите внимание, что взаимоблокировка возможна и при использовании `popen3()` для чтения stdout и stderr. Если один из двух потоков слишком велик для внутреннего буфера (увеличение размера буфера не помогает) и вы `read()` другой поток первым, то тоже возникает взаимоблокировка.425426Замечание об ошибке в popen2: пока программа не вызовет `wait()` или `waitpid()`, завершённые дочерние процессы никогда не удаляются, и в конечном счёте вызовы popen2 будут завершаться с ошибкой из-за ограничения на количество дочерних процессов. Вызов [`os.waitpid()`](https://python-all.ru/2.7/library/os.html#os.waitpid) с опцией [`os.WNOHANG`](https://python-all.ru/2.7/library/os.html#os.WNOHANG) может это предотвратить; хорошее место для такого вызова – перед повторным вызовом `popen2`.427428Во многих случаях всё, что нужно – пропустить данные через команду и получить результат обратно. Если объём данных не слишком велик, проще всего записать их во временный файл и запустить команду, используя этот временный файл как входные данные. Стандартный модуль [`tempfile`](https://python-all.ru/2.7/library/tempfile.html#module-tempfile) предоставляет функцию [`mktemp()`](https://python-all.ru/2.7/library/tempfile.html#tempfile.mktemp) для генерации уникальных имён временных файлов.429430```python431import tempfile432import os433434class Popen3:435 """436 Это безопасная с точки зрения взаимоблокировок версия popen, которая возвращает437 объект с errorlevel, out (строка) и err (строка).438 (capturestderr может не работать в Windows.)439 Пример: print Popen3('grep spam','\n\nhere spam\n\n').out440 """441 def __init__(self,command,input=None,capturestderr=None):442 outfile=tempfile.mktemp()443 command="( %s ) > %s" % (command,outfile)444 if input:445 infile=tempfile.mktemp()446 open(infile,"w").write(input)447 command=command+" <"+infile448 if capturestderr:449 errfile=tempfile.mktemp()450 command=command+" 2>"+errfile451 self.errorlevel=os.system(command) >> 8452 self.out=open(outfile,"r").read()453 os.remove(outfile)454 if input:455 os.remove(infile)456 if capturestderr:457 self.err=open(errfile,"r").read()458 os.remove(errfile)459```460461Имейте в виду, что многие интерактивные программы (например, vi) плохо работают, если вместо стандартного ввода и вывода подставлены каналы. Придётся использовать псевдотерминалы («ptys») вместо каналов. Или можно воспользоваться интерфейсом Python к библиотеке «expect» Дона Лайбса. Расширение Python для expect называется «expy» и доступно по адресу [http://expectpy.sourceforge.net](https://python-all.ru/2.7/faq/library.html). Чистое решение на Python, работающее как expect, – [pexpect](https://python-all.ru/2.7/faq/library.html).462463### [Как получить доступ к последовательному порту (RS232)?](https://python-all.ru/2.7/faq/library.html#id25)464465Для Win32, POSIX (Linux, BSD и т. д.), Jython:466467> [http://pyserial.sourceforge.net](https://python-all.ru/2.7/faq/library.html)468469Для Unix смотрите сообщение в Usenet от Митча Чепмена:470471> [https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com](https://python-all.ru/2.7/faq/library.html)472473### [Почему закрытие sys.stdout (stdin, stderr) на самом деле не закрывает его?](https://python-all.ru/2.7/faq/library.html#id26)474475Файловые объекты Python – это высокоуровневый слой абстракции над потоками C, которые, в свою очередь, являются среднеуровневым слоем абстракции над (в числе прочего) низкоуровневыми файловыми дескрипторами C.476477Для большинства файловых объектов, создаваемых в Python с помощью конструктора `file`, вызов `f.close()` помечает файловый объект Python как закрытый с точки зрения Python, а также инициирует закрытие лежащего в основе потока C. Это также происходит автоматически в деструкторе `f`, когда `f` становится мусором.478479Но stdin, stdout и stderr обрабатываются Python особым образом из-за особого статуса, который им присваивает C. Вызов `sys.stdout.close()` помечает файловый объект на уровне Python как закрытый, но *не* закрывает соответствующий поток C.480481Чтобы закрыть лежащий в основе поток C для одного из этих трёх, сначала стоит убедиться, что это действительно нужно (например, это может запутать расширения, пытающиеся выполнять ввод-вывод). Если всё же нужно, используйте os.close:482483```python484os.close(0) # закрыть поток stdin C485os.close(1) # закрыть поток stdout C486os.close(2) # закрыть поток stderr C487```488489## [Сетевое и интернет-программирование](https://python-all.ru/2.7/faq/library.html#id27)490491### [Какие WWW-инструменты есть для Python?](https://python-all.ru/2.7/faq/library.html#id28)492493Смотрите главы [Интернет-протоколы и поддержка](https://python-all.ru/2.7/library/internet.html#internet) и [Обработка интернет-данных](https://python-all.ru/2.7/library/netdata.html#netdata) в Справочном руководстве по библиотеке Python. В Python есть много модулей, которые помогут создать веб-системы как на стороне сервера, так и на стороне клиента.494495Сводка доступных фреймворков поддерживается Полом Бодди на\\n[https://wiki.python.org/moin/WebProgramming](https://python-all.ru/2.7/faq/library.html).496497Кэмерон Лэрд поддерживает полезный набор страниц о веб-технологиях Python по адресу [http://phaseit.net/claird/comp.lang.python/web\_python](https://python-all.ru/2.7/faq/library.html).498499### [Как имитировать отправку CGI-формы (METHOD=POST)?](https://python-all.ru/2.7/faq/library.html#id29)500501Мне нужно получать веб-страницы, которые появляются после отправки формы. Существует ли готовый код, позволяющий это сделать?502503Да. Вот простой пример с использованием httplib:504505```python506#!/usr/local/bin/python507508import httplib, sys, time509510# сформировать строку запроса511qs = "First=Josephine&MI=Q&Last=Public"512513# подключиться и отправить серверу путь514httpobj = httplib.HTTP('www.some-server.out-there', 80)515httpobj.putrequest('POST', '/cgi-bin/some-cgi-script')516# теперь сгенерировать остальные заголовки HTTP...517httpobj.putheader('Accept', '*/*')518httpobj.putheader('Connection', 'Keep-Alive')519httpobj.putheader('Content-type', 'application/x-www-form-urlencoded')520httpobj.putheader('Content-length', '%d' % len(qs))521httpobj.endheaders()522httpobj.send(qs)523# узнать, что сервер ответил...524reply, msg, hdrs = httpobj.getreply()525if reply != 200:526 sys.stdout.write(httpobj.getfile().read())527```528529Обратите внимание, что в целом для POST-операций с процентным кодированием строки запроса должны быть экранированы с помощью [`urllib.urlencode()`](https://python-all.ru/2.7/library/urllib.html#urllib.urlencode). Например, чтобы отправить `name=Guy Steele, Jr.`:530531```python532>>> import urllib533>>> urllib.urlencode({'name': 'Guy Steele, Jr.'})534'name=Guy+Steele%2C+Jr.'535```536537### [Какой модуль использовать для генерации HTML?](https://python-all.ru/2.7/faq/library.html#id30)538539Вы можете найти подборку полезных ссылок на [вики-странице Web Programming](https://python-all.ru/2.7/faq/library.html).540541### [Как отправить письмо из скрипта Python?](https://python-all.ru/2.7/faq/library.html#id31)542543Используйте модуль стандартной библиотеки [`smtplib`](https://python-all.ru/2.7/library/smtplib.html#module-smtplib).544545Вот очень простой интерактивный отправитель почты, использующий этот модуль. Этот метод будет\\nработать на любом хосте, поддерживающем SMTP-слушатель.546547```python548import sys, smtplib549550fromaddr = raw_input("From: ")551toaddrs = raw_input("To: ").split(',')552print "Enter message, end with ^D:"553msg = ''554while True:555 line = sys.stdin.readline()556 if not line:557 break558 msg += line559560# Непосредственная отправка письма561server = smtplib.SMTP('localhost')562server.sendmail(fromaddr, toaddrs, msg)563server.quit()564```565566Альтернатива, доступная только в Unix, использует sendmail. Расположение программы sendmail различается в разных системах: иногда это `/usr/lib/sendmail`, иногда\\n`/usr/sbin/sendmail`. Страница руководства sendmail поможет разобраться. Вот пример кода:567568```python569import os570571SENDMAIL = "/usr/sbin/sendmail" # Расположение sendmail572p = os.popen("%s -t -i" % SENDMAIL, "w")573p.write("To: receiver@example.com\n")574p.write("Subject: test\n")575p.write("\n") # Пустая строка, отделяющая заголовки от тела576p.write("Some text\n")577p.write("some more text\n")578sts = p.close()579if sts != 0:580 print "Sendmail exit status", sts581```582583### [Как избежать блокировки в методе connect() сокета?](https://python-all.ru/2.7/faq/library.html#id32)584585Модуль select часто используется для организации асинхронного ввода-вывода через сокеты.586587Чтобы предотвратить блокировку при TCP-подключении, можно перевести сокет в неблокирующий режим. Затем при вызове `connect()` соединение либо установится сразу (маловероятно), либо будет получено исключение, содержащее номер ошибки в `.errno`. `errno.EINPROGRESS` означает, что соединение устанавливается, но ещё не завершено. В разных ОС возвращаются разные значения, поэтому потребуется проверить, что возвращается в вашей системе.588589Можно использовать метод `connect_ex()`, чтобы избежать создания исключения. Он просто вернёт значение errno. Для опроса можно вызвать `connect_ex()` позже – 0 или `errno.EISCONN` означают, что соединение установлено – или передать этот сокет в select, чтобы проверить, доступен ли он для записи.590591## [Базы данных](https://python-all.ru/2.7/faq/library.html#id33)592593### [Существуют ли интерфейсы к пакетам баз данных в Python?](https://python-all.ru/2.7/faq/library.html#id34)594595Да.596597Python 2.3 включает пакет [`bsddb`](https://python-all.ru/2.7/library/bsddb.html#module-bsddb), предоставляющий интерфейс к библиотеке BerkeleyDB. В стандартный Python также входят интерфейсы к хэш-таблицам на диске, таким как [`DBM`](https://python-all.ru/2.7/library/dbm.html#module-dbm) и [`GDBM`](https://python-all.ru/2.7/library/gdbm.html#module-gdbm).598599Доступна поддержка большинства реляционных баз данных. Подробнее см. на [вики-странице DatabaseProgramming](https://python-all.ru/2.7/faq/library.html).600601### [Как реализовать постоянные объекты в Python?](https://python-all.ru/2.7/faq/library.html#id35)602603Модуль библиотеки [`pickle`](https://python-all.ru/2.7/library/pickle.html#module-pickle) решает эту задачу очень общим образом (хотя по-прежнему нельзя хранить такие вещи, как открытые файлы, сокеты или окна), а модуль библиотеки [`shelve`](https://python-all.ru/2.7/library/shelve.html#module-shelve) использует pickle и (g)dbm для создания постоянных отображений, содержащих произвольные объекты Python. Для повышения производительности можно использовать модуль [`cPickle`](https://python-all.ru/2.7/library/pickle.html#module-cPickle).604605Более громоздкий способ – использовать младшую сестру pickle – marshal. Модуль [`marshal`](https://python-all.ru/2.7/library/marshal.html#module-marshal) предоставляет очень быстрые способы сохранения нециклических базовых типов Python в файлы и строки и обратной загрузки. Хотя marshal не умеет таких вещей, как сохранение экземпляров классов или корректную обработку общих ссылок, он работает чрезвычайно быстро. Например, загрузка полмегабайта данных может занять меньше трети секунды. Часто это быстрее, чем использовать что-то более сложное и универсальное, например gdbm с pickle/shelve.606607### [Почему cPickle такой медленный?](https://python-all.ru/2.7/faq/library.html#id36)608609По умолчанию [`pickle`](https://python-all.ru/2.7/library/pickle.html#module-pickle) использует относительно старый и медленный формат для обратной совместимости. Однако можно указать другие версии протокола, которые работают быстрее:610611```python612largeString = 'z' * (100 * 1024)613myPickle = cPickle.dumps(largeString, protocol=1)614```615616### [Если моя программа аварийно завершилась с открытой базой данных bsddb (или anydbm), она повреждается. Почему?](https://python-all.ru/2.7/faq/library.html#id37)617618Базы данных, открытые для записи с помощью модуля bsddb (а часто и модуля anydbm, поскольку он предпочитает bsddb), должны быть явно закрыты с помощью метода `.close()` базы данных. Лежащая в основе библиотека кэширует содержимое базы данных, которое нужно преобразовать в форму, пригодную для записи на диск, и записать.619620Если вы инициализировали новую базу данных bsddb, но ничего в неё не записали до сбоя программы, в результате часто остаётся файл нулевой длины, и при следующем открытии возникнет исключение.621622### [Я попытался открыть файл Berkeley DB, но bsddb выдаёт bsddb.error: (22, ‘Invalid argument’). Помогите! Как восстановить мои данные?](https://python-all.ru/2.7/faq/library.html#id38)623624Не паникуйте! Ваши данные, скорее всего, целы. Самая частая причина ошибки – попытка открыть более старый файл Berkeley DB с более новой версией библиотеки Berkeley DB.625626Во многих системах Linux теперь доступны все три версии Berkeley DB. Если вы переходите с версии 1 на более новую, используйте db\_dump185 для создания текстового дампа базы данных. Если вы переходите с версии 2 на версию 3, используйте db2\_dump для создания текстовой версии базы данных. В любом случае используйте db\_load для создания новой родной базы данных для последней версии, установленной на вашем компьютере. Если у вас установлена версия 3 Berkeley DB, вы сможете использовать db2\_load для создания родной базы данных версии 2.627628Следует отказаться от файлов Berkeley DB версии 1, поскольку код хэш-файлов содержит известные ошибки, которые могут повредить ваши данные.629630## [Математика и численные методы](https://python-all.ru/2.7/faq/library.html#id39)631632### [Как генерировать случайные числа в Python?](https://python-all.ru/2.7/faq/library.html#id40)633634Стандартный модуль [`random`](https://python-all.ru/2.7/library/random.html#module-random) реализует генератор случайных чисел. Использовать его просто:635636```python637import random638random.random()639```640641Возвращает случайное число с плавающей запятой в диапазоне \[0, 1).642643В этом модуле также есть много других специализированных генераторов, например:644645- `randrange(a, b)` выбирает целое число в диапазоне \[a, b).646- `uniform(a, b)` выбирает число с плавающей запятой в диапазоне \[a, b).647- `normalvariate(mean, sdev)` делает выборку из нормального (гауссова) распределения.648649Некоторые функции более высокого уровня работают непосредственно с последовательностями, например:650651- `choice(S)` выбирает случайный элемент из заданной последовательности652- `shuffle(L)` перемешивает список на месте, т.е. случайным образом переставляет его элементы.653654Также существует класс `Random`, экземпляр которого можно создать для получения независимых генераторов случайных чисел.655