Create a GUI executable file created with tkinter

One day

I made a script in Python that uses subprocess to execute an external tool, and I made something that can be executed by hitting a Python command. (In short, a wrapper for external tools)

However, the user is not the person who opens the terminal and uses it, so I'm glad that I can click on it with the GUI.

And, as always, a lot of addictive days.

tkinter (PySimpleGUI)

It seems that Python comes with a GUI toolkit called ** tkinter [^ 1] ** as standard. If you use this, it seems that you can make a GUI even if it is temporary.

When I asked Google teacher a little bit, I arrived at the article If you use Tkinter, try using PySimpleGUI ** PySimpleGUI [^ 2] I came across a wrapper library for tkinter (and Qt, WxPython, Remi) called] **.

Here, in addition to tkinter, if you use Qt, WxPython, Remi, you will know that you can make a GUI with Python. (I don't want to create a GUI in Python separately, I just want a GUI that can easily execute Python code, so in reality anything is fine)

tkinter is not installed ?? </ font>

I immediately tried Hello World by referring to PySimpleGUI --Jump Start, but I still suffer from the following error.

Terminal


$ python hello.py 
Traceback (most recent call last):
  File "hello.py", line 1, in <module>
    import PySimpleGUI as sg
  File "/Users/chibi/.pyenv/versions/3.8.2/lib/python3.8/site-packages/PySimpleGUI/__init__.py", line 2, in <module>
    from .PySimpleGUI import *
  File "/Users/chibi/.pyenv/versions/3.8.2/lib/python3.8/site-packages/PySimpleGUI/PySimpleGUI.py", line 103, in <module>
    import tkinter as tk
  File "/Users/chibi/.pyenv/versions/3.8.2/lib/python3.8/tkinter/__init__.py", line 36, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

PySimpleGUI should not be bad, so it will be installed correctly by the following command described in Python interface of Tcl / Tk. Check if it is.

Terminal


$ python -m tkinter

Of course, I think it wasn't installed correctly, so I get the same error.

Although it was delayed to describe, this environment is as follows.

  • MacOS Catalina: 10.15.4
  • Python: 3.8.2
  • pip: 20.0.2

And the article that I referred to in this issue is How to use tkinter with python in pyenv. This article was exactly the answer because I use pyenv.

You should install something called tcl-tk with brew. In addition, you should add an option when building Python and reinstall Python. Use the previous command to check if the installation is successful.

Terminal


$ python -m tkinter
20200509152812.png

There seems to be no problem!

Next, try running Hello World of PySimpleGUI.

20200509153240.png

There seems to be no problem! !!

How to start the implemented GUI ... ?? </ font>

For the time being, Hello World is complete, so let's actually create a GUI. However, there are only two functions: "** File selection dialog ** allows you to select a file" and "** Run button ** allows you to use the selected file path".

You couldn't just double-click a Python file implemented using PySimpleGUI to actually launch the GUI. After all, you have to enter the Python command as follows:

#Gui with GUI.py(Temporary)To execute.
$ python gui.py

With this, the execution target has changed from a Python file ** that uses subprocess to a Python file ** that uses PySimpleGUI, and it has not escaped from execution from the terminal. What I want to do here is to put it in the Dock like a normal ** application ** and start it with a click. That is.

py2app

Now, it's time to rely on Google teachers again. I got stuck with several types, but I decided to use ** py2app [^ 3] **. Here, I referred to the following article. Create a native Mac app with py2app

The work flow is as follows.

  1. Install py2app with pip
  2. Generate a setup script with py2app
  3. Execute (build) the script ← Here error </ font>

Error in setup script ?? </ font>

Terminal


$ python setup.py py2app
~ Abbreviation ~
ValueError: '/Users/chibi/.pyenv/versions/3.8.2/lib/libpython3.8.dylib' does not exist

There is no .dylib ~. When I actually go to see it, I have libpython3.8.a but not .dylib.

[Make it a standalone app on python Mac](https://medium.com/@Dorobune/python-mac%E3%81%A7%E3%82%B9%E3%82%BF%E3%83%B3%E3 % 83% 89% E3% 82% A2% E3% 83% AD% E3% 83% B3% E3% 82% A2% E3% 83% 97% E3% 83% AA% E3% 81% AB% E3% 81 % 99% E3% 82% 8B-py2app-9ef3057519c) If you refer to it, you can play with the parameters of setup.py. .. .. It's Python 3.8.2 in my environment, so I'll try it with some changes.

setup.py


  from setuptools import setup

  APP = ['gui.py']
  DATA_FILES = []
- OPTIONS = {}
+ OPTIONS = {
+     'argv_emulation':True,
+     'plist': {
+         'PyRuntimeLocations': [
+             '@executable_path/../Frameworks/libpython3.8m.dylib',
+             '/Users/chibi/.pyenv/versions/3.8.2/lib/libpython3.8m.dylib'
+         ]
+     }
+ }

  setup(
      app=APP,
      data_files=DATA_FILES,
      options={'py2app': OPTIONS},
      setup_requires=['py2app'],
  )

No, when I tried this, there is no .dylib in /Users/chibi/.pyenv/versions/3.8.2/lib/, so I can't do it. I see people in the Anaconda environment, such as older versions, but I wonder if there is a .dylib in another environment from the beginning.

I decided to use the existing .a as a trial, but my expectations were empty and it was useless.

Actually tried setup.py (folding)

setup.py


  from setuptools import setup

  APP = ['gui.py']
  DATA_FILES = []
  OPTIONS = {
      'argv_emulation':True,
      'plist': {
          'PyRuntimeLocations': [
              '@executable_path/../Frameworks/libpython3.8m.dylib',
-             '/Users/chibi/.pyenv/versions/3.8.2/lib/libpython3.8m.dylib'
+             '/Users/chibi/.pyenv/versions/3.8.2/lib/libpython3.8.a'
          ]
      }
  }

  setup(
      app=APP,
      data_files=DATA_FILES,
      options={'py2app': OPTIONS},
      setup_requires=['py2app'],
  )

Apparently static library doesn't work and you have to prepare a shared library.

In pyenv, it seems that PYTHON_CONFIGURE_OPTS =" --enable-framework " should be present at the time of installation. Then, it seems that libpython is placed as a shared library. Similar to tkinter, it seems that there are not enough options when going through pyenv. PYTHON_CONFIGURE_OPTS is an environment variable that was also needed for tkinter, so I'll add --enable-framework and try installing Python again.

If all goes well, you will have dist / xxx.app. By the way, at this time, the setup.py mentioned above should be left as the default. In other words, ʻOPTIONS` can be left as an empty array.

Double-click on xxx.app to open it. .. ..

20200510180322.png

Like this. You can select a file and there is a run button.

GUI doesn't pass ?? </ font>

When I tried to check the operation, I was told that there was no specific external tool in the which command that was executed internally. Since the PATH itself is written in .bashrc and .bash_profile, it seems that the path is in the state from the terminal, but the path is not in the state from the GUI. How do you register environment variables like Windows?

See Exploring how to set environment variables for GUI apps on macOS.

Terminal


$ sudo launchctl config user path <PATH information you want to set>

You can set it like this. A reboot is also required. By the way, as it was written in the above article, the path set by launchctl is saved in the following. /var/db/com.apple.xpc.launchd/config/user.plist

After restarting, when I ran the tool I made again, the subprocess worked as expected, and the execution result was as expected.

Summary

I was addicted to various things, but a little tool that works as expected was completed.

  • GUI
    • tkinter (PySimpleGUI)
    • tcl-tk --Setting environment variables for Python installation (tcl, tk related) --Executable file
    • py2app --Setting environment variables for Python installation (--enable-framework) --GUI environment variables
    • launchctl

[^ 1]: Python interface for Tcl / Tk

Recommended Posts