Python C API — Остановка выполнения (и продолжение его позже)

#c #python #api #profile #execution

#c #python #API #Профиль #выполнение

Вопрос:

1) Я хотел бы использовать функции профилирования в Python C API, чтобы перехватывать интерпретатор python, когда он возвращается из определенных функций.

2) Я хотел бы приостановить интерпретатор python, отправить выполнение обратно функции, которая вызвала интерпретатор в моей программе C , и, наконец, вернуть выполнение интерпретатору python, запустив его в строке кода после того, как оно остановилось. Я хотел бы поддерживать как глобальные, так и локальные значения между моментами, когда выполнение принадлежит python.

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

Из того, что я смог найти в документах python API, мне придется сохранить некоторую часть исполняемого фрейма, но я ничего не нашел. Некоторые дополнительные вопросы… Что именно содержит PyFrameObject? Удивительно, но документы python API никогда не объясняют этого.

Комментарии:

1. Вы пробовали посмотреть на использование SIGSTOP / SIGCONT ?

2. Мой интерпретатор Python запущен в том же потоке, что и моя программа на C … Я хочу, чтобы выполнение передавалось в этом потоке, а не останавливало весь процесс… Возможно, я не до конца понимаю, какое влияние SIGSTOP и SIGCONT окажут на мою программу? Если да, пожалуйста, объясните.

Ответ №1:

Если я понимаю вашу проблему, у вас есть программа на C , которая вызывает python. Когда python завершает выполнение функции, вы хотите приостановить интерпретатор и продолжить с того места, на котором остановился код C . Некоторое время спустя вашей программе на C необходимо вернуться к python и попросить интерпретатор python продолжить с того места, на котором она остановилась.

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

 [ top of stack ]
[ some interpreter frames ]
[ some c   frames ] 
  

Чтобы приостановить интерпретатор, вам нужно сохранить фреймы интерпретатора и вернуться к самому верхнему фрейму C . Затем, чтобы отменить паузу, вам нужно восстановить фреймы интерпретатора и перейти вверх по стеку к тому месту, где вы остановились. Переключение выполнимо (см. http://en.wikipedia.org/wiki/Setjmp.h ), но сохранить и восстановить стек сложнее. Я не знаю API для этого.

Однако вы могли бы сделать это с помощью двух потоков. Поток, созданный в начале вашей программы на c (назовем его потоком 1), запускает код на c и создает поток 2 для запуска интерпретатора python.

Изначально (при запуске кода c ) выполняется поток 1, а поток 2 заблокирован (скажем, в переменной условия, см.https://computing.llnl.gov/tutorials/pthreads /). Когда вы запускаете или отменяете паузу, поток интерпретатора 1 сигнализирует о переменной условия и ожидает ее. Это приводит к пробуждению потока 2 (который запускает интерпретатор) и вызывает блокировку потока 1. Когда интерпретатору необходимо сделать паузу, поток 2 сигнализирует о переменной условия и ожидает ее (таким образом, поток 2 блокируется, поток 1 пробуждается). Вы можете переключаться между потоками сколько душе угодно. Надеюсь, это поможет.

Комментарии:

1. Спасибо! Я только что погуглил вокабуляр в вашем ответе, который я не понял, так что теперь я понимаю, что вы имеете в виду. Сработало как по волшебству.