Spec-Zone.ru › Elisp

Создание асинхронного процесса

В этом разделе описывается, как создать асинхронный процесс. После создания асинхронный процесс выполняется параллельно с Emacs, и Emacs может взаимодействовать с ним с помощью функций, описанных в следующих разделах (см. Отправка данных процессам и Получение данных от процессов). Обратите внимание, что взаимодействие с процессом является лишь частично асинхронным: Emacs отправляет данные процессу и получает их от него только при вызове этих функций.

Асинхронный процесс управляется либо через pty (псевдотерминал), либо через канал. Выбор между pty и каналом выполняется при создании процесса и по умолчанию зависит от значения переменной process-connection-type (см. ниже). Если доступны pty, они обычно предпочтительны для процессов, видимых пользователю, например в режиме Shell, поскольку позволяют управлять заданиями (C-c, C-z и т. д.) между процессом и его дочерними процессами, а также потому, что интерактивные программы воспринимают pty как терминальные устройства, тогда как каналы не поддерживают эти возможности. Однако для подпроцессов, используемых программами на Lisp во внутренних целях (то есть когда взаимодействие пользователя с подпроцессом не требуется) и обменивающихся значительными объемами данных с программой на Lisp, часто лучше использовать канал, поскольку каналы работают эффективнее. Кроме того, во многих системах общее количество pty ограничено, поэтому не следует расходовать их без необходимости.

Функция: make-process &rest args

Эта функция является базовой низкоуровневой примитивной функцией для запуска асинхронных подпроцессов. Она возвращает объект процесса, представляющий подпроцесс. По сравнению с более высокоуровневой функцией start-process, описанной ниже, она принимает аргументы-ключевые слова, более гибкая и позволяет указать фильтры и обработчики-сигнализаторы процесса за один вызов.

Аргументы args представляют собой список пар «ключевое слово/аргумент». Пропуск ключевого слова всегда равнозначен указанию для него значения nil. Ниже перечислены допустимые ключевые слова:

:name name

Использовать строку name в качестве имени процесса; если процесс с таким именем уже существует, name изменяется (к нему добавляется «<1>» и т. д.), чтобы имя стало уникальным.

:buffer buffer

Использовать buffer в качестве буфера процесса. Если значение равно nil, подпроцесс не связывается ни с одним буфером.

:command command

Использовать command в качестве командной строки процесса. Значение должно быть списком, начинающимся с имени исполняемого файла программы, за которым следуют строки, передаваемые программе в качестве аргументов. Если первый элемент списка равен nil, Emacs открывает новый псевдотерминал (pty) и связывает его ввод и вывод с buffer, не запуская при этом никакую программу; в таком случае остальные элементы списка игнорируются.

:coding coding

Если coding — это символ, он задает кодировку, используемую для чтения данных из соединения и записи данных в него. Если coding — это конс-ячейка (decoding . encoding), для чтения будет использоваться decoding, а для записи — encoding. Кодировка, используемая для кодирования данных, записываемых в программу, также применяется для кодирования аргументов командной строки (но не самой программы, имя файла которой кодируется как любое другое имя файла; см. file-name-coding-system).

Если coding равно nil, будут применяться правила по умолчанию для определения кодировки. См. Кодировки по умолчанию.

:connection-type type

Задать тип устройства, используемого для взаимодействия с подпроцессом. Возможные значения: pty для использования pty, pipe для использования канала или nil для использования значения по умолчанию, определяемого переменной process-connection-type. Если type — это конс-ячейка (input . output), для стандартного ввода будет использоваться input, а для стандартного вывода (и стандартного потока ошибок, если :stderr равно nil) — output.

В системах, где pty недоступны (MS-Windows), этот параметр игнорируется, и всегда используются каналы.

:noquery query-flag

Задать флаг запроса при завершении процесса значением query-flag. См. Запрос перед завершением.

:stop stopped

Если задано, stopped должно быть равно nil; использовать любое значение, отличное от nil, нельзя. В противном случае ключ :stop игнорируется и сохраняется для совместимости с другими типами процессов, например процессами-каналами. Асинхронные подпроцессы никогда не запускаются в остановленном состоянии.

:filter filter

Задать фильтр процесса значением filter. Если он не указан, будет предоставлен фильтр по умолчанию, который впоследствии можно переопределить. См. Функции-фильтры процессов.

:sentinel sentinel

Задать обработчик-сигнализатор процесса значением sentinel. Если он не указан, будет использоваться обработчик-сигнализатор по умолчанию, который впоследствии можно переопределить. См. Обработчики-сигнализаторы: обнаружение изменений состояния процесса.

:stderr stderr

Связать stderr со стандартным потоком ошибок процесса. Значение, отличное от nil, должно быть буфером или процессом-каналом, созданным с помощью make-pipe-process, описанной ниже. Если stderr равно nil, стандартный поток ошибок объединяется со стандартным выводом, и оба потока передаются в buffer или filter.

