Как импортировать внешний скрипт Python? - PullRequest
1 голос
/ 31 октября 2011

Я пишу игровой движок на Python, и дело в том, что я не уверен, как обращаться с внешними скриптами (подумайте о модулях с исходным движком, LUA).К каждой сцене, сущности в игре, может быть прикреплен собственный сценарий, но игровой движок не знает об этих сценариях, пока сцена не загружается.Например, может существовать сценарий, который будет анимировать кат-сцену, и этот сценарий будет использоваться только в одной сцене.

Итак, что я хочу знать, каков наилучший способ обработки этих сценариев?Я знаю, что могу импортировать их с помощью exec или eval, но кто-то сказал, что теперь это безопасно.Зачем?Я мог бы также создать некоторый язык сценариев, который будет анализироваться во время выполнения, но я не вижу смысла в этом, учитывая, что Python сам является языком сценариев.Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

0 голосов
/ 31 октября 2011

Да, exec и eval небезопасны для пользовательских данных, таких как обработка выражений или ввод через Интернет. Но если вы специально хотите предоставить пользователям полную мощность Python и понимаете риски (пользователи могут что угодно - стирать / читать файлы на компьютере, аварийно завершать работу Python, вводить бесконечный цикл и т. Д.) , используя exec отлично.

Если вы доверяете разработчикам игровых сценариев, exec прочь. Если уровни могут исходить от случайных людей в Интернете, по крайней мере, пусть ваши игроки знают о риске.

0 голосов
/ 01 ноября 2011

Вы можете запустить свой внешний скрипт, либо импортировав его, используя __import__(), либо используя функцию exec / execfile.Приятно знать, что:

  • import компилирует скрипт в байт-код и сохраняет файл .pyc при первом использовании
  • import пытается найти модуль и в конечном итоге он создает модуль со своим собственным пространством имен в отличие от exec / execfile, который просто выполняет код в строке / файле.
  • можно выполнить песочницу вашего кодабит посредством искажения встроенных глобальных переменных во время передачи глобальных параметров в качестве параметров __import__ / execfile, хотя этот метод не является супер-безопасным, см. мой ответ на этот вопрос , например.
0 голосов
/ 31 октября 2011

Для этого вы можете использовать __import__().Скажем, у вашего entity есть атрибут script, который может быть либо None, либо именем скрипта (который находится в известном месте, который находится на sys.path), вы можете использовать следующий код для запуска main() функция из этого скрипта:

if entity.script is not None:
    custom_script = __import__(entity.script, globals(), locals(), [], -1)
    custom_script.main()
...