#java #jython #scripting-language #jython-2.7
#java #jython #язык сценариев #jython-2.7
Вопрос:
Обязательно ли каждый раз вызывать cleanup()
before close()
в PythonInterpreter
в Jython?
Я читал документы, но не нашел много информации об этой функции. javadocs вообще ничего не говорят. Самая близкая информация, которую я нашел, находится здесь, в readthedocs , где они объясняют, что очистка необходима в некоторых случаях программирования с использованием потоков, и я даже не уверен, что они ссылаются на эту конкретную функцию.
Интересно, когда мне нужно позвонить cleanup()
… и если ответ всегда, то зачем им создавать cleanup()
и close()
отдельные функции?
Комментарии:
1. На самом деле у меня нет ответа, но
cleanup()
вызывается изclose()
. Смотрите github.com/jython/jython/blob/master/src/org/python/util /… .2. Что ж, для меня этого достаточно. Спасибо!
Ответ №1:
Хорошо, я прочитал исходный код Jython и выполнил несколько тестов. Вот что я нашел:
Что cleanup()
делает: Он берет на себя ответственность за необработанные ресурсы, такие как запущенные потоки и файлы.
Что cleanup()
не делает: Сбрасывает состояние интерпретатора в любой форме; импортированные модули и определенные переменные сохраняются.
Следующие примеры демонстрируют это поведение:
Пример 1
Давайте импортируем модуль, определим переменную и откроем файл.
PythonInterpreter py = new PythonInterpreter();
String code1 = "import sys;"
"a=45;"
"f = open('test.txt')";
String code2 = "print(sys.version_info);"
"print(a);"
"print(f.closed)";
// first execution
py.exec(code1);
py.exec(code2);
// second execution
py.cleanup();
py.exec(code2);
py.close()
Он выводит
sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0)
45
False
------
sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0)
45
True
Модуль sys
и переменные a
и f
все еще существуют с теми же значениями после очистки, но открытый файл закрыт.
Пример 2
Для этого func
используется медленная функция, выполнение которой занимает примерно 2 секунды (больше, чем обычно cleanup()
).
PythonInterpreter py = new PythonInterpreter();
String code3 = "from threading import Threadn"
"def func():n"
" print 'th start'n"
" for i in range(0,20000000):n"
" x=in"
" print 'th done'n"
"th = Thread(target=func)n"
"th.start()";
String code4 = "print th.isAlive()n"
"th.join()";
// first execution
py.exec(code3);
py.exec(code4);
System.out.println("------");
// second execution
py.exec(code3);
py.cleanup();
py.exec(code4);
py.close();
Это выводит:
th start
True
th done
------
th start
th done
False
При первом выполнении у основного потока есть достаточно времени, чтобы проверить, работает ли th
, и распечатать его. Во втором он всегда ожидает th
завершения, что означает, что cleanup()
где-то присоединяется к потоку.
Заключение
Как указал @mzjn, close()
функция вызывает cleanup()
, и это имеет смысл, поэтому вам никогда не нужно вызывать cleanup()
раньше close()
. Единственный случай, когда вам может понадобиться вызвать его вручную, это если вы хотите продолжить использовать PythonInterpreter
, но вам необходимо закрыть все открытые файлы и присоединиться ко всем потокам.
Комментарии:
1. Спасибо за подробную информацию. Что, если у меня есть интерпретатор, прослушивающий все поступающие запросы
interpreter.exec()
илиinterpreter.eval()
? Нужно ли мне периодически вызывать вручнуюcleanup()
? Я провожу нагрузочный тест, где я вижу, что для того же кода Python время выполнения становится все медленнее и медленнее. И через некоторое время время выполнения становится лучше, а затем снова медленнее. Но я вижу, что общее время выполнения становится больше. Я думаю,cleanup()
может помочь или нет?2. Насколько я понимаю, если вы правильно управляете файлами и потоками в своем коде (закрываете и объединяете их соответственно), в этом не было бы необходимости.
3. Я не управляю файлами, а просто инициализирую экземпляр и вызываю метод. Насколько я понимаю, основываясь на документе Jython, я могу напрямую использовать собственное управление потоками интерпретатора для обработки поступающего вызова
eval
orexec
(поскольку интерпретатор потокобезопасен): у меня есть пул для контроля того, сколько запросов обрабатывается в данный момент, но все они используют один и тот же интерпретатор. Прежде чем вы ответили, я пытался периодически вызыватьcleanup()
, и, похоже, потребление памяти более стабильно, а время выполнения также более стабильно. Но мне может понадобиться дополнительный нагрузочный тест, чтобы увидеть, действительно ли это помогает.4. @Vision ты нашел решение для своего, я вижу то же самое