2015-08-27 4 views
15

У меня есть следующий код:Почему этот цикл Jython терпит неудачу после одного прогона?

public static String getVersion() 
{ 
    PythonInterpreter interpreter = new PythonInterpreter(); 

    try 
    { 
     interpreter.exec(IOUtils.toString(new FileReader("./Application Documents/Scripts/Version.py"))); 
     PyObject get_version = interpreter.get("get_latest_version"); 
     PyObject result = get_version.__call__(interpreter.get("url")); 
     String latestVersion = (String) result.__tojava__(String.class); 
     interpreter.close(); 
     return latestVersion; 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
     interpreter.close(); 
     return Version.getLatestVersionOnSystem(); 
    } 

Для полноты картины я добавил код Python:

import urllib2 as urllib 
import warnings 

url = 'arcticlights.ca/api/paint&requests?=version' 

def get_latest_version(link=url): 
    request = urllib.Request(link) 
    handler = urllib.urllopen(request) 
    if handler.code is not 200: 
     warnings.warn('Invalid Status Code', RuntimeWarning) 
    return handler.read() 

version = get_latest_version() 

Он работает безотказно, но только 10% времени. Если я запускаю его следующим образом:

public static void main(String[] args) 
{ 
    for (int i = 0; i < 10; i++) { 
     System.out.println(getVersion()); 
    } 
} 

Это работает в первый раз. Он дает мне вывод, который я хочу, который является данными из http-запроса, который написан в моем файле Versions.py, который имеет код java выше вызовов. После второго раза он выдает эту массивную ошибку (длина которой составляет 950 строк, но, конечно, я не буду мучить вас, ребята). Вот суть его:

Aug 26, 2015 10:41:21 PM org.python.netty.util.concurrent.DefaultPromise execute 
SEVERE: Failed to submit a listener notification task. Event loop shut down? 
java.util.concurrent.RejectedExecutionException: event executor terminated 

Мой Python отслеживающий, который поставляется в конце 950 строки Java трассировки стека в основном это:

File "<string>", line 18, in get_latest_version 
urllib2.URLError: <urlopen error [Errno -1] Unmapped exception: java.util.concurrent.RejectedExecutionException: event executor terminated> 

Если кому-то интересно, то, казалось бы, нарушившая линия мой get_latest_version просто:

handler = urllib2.urlopen(request) 

Поскольку сервер, что код вызывающего бежится (по CherryPy) на локальном хосте на моей сети, я могу видеть, как он взаимодействует с мой сервер. Он фактически отправляет два запроса (и выдает исключение сразу после второго).

127.0.0.1 - - [26/Aug/2015:22:41:21] "GET/HTTP/1.1" 200 3 "" "Python-urllib/2.7" 
127.0.0.1 - - [26/Aug/2015:22:41:21] "GET/HTTP/1.1" 200 3 "" "Python-urllib/2.7" 

В то время как я никогда не буду запускать этот код в цикле, скорее всего, я очень любопытно, как к двум вещам:

  • Is обижая код мой Python или Java-код? Или это может быть просто проблема с Jython?
  • Что означает исключение (это похоже на исключение Java)? Почему его бросают, когда это происходит? Есть ли способ сделать цикл, подобный этой работе? Может ли это быть написано лучше?
+0

Вполне возможно, что вы обращаетесь к ресурсу слишком быстро, что при первом обращении к 'GetVersion()' вы получили блокировка файла, который еще не выпущен. Можете ли вы попробовать вызвать [Thread.sleep] (https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep%28long%29) или [Thread.yield] (https : //docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#yield%28%29) после 'getVersion()' в цикле? – DaedalusUsedPerl

+0

@DaedalusUsedPerl Я попробую скрыть тему, как долго, по-твоему, я должен это делать? Возможно, 2-3 секунды? – Zizouz212

+0

Даже второй может быть излишним, но я не уверен. Попробуйте 2 и настройте вверх/вниз для соответствия. – DaedalusUsedPerl

ответ

7

В библиотеке python urllib2, которую вы используете, используется Netty.

Netty есть проблема, которая широко известна:

По всем этим ссылкам NettyHttpClient терпит неудачу фр om время от времени после закрытия. Похоже, что Netty восстанавливается через некоторое время, и некоторые приложения работают нормально с этой проблемой. В любом случае, он выглядит неустойчивым.


В: Является ли код нарушения моим кодом Python или Java? Или это может быть просто проблема с Jython?

A: Проблема вызвана библиотекой Jython urllib2, которая использует Netty.


В: Что означает исключение (это похоже на исключение Java)? Почему его бросают, когда это происходит?

A: urllib2 использует внутренне Netty. Netty написан на Java и выбрасывает это исключение Java. Netty использует собственный Thread Executor, который отключается и не используется в течение некоторого времени после закрытия запроса. Вы набрали именно это время.


В: Есть ли способ сделать цикл, подобный этой работе? Может ли это быть написано лучше?

A: Я бы попытался использовать библиотеку Requests.

+0

Это не отвечает на мой вопрос * на * все. Я ищу объяснение исключения и почему он не работает. Это не помогает мне. Что вызывает исключение? Зачем? Это ошибка с реализацией? Интересно, похоже, что вы не потрудились прочитать вопрос: у меня есть единая среда Jython за раз, а не несколько одновременно. – Zizouz212

+0

@ Zizouz212 Было нелегко полностью проанализировать проблему без вашего кода на Python. Но похоже, что я нашел причину. * Я полностью переписал ответ. Надеюсь, теперь это поможет. –

+0

Спасибо @OlegRudenko. Интересно прочитать причину проблемы и приятно отслеживать ее Netty. Я собирался посмотреть на него дальше, но у меня не хватило времени. –

0

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

PySystemState.initialize(); 
PythonInterpreter interpreter = new PythonInterpreter(null, new PySystemState()); 
Смежные вопросы