从Python setuptools创建可启动的GUI脚本(无控制台窗口!)

10

我目前为我的基于Python的GUI添加可执行文件的方法如下:

setup(
      # ...
      entry_points = {"gui_scripts" : ['frontend = myfrontendmodule.launcher:main']},
      # ...
      )
在Windows上,这将在Python的scripts文件夹中创建“frontend.exe”和“frontend-script.pyw”(使用Python 2.6)。当我执行EXE文件时,会显示一个控制台窗口,但PYW文件可以正常工作而无需显示控制台窗口。
所以我的问题是:如何使EXE文件在没有控制台窗口的情况下执行程序?解决方案也应该适用于Linux(不要建议py2exe ;))。
2个回答

12

好的,我在setuptools源代码中进行了一些调查,发现问题归结为setuptools(easy_install.py)中的一个bug:

# On Windows/wininst, add a .py extension and an .exe launcher
if group=='gui_scripts':
    ext, launcher = '-script.pyw', 'gui.exe'
    old = ['.pyw']
    new_header = re.sub('(?i)python.exe','pythonw.exe',header)
else:
    ext, launcher = '-script.py', 'cli.exe'
    old = ['.py','.pyc','.pyo']
    new_header = re.sub('(?i)pythonw.exe','python.exe',header)

if os.path.exists(new_header[2:-1]) or sys.platform!='win32':
    hdr = new_header
else:
    hdr = header

最后的if语句决定了将pythonw.exe或python.exe的路径写入"frontend-script.pyw"的shebang中。由于该shebang由创建的EXE文件评估,因此需要确保else语句不被执行。问题在于,在我的情况下,new_header[2:-1]是带引号的"C:\Program Files (x86)\Python26\pythonw.exe",所以os.path.exists由于引号而导致无法找到它。

我会尝试让setuptools的开发人员进行更正。剩下的问题将是absolute pythonw.exe路径。如果我创建一个Windows设置/MSI安装程序,shebang将包含我的pythonw.exe路径("C:\Program Files (x86)\Python26\pythonw.exe"),但用户可能已经安装了Python在"C:\Python26"。我会在报告这个问题后报告最终的解决方案。


我在两年前发布了这篇文章,很抱歉我还没有提供我的解决方案。不确定是否有更现代的解决方案(可能distribute提供了一些),但以下是我当时使用的内容(复制粘贴):

文件dogsync-frontend-script.pyw

#!pythonw.exe

# This script will be executed by the primary Python version that is installed, which might as well be Python 3. But
# we want to execute it with the Python version that belongs to this script's path. So let's do a major hack:

import os
import sys
import subprocess

if sys.argv[-1] == "magic":
    from dogsync_frontend.launcher import main
    main()
else:
    # The CPython folder hierarchy is assumed here (<installation>\pythonw.exe, <installation>\Scripts\<thisscript>)
    subprocess.Popen([os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "pythonw.exe")),
                      __file__,
                      "magic"])

文件 dogsync-frontend.exe

自动从<python安装路径>\lib\site-packages\setuptools\gui.exe复制而来(见下文)。如果我没记错,此文件将自动执行脚本<EXE名称>-script.py[w]

文件 setup.py

from setuptools import __file__ as setupToolsFilename

if os.name == "nt":
    # Use a customized (major hack) start script instead of the one that gets automatically created by setuptools
    # when the "gui_scripts" parameter is used. This way, we don't need setuptools installed in order to run DogSync.
    shutil.copy2(os.path.join(os.path.dirname(setupToolsFilename), "gui.exe"),
                 "build-environment/windows-scripts/dogsync-frontend.exe")
    startScripts = dict(scripts = ["build-environment/windows-scripts/dogsync-frontend-script.pyw",
                                   "build-environment/windows-scripts/dogsync-frontend.exe"])
else:
    # For Linux, I don't have a solution to remove the runtime dependency on setuptools (yet)
    startScripts = dict(entry_points = {"gui_scripts" : ['dogsync-frontend = dogsync_frontend.launcher:main']})

setup(<other options>,
      **startScripts)

使用这个设置,exe/pyw文件会被复制到<python installation>\Scripts(在Windows上),启动dogsync-frontend.exe将运行pyw脚本而不需要控制台。由于setuptools多年来没有更新,这个解决方案仍然有效。

1
谢谢!我已经在SVN中为您修复了一个问题(在exists()调用中对路径执行.strip('"')操作),并且它将在明天的快照版本中提供。现在使用“easy_install -U setuptools==dev06”升级到SVN版本并尝试一下吧! - PJ Eby
@pjeby:太棒了,那甚至是在我能使用新创建的错误跟踪器帐户之前。谢谢,我会尽快尝试它的。 - AndiDog
1
@pjeby:我已经在http://bugs.python.org/setuptools/issue112上报告了绝对路径的错误。 - AndiDog
我看到你提出的错误还没有关闭。你在使用绝对路径时有问题吗? - Piotr Dobrogost
@PiotrDobrogost:请看一下我是如何解决的,我只是添加了我的解决方案。setuptools没有更新,因为它被“distribute”取代了。我没有检查他们是否以某种方式修复了它。 - AndiDog

0

为什么不在Linux上使用.pyw文件,在Windows上使用py2exe呢?


1
因为在http://packages.python.org/distribute/setuptools.html上的更新日志中写道:“0.6a3-添加了gui_scripts入口点组,以允许在Windows和其他平台上安装GUI脚本。(特殊处理仅适用于Windows;其他平台与console_scripts相同。)”。所以我认为他们进行了一些更改以适应Windows。而我有更新的版本0.6c11。 - AndiDog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接