简体   繁体   English

Python threading.Timer对象在编译为.exe时不起作用

[英]Python threading.Timer object not functioning when compiled to .exe

This is a follow up to https://stackoverflow.com/questions/37684111/ironpython-exe-file-closing-immediately-no-exception-thrown 这是对https://stackoverflow.com/questions/37684111/ironpython-exe-file-closing-immediately-no-exception-thrown的跟进

I figured out that my program is not working once compiled due to an issue with the Timer object in the threading library. 我发现由于线程库中的Timer对象存在问题,我的程序在编译后无法正常工作。 I've included the library in my \\Lib\\site-packages directory and added the directory to the path in the program. 我已将库包含在我的\\ Lib \\ site-packages目录中,并将该目录添加到程序中的路径中。 Here is the test code I'm using - a simple counting program: 这是我正在使用的测试代码 - 一个简单的计数程序:

import sys
from threading import Timer

sys.path.append('C:\Users\[user]\Documents\Visual Studio 2015\Projects\Testing Timer Compilation issue\Testing Timer Compilation issue')
sys.path.append('C:\Users\[user]\Documents\Visual Studio 2015\Projects\Testing Timer Compilation issue\Testing Timer Compilation issue\Lib')

class Chron():
    def __init__(self):
        self.t = Timer(2, self.count)
        self.t.start()
        self.i = 0

    def count(self):
        print(self.i)
        self.i += 1
        if self.i <= 15:
            self.t = Timer(2, self.count)
            self.t.start()

c = Chron()

Works perfectly in the Interactive Interpreter within Visual Studio, but once I use pyc.py to compile to an exe file, it will not run, and simply closes after ~5 seconds, no exception thrown. 在Visual Studio中的Interactive Interpreter中完美运行,但是一旦我使用pyc.py编译为exe文件,它就不会运行,只需在~5秒后关闭,不会抛出任何异常。

As mentioned in the previous question, I have a program with a Timer in it that I need compiled, as the source code contains sensitive credentials. 正如前一个问题中所提到的,我有一个程序,其中包含一个我需要编译的Timer,因为源代码包含敏感凭据。 Are there any tricks necessary to make the Timer work within an exe? 是否有任何必要的技巧使Timer在exe中工作? Is it simply incompatible? 它只是不兼容吗?

Edit: 6 days without an answer. 编辑:6天没有答案。 Unfortunately, there doesn't seem to be any resources for this specific issue anywhere on the internet. 不幸的是,互联网上似乎没有任何资源可以解决这个特定问题。 It's almost as if I'm the only one having this issue. 这几乎就像我是唯一一个有这个问题的人。 This seems strange to me, since the problem seems to be with the Timer object itself, and I can't imagine that no one else has tried to deploy an application with a Timer in it. 这对我来说似乎很奇怪,因为问题似乎与Timer对象本身有关,我无法想象没有其他人试图在其中部署带有Timer的应用程序。 Any insight would be helpful at this point, as I am completely stumped. 任何见解在这一点上都会有所帮助,因为我完全难过。

The problem is that you are relying on the underlying Python interpreter to gracefully handle the case where the main thread of your executable has terminated, but there should be some others still running. 问题是你依靠底层的Python解释器来优雅地处理你的可执行文件的主线程终止的情况,但应该还有一些其他的仍在运行。

Running the code directly with CPython or IronPython works as expected. 使用CPython或IronPython直接运行代码可以正常工作。 The Timer objects that you create are actually a specialization of a Thread. 您创建的Timer对象实际上是Thread的特化。 The interpreter recognizes that there are some non-daemon Threads still active and so doesn't terminate. 解释器识别出一些非守护进程的线程仍处于活动状态,因此不会终止。 See the docs for an explanation of daemon threads if you don't know the difference between the 2 types of Threads. 如果您不知道两种类型的线程之间的区别,请参阅文档以获取有关守护程序线程的说明。

However, when you run as an executable, it would appear that the code IronPython uses to wrap the interpreter is not so kind. 但是,当您作为可执行文件运行时,看起来IronPython用来包装解释器的代码并不那么友好。 It just waits for the main thread to end and then closes everything. 它只是等待主线程结束然后关闭所有内容。 This happens despite the fact that your Timers are declared to be non-daemon Threads. 尽管您的计时器被声明为非守护程序线程,但仍会发生这种情况。 Arguably this is a bug in IronPython. 可以说这是IronPython中的一个错误。

The solution is therefore to leave your main thread running while your Timer threads are still operating. 因此,解决方案是在Timer线程仍在运行时让主线程运行。 The simplest way to do that for this sample code is just to sleep - for example: 对此示例代码执行此操作的最简单方法就是睡眠 - 例如:

import sys
sys.path.append(r"c:\Program Files (x86)\IronPython 2.7\Lib")
from threading import Timer
from time import sleep

class Chron():
    def __init__(self):
        self.t = Timer(2, self.count)
        self.t.start()
        self.i = 0

    def count(self):
        print(self.i)
        self.i += 1
        if self.i <= 15:
            self.t = Timer(2, self.count)
            self.t.start()

c = Chron()
sleep(35)

However, for more complicated applications, you should consider some communication between your threads to coordinate when to close - eg using join() to wait for thread termination. 但是,对于更复杂的应用程序,您应该考虑线程之间的一些通信以协调何时关闭 - 例如使用join()来等待线程终止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM