Выполнить произвольный код Python удаленно — можно ли это сделать?

Я работаю над сетевой системой, в которой есть несколько очень мощных компьютеров. Их можно использовать для очень быстрого выполнения функций Python. У моих пользователей есть ряд функций Python, которые требуют много времени для расчета на рабочих станциях, в идеале они хотели бы иметь возможность вызывать некоторые функции на удаленном мощном сервере, но они должны работать локально.

В Python есть старая функция под названием «применить» — в наши дни она в основном бесполезна, поскольку python поддерживает синтаксис расширенного вызова (например, ** аргументы), однако мне нужно реализовать что-то, что работает примерно так:

rapply = Rapply( server_hostname ) # Set up a connection
result = rapply( fn, args, kwargs ) # Remotely call the function
assert result == fn( *args, **kwargs ) #Just as a test, verify that it has the expected value. 

Rapply должен быть классом, который можно использовать для удаленного выполнения некоторого произвольного кода (fn может быть буквально любым) на удаленном сервере. Он отправит обратно результат, который вернет функция rapply. «Результат» должен иметь то же значение, как если бы я вызвал функцию локально.

Теперь давайте предположим, что fn — это функция, предоставляемая пользователем. Мне нужен какой-то способ отправить ее по сети на исполняющий сервер. Если бы я мог гарантировать, что fn всегда будет чем-то простым, это могла бы быть просто строка, содержащая исходный код Python... но что, если бы это было не так просто?

Что, если fn может иметь локальные зависимости: это может быть простая функция, которая использует класс, определенный в другом модуле, есть ли способ инкапсулировать fn и все, что требуется fn, кроме стандартной библиотеки? Идеальное решение не требует от пользователей этой системы больших знаний о разработке на Python. Они просто хотят написать свою функцию и вызвать ее.

Просто чтобы уточнить, я не заинтересован в обсуждении того, какой сетевой протокол может использоваться для реализации связи между клиентом и сервером. Моя проблема заключается в том, как инкапсулировать функцию и ее зависимости в виде единого объекта, который можно сериализовать и выполнять удаленно.

Меня также не интересуют последствия для безопасности запуска произвольного кода на удаленных серверах — скажем так, эта система предназначена исключительно для исследований и находится в среде с сильным брандмауэром.


person Salim Fadhley    schedule 11.02.2009    source источник
comment
Что мешает вам иметь общую библиотеку кода для клиента и серверов?   -  person Deestan    schedule 11.02.2009
comment
Разве Celery не делает этого по своей сути? Я думаю, когда вы определяете функции как задачи, они упаковываются и отправляются рабочим, которые запускают их удаленно, с параметрами, которые вы помещаете в очередь заданий.   -  person Nick T    schedule 29.03.2016


Ответы (6)


Взгляните на PyRO (удаленные объекты Python). все компьютеры в вашем кластере и вызывать их напрямую или косвенно через сервер имен и механизм публикации-подписки.

person Jim Carroll    schedule 11.02.2009

Похоже, вы хотите сделать следующее.

  • Определите общее пространство файловой системы.

  • Поместите ВЕСЬ ваш исходный код Python в это общее пространство файловой системы.

  • Определите простые агенты или серверы, которые будут «выполнять» блок кода.

  • Затем ваш клиент связывается с агентом (для этого
    хорошо подходит протокол REST с методами POST) с блоком кода. Агент сохраняет блок кода и выполняет execfile для этого блока кода.

Поскольку все агенты используют общую файловую систему, все они имеют одинаковую структуру библиотеки Python.

Мы делаем это с помощью простого приложения WSGI, которое мы называем «пакетным сервером». У нас есть протокол RESTful для создания и проверки удаленных запросов.

person S.Lott    schedule 11.02.2009
comment
Протокол (REST) ​​немного выходит за рамки этого вопроса. Общий код Python — это хорошая идея, это решение, которое у нас есть на данный момент. Проблема в том, что для того, чтобы получить код на сервере, он должен быть общим (следовательно, не полностью произвольным). - person Salim Fadhley; 11.02.2009
comment
@Salim Fadhley: Не то, что я сказал. Я сказал, что протокол REST содержит код. Код сохраняется в файл. Файл обрабатывается с помощью execfile. Можно отправить произвольный код. Предустановлены только зависимости. - person S.Lott; 11.02.2009
comment
Понятно, ваше решение - отправить нескомпилированный код Python - это именно то, что я предлагаю в своем вопросе. Я ищу альтернативу, которая решит проблему того, что, если этот код содержит импорт для пользовательского класса в другом файле. - person Salim Fadhley; 11.02.2009
comment
Разработанные пользователем классы должны быть установлены в общий каталог. Либо в site-packages, либо в пользовательском каталоге с файлом .pth в site-packages. - person S.Lott; 11.02.2009

У Stackless была возможность обрабатывать и распаковывать работающий код. К сожалению, текущая реализация не поддерживает эту функцию.

person Łukasz    schedule 11.02.2009
comment
Интересный ответ - к сожалению, я застрял с Python 2.4, однако за него голосуют! - person Salim Fadhley; 11.02.2009
comment
Ссылка на stackless не работает. - person Travis Bear; 09.02.2013
comment
Спасибо, исправил ссылку и обновил ответ до текущего состояния реализации без стека. - person Łukasz; 12.02.2013

Вы можете использовать готовое решение для кластеризации, например Parallel Python. Вы можете относительно легко настроить несколько удаленных ведомых устройств и запустить на них произвольный код.

person Ali Afshar    schedule 11.02.2009

Вы можете использовать SSH-соединение с удаленным ПК и запускать команды на другом компьютере напрямую. Вы даже можете скопировать код Python на машину и выполнить его.

person Ash    schedule 11.02.2009
comment
Но как узнать, что копировать? И в каком виде его копировать? Вот в чем вопрос. SSHing выходит за рамки вопроса (см. Выше). - person Salim Fadhley; 11.02.2009

Синтаксис:

кошка ./test.py | sshpass -p 'пароль' ssh user@remote-ip "python - script-arguments-if-any для сценария test.py"

1) здесь «test.py» — это локальный скрипт Python. 2) sshpass используется для передачи пароля ssh для соединения ssh

person Amalraj Victory Raja    schedule 16.06.2015