【问题标题】:Why does this Jython loop fail after a single run?为什么这个 Jython 循环在一次运行后会失败?
【发布时间】:2015-11-21 06:42:58
【问题描述】:

我有以下代码:

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% 的时间。如果我使用如下的 main 运行它:

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

它第一次工作。它为我提供了我想要的输出,这是写在我的Versions.py 文件中的 http 请求的数据,上面的 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

在 950 行 Java 堆栈跟踪末尾提供的我的 Python 回溯主要是这样的:

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"

虽然我可能永远不会在循环中运行此代码,但我对两件事非常好奇:

  • 有问题的代码是我的 Python 还是 Java 代码?还是完全是 Jython 的问题?
  • 异常是什么意思(看起来像java异常)?为什么它被抛出?有没有办法让这样的循环工作?能不能写得好一点?

【问题讨论】:

  • 可能是您访问资源的速度太快了,在第一次调用getVersion() 时,您锁定了尚未释放的文件。您可以尝试在循环中的getVersion() 之后调用Thread.sleepThread.yield 吗?
  • @DaedalusUsedPerl 我会尝试让线程休眠,你认为我应该这样做多久?也许 2-3 秒?
  • 即使是一秒钟也可能是矫枉过正,但我​​不确定。尝试 2 并向上/向下调整以适应。
  • 如果循环运行 20 次,它是否有 5% 的时间工作?这看起来像是解释器清理资源的问题。尝试将解释器设置为静态字段,然后不要调用 close。
  • @DaedalusUsedPerl 它并没有真正做任何事情,同样的结果。经过长达 5 秒的测试。

标签: java python loops exception-handling jython


【解决方案1】:

您使用的python库urllib2使用Netty

Netty有一个问题,众所周知:

根据所有这些链接Netty HttpClient 在关闭后不时失败。看起来Netty 会在一段时间后恢复,并且某些应用程序可以正常工作以解决此问题。反正看起来很不稳定。


问:有问题的代码是我的 Python 代码还是 Java 代码?还是完全是 Jython 的问题?

A:问题是由 Jython 库urllib2 引起的,它使用了Netty


问:异常是什么意思(看起来像java异常)?为什么当它被抛出?

答:urllib2 在内部使用 NettyNetty 是用 Java 编写的,会抛出这个 Java 异常。 Netty 使用自己的 Thread Executor,在关闭请求后一段时间内会关闭并且无法使用。你这次正好命中。


问:有没有办法让这样的循环工作?能不能写得好一点?

A:我会尝试使用Requests 库。

【讨论】:

  • 这并不能完全回答我的问题。我正在寻找对异常的解释,以及为什么它不起作用。这对我没有任何帮助。什么引发异常?为什么?这是实现的错误吗?有趣的是,您似乎没有费心阅读这个问题:我一次只有一个 Jython 环境,而不是同时有多个。
  • @Zizouz212 没有你的python代码,完全分析问题并不容易。看起来我仍然找到了原因。 我已经完全重写了答案。希望,它现在会有所帮助。
  • 感谢@OlegRudenko。阅读问题原因并很好地追踪到 Netty 很有趣。我打算接下来看看它,但时间用完了。
  • @OlegRudenko 这好多了。我通常对我的所有 python 工作都使用请求,但是如何使用 Jython 让它工作呢?即使操纵sys.path 和工作目录,我也从未设法得到它。否则,这个答案会好很多很多:D
  • @Zizouz212 抱歉,我没有解决这个问题的经验。也许这个答案会有所帮助:How to get urllib3 and requests working with jython 2.7 beta 1?
【解决方案2】:

尝试在每次创建解释器时为其提供一个新初始化的系统状态:

PySystemState.initialize();
PythonInterpreter interpreter = new PythonInterpreter(null, new PySystemState());

【讨论】:

    猜你喜欢
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多