Исполнение Python программ: все способы и приемы
Основные способы выполнения кода Python
Самый распространенный способ выполнения кода Python - это запуск готового файла с расширением .py через интерпретатор. Для этого в командной строке (терминале) необходимо передать имя файла в качестве аргумента программе python (или python3 в системах Linux/macOS).
echo 'print("Привет, мир!")' > hello.py
python hello.pyPython execute code (выполнение кода python)
Привет, мир!
Внутри скрипта может быть любой корректный код Python: объявления функций, классы, импорты, условные операторы и циклы. После завершения работы скрипта интерпретатор завершается, и все ресурсы освобождаются.
Типичные проблемы:
- Ошибка ModuleNotFoundError – если не установлен требуемый сторонний пакет. Решение: установить через pip.
- Ошибка SyntaxError – наличие синтаксической ошибки в коде. Проверьте строку, указанную в сообщении.
- Проблемы с кодировкой (UnicodeDecodeError) – если файл сохранен в неверной кодировке. Используйте UTF-8.
Как выполнить код Python без создания файла?
Интерпретатор можно запустить без аргументов – тогда открывается интерактивная оболочка (REPL). В ней ввод команд происходит построчно, результат выводится сразу.
$ python
>>> print("Hello")
Hello
>>> 2 + 3
5
>>> exit()
Этот режим удобен для быстрой проверки идей, отладки небольших фрагментов или изучения поведения функций.
Недостатки:
- Код не сохраняется после выхода – его сложно повторно использовать.
- Не подходит для сложных многострочных программ.
Как выполнить строку кода из другой программы?
Функция exec принимает строку, содержащую код Python, и выполняет его в текущей или указанной области видимости. Это мощный, но опасный инструмент.
code = "x = 10\ny = 20\nprint(f'Сумма: {x+y}')"
exec(code)
Сумма: 30
По умолчанию exec работает с текущими глобальными и локальными переменными. Можно передать отдельные словари для контроля.
Проблемы безопасности:
- Если строка получена от пользователя, злоумышленник может выполнить произвольный код (удаление файлов, чтение данных).
- Используйте exec только с доверенными источниками.
- Переопределение переменных может привести к неожиданным побочным эффектам.
Как вычислить значение выражения из строки?
eval вычисляет одно выражение и возвращает результат. В отличие от exec, eval не может выполнять инструкции (присваивания, циклы).
result = eval("2 * 3 + 4")
print(result)
10
eval удобен для разбора математических формул или конфигураций, где требуется только вычисление.
Риски:
- Аналогично exec, eval может выполнять опасные функции (например, eval("__import__('os').system('rm -rf /')")).
- Никогда не передавайте непроверенные данные.
Как выполнить код из другого файла внутри текущей программы?
Если файл является модулем (содержит функции/классы), его можно импортировать с помощью import. При первом импорте код модуля выполняется. Если нужно выполнить файл как скрипт (не модуль), используют importlib или exec(open(...).read()).
# script.py содержит: print("Запуск script.py")
import script # выполнит print
print("После импорта")
Запуск script.py После импорта
Ошибки:
- Повторный импорт не выполняет код заново – модуль кешируется. Используйте importlib.reload для принудительного перезапуска.
- Имя файла не должно совпадать со стандартными модулями.
Как запустить другой скрипт Python как отдельный процесс?
Модуль subprocess позволяет создать дочерний процесс, передать ему аргументы, получить вывод и код возврата. Это изолирует окружение и позволяет взаимодействовать через stdin/stdout.
import subprocess
result = subprocess.run(['python', '-c', 'print("Из дочернего процесса")'], capture_output=True, text=True)
print(result.stdout)
Из дочернего процесса
Проблемы:
- Необходимость экранировать аргументы – используйте список, а не строку.
- Ошибки с кодировкой при чтении stdout.
- Запуск внешнего процесса медленнее, чем вызов функции.
Как сделать Python-скрипт исполняемым в Unix?
Добавив в первую строку файла #!/usr/bin/env python3 и установив права на выполнение (chmod +x script.py), можно запускать скрипт напрямую: ./script.py.
#!/usr/bin/env python3
print("Скрипт запущен напрямую")
Возможные ошибки:
- Если python3 не найден, появится ошибка "command not found".
- Путь к интерпретатору должен быть корректным – используйте /usr/bin/env для переносимости.
Расширенные примеры выполнения кода
code = """
def factorial(n):
return 1 if n <= 1 else n * factorial(n-1)
print(factorial(5))
"""
compiled = compile(code, '<string>', 'exec')
exec(compiled)
120
Компиляция позволяет проверить синтаксис до выполнения, а также выполнять один и тот же скомпилированный объект многократно.
import timeit
exec_time = timeit.timeit(stmt='[x**2 for x in range(1000)]', number=10000)
print(f"Среднее время: {exec_time/10000:.6f} секунд")
Среднее время: 0.000152 секунд
timeit автоматически отключает сборщик мусора и запускает код многократно для получения точных результатов.
# Файл args_demo.py
import sys
print("Аргументы:", sys.argv[1:])
# Запуск:
# python args_demo.py --name John --age 30
# Результат:
# Аргументы: ['--name', 'John', '--age', '30']
Аргументы: ['--name', 'John', '--age', '30']
import ast
user_input = "{'a': 1, 'b': [2, 3]}"
data = ast.literal_eval(user_input)
print(data['b'][1]) # 3
3
ast.literal_eval обрабатывает только строки, числа, кортежи, списки, словари, множества и None, поэтому безопаснее eval.
safe_globals = {"__builtins__": {}} # отключаем встроенные функции
try:
exec("print('какой-то код')", safe_globals)
except Exception as e:
print("Ошибка:", e)
Ошибка: name 'print' is not defined
Полностью изолировать выполнение сложно, но можно ограничить доступ.
import asyncio
async def run_code_async(code):
exec(code)
code = """
async def test():
await asyncio.sleep(0.1)
print("Асинхронно выполнено")
await test()
"""
asyncio.run(run_code_async(code))
Асинхронно выполнено
import threading
def execute_in_thread(code):
exec(code)
code = "import time; time.sleep(0.5); print('Поток завершен')"
t = threading.Thread(target=execute_in_thread, args=(code,))
t.start()
t.join()
Поток завершен
import subprocess
p = subprocess.Popen(['python', '-c', 'import sys; data = sys.stdin.read(); print("Получено:", data)'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
out, _ = p.communicate("Привет из stdin")
print(out)
Получено: Привет из stdin