Если stderr — это буфер, Emacs создаст процесс-канал — процесс стандартного потока ошибок. Для этого процесса будут использоваться фильтр по умолчанию (см. Функции-фильтры процессов), обработчик-сигнализатор по умолчанию (см. Обработчики-сигнализаторы: обнаружение изменений состояния процесса) и кодировки по умолчанию (см. Кодировки по умолчанию). При этом в качестве флага запроса при завершении будет использоваться query-flag (см. Запрос перед завершением). Процесс будет связан с буфером stderr (см. Буферы процессов) и будет отправлять туда свой вывод (то есть стандартный поток ошибок основного процесса). Чтобы получить объект процесса для процесса стандартного потока ошибок, передайте буфер stderr функции get-buffer-process.

Если stderr — это процесс-канал, Emacs будет использовать его в качестве процесса стандартного потока ошибок для нового процесса.

:file-handler file-handler

Если file-handler не равно nil, будет выполнен поиск обработчика имен файлов для значения default-directory текущего буфера, и этот обработчик будет вызван для создания процесса. Если такого обработчика нет, функция продолжит работу так, как если бы file-handler было равно nil.

Исходный список аргументов, дополненный фактическими сведениями о соединении, доступен через функцию process-contact.

Текущим рабочим каталогом подпроцесса задается значение default-directory текущего буфера, если оно локальное (что определяется с помощью unhandled-file-name-directory); в противном случае используется ~. Чтобы запустить процесс в удаленном каталоге, передайте :file-handler t функции make-process. В этом случае текущим рабочим каталогом будет локальная часть имени default-directory (как определяется с помощью file-local-name).

В зависимости от реализации обработчика имен файлов применить filter или sentinel к результирующему объекту процесса может быть невозможно. Аргумент :stderr не может быть процессом-каналом: обработчики имен файлов не поддерживают использование процессов-каналов. В качестве аргумента :stderr допускается буфер; его содержимое отображается без использования процессов-каналов. См. Функции-фильтры процессов, Обработчики-сигнализаторы: обнаружение изменений состояния процесса и Прием вывода от процессов.

Некоторые обработчики имен файлов могут не поддерживать make-process. В таких случаях эта функция ничего не делает и возвращает nil.

Функция: make-pipe-process &rest args

Эта функция создает двунаправленный канал, который можно подключить к дочернему процессу. Это полезно в сочетании с ключевым словом :stderr функции make-process. Функция возвращает объект процесса.

Аргументы args представляют собой список пар «ключевое слово/аргумент». Пропуск ключевого слова всегда равнозначен указанию для него значения nil.

Ниже перечислены допустимые ключевые слова:

:name name

Использовать строку name в качестве имени процесса. Как и в случае с make-process, при необходимости имя изменяется, чтобы стать уникальным.

:buffer buffer

Использовать buffer в качестве буфера процесса. Если значение равно nil, подпроцесс не связывается ни с одним буфером.

:coding coding

Если coding — это символ, он задает кодировку, используемую для чтения данных из соединения и записи данных в него. Если coding — это конс-ячейка (decoding . encoding), для чтения будет использоваться decoding, а для записи — encoding.

Если coding равно nil, будут применяться правила по умолчанию для определения кодировки. См. Кодировки по умолчанию.

:noquery query-flag

Задать флаг запроса при завершении процесса значением query-flag. См. Запрос перед завершением.

:stop stopped

Если stopped не равно nil, запустить процесс в остановленном состоянии. В остановленном состоянии процесс-канал не принимает входящие данные, но позволяет отправлять исходящие данные. Остановленное состояние устанавливается с помощью stop-process и снимается с помощью continue-process (см. Отправка сигналов процессам).

:filter filter

Задать фильтр процесса значением filter. Если он не указан, будет предоставлен фильтр по умолчанию, который впоследствии можно изменить. См. Функции-фильтры процессов.

:sentinel sentinel

Задать обработчик-сигнализатор процесса значением sentinel. Если он не указан, будет использоваться обработчик-сигнализатор по умолчанию, который впоследствии можно изменить. См. Обработчики-сигнализаторы: обнаружение изменений состояния процесса.

Исходный список аргументов, дополненный фактическими сведениями о соединении, доступен через функцию process-contact.

Функция: start-process name buffer-or-name program &rest args

Эта функция представляет собой высокоуровневую обертку вокруг make-process с интерфейсом, похожим на call-process. Она создает новый асинхронный подпроцесс и запускает в нем указанную программу program. Функция возвращает объект процесса, представляющий новый подпроцесс в Lisp. Аргумент name задает имя объекта процесса; как и в случае с make-process, при необходимости оно изменяется, чтобы стать уникальным. Буфер buffer-or-name — это буфер, который нужно связать с процессом.

