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

时间:2010-08-22 15:51:48

标签: python setuptools distutils

我目前为基于Python的GUI添加可执行文件的方式是:

setup(
      # ...
      entry_points = {"gui_scripts" : ['frontend = myfrontendmodule.launcher:main']},
      # ...
      )

在Windows上,这将在Python的脚本文件夹(使用Python 2.6)中创建“frontend.exe”和“frontend-script.pyw”。当我执行EXE文件时,会显示一个控制台窗口,但PYW文件正常工作而不显示。

所以我的问题是:如何在没有控制台窗口的情况下让EXE文件执行程序?该解决方案也适用于Linux(不建议使用py2exe;)。

2 个答案:

答案 0 :(得分:10)

好吧,我在setuptools源代码中进行了一些调查,结果归结为setuptools中的一个错误(easy_install.py):

# 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开发人员更正此问题。剩下的问题将是绝对的pythonw.exe路径。如果我创建Windows安装程序/ MSI安装程序,shebang将包含我的pythonw.exe路径(“C:\ Program Files(x86)\ Python26 \ pythonw.exe”)但用户可能已在“C:\ Python26”中安装了Python ”。在我报告此问题后,我将报告最终解决方案。


两年前我发布了这个,对不起,我还没有提供我的解决方案。不确定是否有更现代的解决方案(可能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 installation>\lib\site-packages\setuptools\gui.exe自动复制(见下文)。如果我没记错的话,该文件将自动执行脚本<name of 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 :(得分:0)

为什么不使用Linux的.pyw文件和Windows的py2exe文件?