简体   繁体   English

Pyinstaller可执行文件保持打开状态

[英]Pyinstaller executable keeps opening

Background 背景

I am working on face recognition following this link and I would like to build a standalone application using Python. 我正在通过此链接进行面部识别,我想使用Python构建一个独立的应用程序。 My main.py script looks like the following. 我的main.py脚本如下所示。

# main.py

# Import packages and other scripts
import tkinter as tk
...

# Some functions
def initialization():
    # OpenCV and sklearn are used here
    ...

def registration():
    # OpenCV, and sklearn are used here
    ...

def face_recognition():
    # OpenCV and sklearn are used here
    ...

# Start the Tkinter GUI
window = tk.Tk()

# Initialize the face recognition model
initialization()

# Input name for registration
tk.Label(window, text = "Name").grid(...)
entry1 = tk.Entry(window)
entry1.grid(row=0, column=1)

# When the button is clicked, different command is executed
tk.Button(window, text='Registration', command=registeration).grid(...) 
tk.Button(window, text='Face Recognition', command=face_recognition).grid(...)

window.mainloop()

Using python interpret to run the script ( python main.py ), everything works fine. 使用python python main.py来运行脚本( python main.py ),一切正常。


Problem 问题

I use Pyinstaller to convert the scripts to a single exe with this command: 我使用Pyinstaller将脚本转换为使用此命令的单个exe:

pyinstaller --onefile \
            --windowed \
            --hidden-import sklearn.neighbors.typedefs \
            main.py

Then, I have two exe generated. 然后,我有两个exe生成。 The first one is in dist/main and the second one is in dist/main.app/Contents/MacOS/main 第一个是dist/main ,第二个是dist/main.app/Contents/MacOS/main

When running the exe, the exe keeps duplicate itself. 运行exe时,exe会自行复制。 I display the running process and found this result 我显示正在运行的进程并找到了这个结果

$ ps
PID    TTY    TIME    CMD
...    ...    ...     /path/to/main -B -s -S -E -c from multiprocessing.semaphore_tracker import main:main(8)
...    ...    ...     /path/to/main -B -s -S -E -c from multiprocessing.semaphore_tracker import main:main(8)
...    ...    ...     /path/to/main -B -s -S -E -c from multiprocessing.semaphore_tracker import main:main(7)
...    ...    ...     /path/to/main -B -s -S -E -c from multiprocessing.semaphore_tracker import main:main(7)
...    ...    ...     /path/to/main -B -s -S -E -c from multiprocessing.semaphore_tracker import main:main(8)

I have no idea what happens to the exe since I do not import multiprocessing packages in my scripts. 我不知道exe会发生什么,因为我没有在我的脚本中导入多处理包。 Any idea how to fix this problem? 知道如何解决这个问题吗? Thanks 谢谢


Update 1 更新1

I added a --log-level ERROR when using Pyinstaller and gives this result. 我在使用Pyinstaller时添加了一个--log-level ERROR并给出了这个结果。 Not sure if it is related to my problem. 不确定它是否与我的问题有关。

Traceback (most recent call last):
  File "<string>", line 2, in <module>
ModuleNotFoundError: No module named 'Crypto.Math'
174598 INFO: MKL libraries found when importing numpy. Adding MKL to binaries
176282 ERROR: Can not find path ./libtbb.dylib (needed by /Users/user/anaconda3/lib/libmkl_tbb_thread.dylib)

Update 2 更新2

I found out that one of the packages that I am using -- imultis VideoStream involves threading . 我发现我使用的其中一个软件包 - imultis VideoStream涉及threading I guess it is the reason for observing from multiprocessing.semaphore_tracker as shown above even though I do not import multiprocessing explicitly. 我想这是from multiprocessing.semaphore_tracker上面显示的from multiprocessing.semaphore_tracker观察的原因,即使我没有显式import multiprocessing

Then I come across with this post , suggesting to add multiprocessing.freeze_support() . 然后我遇到这篇文章 ,建议添加multiprocessing.freeze_support() It can suppress the GUI window from keep duplicating, but the background processes as shown using $ ps still keep duplicating. 它可以抑制GUI窗口保持重复,但使用$ ps显示的后台进程仍然保持重复。 The problem has not fixed yet. 问题尚未解决。


Update 3 (Issue located but not fix) 更新3(问题已定位但未修复)

After debugging the code for quite a while, it turns out that the causes of this infinite looping is NOT due to the threading of imultis VideoStream (I write another script to test imultis and it is completely OK). 在调试代码很长一段时间之后,事实证明这种无限循环的原因不是由于imultis VideoStream的threading化(我编写另一个脚本来测试imultis并且它完全没问题)。 But the problem comes from importing sklearn !!! 但问题来自于导入sklearn !!! This problem has been reported in GitHub in this link . 链接已在GitHub中报告此问题。

This GitHub link also suggest to include multiprocessing.freeze_support() . 此GitHub链接还建议包括multiprocessing.freeze_support() Moreover one of the responses suggests to import sklearn after multiprocessing.freeze_support() is called. 此外,其中一个响应建议在multiprocessing.freeze_support()后导入sklearn 。调用sklearn multiprocessing.freeze_support() I try it with a simple script but the problem is still here. 我用一个简单的脚本尝试它,但问题仍然存在。

Conclusion : sklearn causes the executable keeps opening. 结论sklearn导致可执行文件保持打开状态。 But I have no idea why it is the case, and I do not know how to solve it. 但我不知道为什么会这样,我不知道如何解决它。 Any help would be appreciated. 任何帮助,将不胜感激。 Thanks. 谢谢。

I met the same issue. 我遇到了同样的问题。 Scikit-learn provides a workaround. Scikit-learn提供了一种解决方法。

https://scikit-learn.org/stable/faq.html#why-do-i-sometime-get-a-crash-freeze-with-n-jobs-1-under-osx-or-linux https://scikit-learn.org/stable/faq.html#why-do-i-sometime-get-a-crash-freeze-with-n-jobs-1-under-osx-or-linux

I added below codes at the beginning of my script and fixed my issue: 我在脚本的开头添加了以下代码并修复了我的问题:

import multiprocessing
multiprocessing.set_start_method('forkserver', force=True)
multiprocessing.freeze_support()

Hope this can also fix yours. 希望这也可以解决你的问题。

This fix does not work on macOS - the problem still persists if you freeze an app with PyInstaller that calls sklearn. 此修复程序不适用于macOS - 如果您使用调用sklearn的PyInstaller冻结应用程序,问题仍然存在。 I am running Python 3.7.2 with PyInstaller 3.4 and PyQT5 5.12, on macOS Mojave 10.14.3. 我在macOS Mojave 10.14.3上使用PyInstaller 3.4和PyQT5 5.12运行Python 3.7.2。

This answer does a good job explaining why this happens: https://stackoverflow.com/a/55382641/109525 这个答案很好地解释了为什么会发生这种情况: https//stackoverflow.com/a/55382641/109525

First try setting this before starting your program: 首先尝试在启动程序之前设置此项:

export JOBLIB_MULTIPROCESSING=0

If it works, you can add a runtime hook to your program to set the environment variable automatically. 如果可行,则可以向程序添加运行时挂钩以自动设置环境变量。 See: https://pythonhosted.org/PyInstaller/when-things-go-wrong.html#changing-runtime-behavior 请参阅: https//pythonhosted.org/PyInstaller/when-things-go-wrong.html#changing-runtime-behavior

Starting my main entry point with: 从我的主要入口点开始:

from multiprocessing import freeze_support
freeze_support()

Worked for me! 为我工作!

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

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