Python GUI entry point not working on Bash for Windows

Question:

I have a Python GUI app (using either PyQt5 or PySide2) which I would like to start with the command mypackage. Therefore, I added the following section to setup.cfg:

[options.entry_points]
gui_scripts =
    mypackage = mypackage:main

On Linux and macOS, installing the package with pip successfully creates a mypackage command which starts the app. However, on Windows I get an error message after typing mypackage in a Git Bash terminal: a dialog pops up titled "Fatal Error in Launcher" saying "stderr duplication failed". Note that everything works fine when I use Command Prompt (cmd.exe) or Power Shell (powershell.exe).

Relevant package structure:

mypackage/
    mypackage/
        __init__.py
        __main__.py
    pyproject.toml
    setup.cfg

__init__.py:

import sys
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QApplication, QLabel

                                           
def main():
    app = QApplication(sys.argv)
    label = QLabel("Hello World", alignment=Qt.AlignCenter)
    label.show()
    sys.exit(app.exec_())

__main__.py:

from . import main


if __name__ == "__main__":
    main()

pyproject.toml:

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

setup.cfg:

[metadata]
name = mypackage
version = 0.0.1

[options]
packages = mypackage

[options.entry_points]
gui_scripts =
    mypackage = mypackage:main

Steps to reproduce:

  1. Install Python (3.9.8 from https://www.python.org/) and then pip install PySide2
  2. Open a Git Bash on Windows and change into the root project folder mypackage
  3. pip install .
  4. Type mypackage – a dialog with the error pops up

Again, if I use Command Prompt or Power Shell in step 3, everything works!

All files are available in this repo: https://github.com/cbrnr/stderr-duplication

Asked By: cbrnr

||

Answers:

I recently experienced the same problem and realized that it was because I had not defined main() in my PyQt application. From pouring over SO posts and PyQt tutorials, it doesn’t appear that defining main() is a convention (I would be interested to know why this is). To fix this this I did some simple restructuring:

Old

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()

Restructured

def main():
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()

if __name__ == '__main__':
    main()

This allowed my to use the entry point in setup.py

entry_points={
        'console_scripts':[
            'my_gui=my_gui:main',
            ]}
Answered By: Ian Gilman

This was actually a bug which has been fixed in https://github.com/pypa/pip/issues/10875. Using pip ≥ 22.3 should now work.

Answered By: cbrnr