Если program равно nil, Emacs открывает новый псевдотерминал (pty) и связывает его ввод и вывод с buffer-or-name, не создавая подпроцесс. В этом случае оставшиеся аргументы args игнорируются.

Остальные элементы args — это строки, задающие аргументы командной строки для подпроцесса.

В приведенном ниже примере запускается первый процесс, который работает (точнее, ожидает) 100 секунд (выходной буфер «foo» создается сразу). Тем временем запускается второй процесс, которому для обеспечения уникальности присваивается имя «my-process<1>». Он добавляет список каталогов в конец буфера «foo» до завершения первого процесса. Затем второй процесс завершается, и в буфер добавляется соответствующее сообщение. Значительно позже завершается первый процесс, и в буфер добавляется еще одно сообщение.

(start-process "my-process" "foo" "sleep" "100")
     ⇒ #<process my-process>
(start-process "my-process" "foo" "ls" "-l" "/bin")
     ⇒ #<process my-process<1>>

---------- Buffer: foo ----------
total 8336
-rwxr-xr-x 1 root root 971384 Mar 30 10:14 bash
-rwxr-xr-x 1 root root 146920 Jul  5  2011 bsd-csh
...
-rwxr-xr-x 1 root root 696880 Feb 28 15:55 zsh4

Process my-process<1> finished

Process my-process finished
---------- Buffer: foo ----------
Функция: start-file-process name buffer-or-name program &rest args

Подобно функции start-process, эта функция запускает новый асинхронный подпроцесс с программой program и возвращает объект процесса.

Отличие от start-process заключается в том, что эта функция может вызвать обработчик имен файлов в зависимости от значения default-directory. Этот обработчик должен запускать program, возможно, на локальном компьютере или на удаленном компьютере, соответствующем default-directory. В последнем случае локальная часть default-directory становится рабочим каталогом процесса.

Эта функция не пытается вызывать обработчики имен файлов для program или остальных элементов args. Поэтому, если в program или каком-либо элементе args используется синтаксис удаленных файлов (см. Придание некоторым именам файлов «магических» свойств), эти имена необходимо преобразовать либо в имена файлов относительно default-directory, либо в имена, однозначно указывающие на файлы на удаленном компьютере, с помощью функции file-local-name.

В зависимости от реализации обработчика имен файлов применить process-filter или process-sentinel к результирующему объекту процесса может быть невозможно. См. Функции-фильтры процессов и Обработчики-сигнализаторы: обнаружение изменений состояния процесса.

Некоторые обработчики имен файлов могут не поддерживать start-file-process (например, функция ange-ftp-hook-function). В таких случаях эта функция ничего не делает и возвращает nil.

Функция: start-process-shell-command name buffer-or-name command

Эта функция подобна start-process, но использует оболочку для выполнения указанной команды command. Аргумент command — это строка с командой оболочки. Переменная shell-file-name задает используемую оболочку.

Программа запускается через оболочку, а не напрямую с помощью make-process или start-process, чтобы можно было использовать такие возможности оболочки, как подстановочные знаки в аргументах. Поэтому, если в команду включаются произвольные аргументы, заданные пользователем, их следует предварительно заключить в кавычки с помощью shell-quote-argument, чтобы специальные символы оболочки не имели специального значения. См. Аргументы оболочки. Разумеется, при выполнении команд на основе пользовательского ввода также следует учитывать вопросы безопасности.

Функция: start-file-process-shell-command name buffer-or-name command

Эта функция подобна start-process-shell-command, но внутри использует start-file-process. Благодаря этому команда command может выполняться и на удаленных компьютерах в зависимости от default-directory.

Переменная: process-connection-type

Эта переменная задает тип устройства, используемого для взаимодействия с асинхронными подпроцессами. Если ее значение не равно nil, используются pty, если они доступны. В противном случае используются каналы.

Значение process-connection-type применяется при вызове make-process или start-process. Поэтому способ взаимодействия с отдельным подпроцессом можно задать, связав переменную на время вызова этих функций.

Обратите внимание, что значение этой переменной игнорируется, если make-process вызывается со значением параметра :stderr, отличным от nil; в этом случае Emacs будет взаимодействовать с процессом через каналы. Оно также игнорируется, если pty недоступны (MS-Windows).

(let ((process-connection-type nil))  ; use a pipe
  (start-process ...))

Чтобы определить, получил ли данный подпроцесс канал или pty, используйте функцию process-tty-name (см. Сведения о процессах).

Переменная: process-error-pause-time

Если в функции обработчика-сигнализатора или фильтра процесса возникает ошибка, Emacs (по умолчанию) приостанавливает работу на process-error-pause-time секунд после отображения этой ошибки, чтобы пользователи успели ее увидеть. Однако при частом возникновении таких ошибок Emacs может перестать отвечать; это поведение можно отключить, установив для process-error-pause-time значение 0.

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Asynchronous-Processes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API