From 4b49248f2a5dd07bbe5a6223b20879e3b874c3b5 Mon Sep 17 00:00:00 2001 From: Brent Vollebregt Date: Sat, 5 Oct 2024 13:34:17 +1300 Subject: [PATCH] Add examples with configurations --- MANIFEST.in | 1 + README.md | 9 +++ examples/1-basic/auto-py-to-exe-config.json | 17 +++++ examples/1-basic/main.py | 4 ++ examples/1-basic/readme.md | 36 ++++++++++ .../2-no-console/auto-py-to-exe-config.json | 17 +++++ examples/2-no-console/main.py | 11 +++ examples/2-no-console/readme.md | 22 ++++++ .../assets/data.json | 5 ++ .../assets/image.gif | Bin 0 -> 11262 bytes .../auto-py-to-exe-config.json | 21 ++++++ .../3-images-and-other-non-py-files/main.py | 34 ++++++++++ .../3-images-and-other-non-py-files/readme.md | 28 ++++++++ .../auto-py-to-exe-config.json | 17 +++++ examples/4-persistent-data/main.py | 41 +++++++++++ examples/4-persistent-data/readme.md | 64 ++++++++++++++++++ 16 files changed, 327 insertions(+) create mode 100644 examples/1-basic/auto-py-to-exe-config.json create mode 100644 examples/1-basic/main.py create mode 100644 examples/1-basic/readme.md create mode 100644 examples/2-no-console/auto-py-to-exe-config.json create mode 100644 examples/2-no-console/main.py create mode 100644 examples/2-no-console/readme.md create mode 100644 examples/3-images-and-other-non-py-files/assets/data.json create mode 100644 examples/3-images-and-other-non-py-files/assets/image.gif create mode 100644 examples/3-images-and-other-non-py-files/auto-py-to-exe-config.json create mode 100644 examples/3-images-and-other-non-py-files/main.py create mode 100644 examples/3-images-and-other-non-py-files/readme.md create mode 100644 examples/4-persistent-data/auto-py-to-exe-config.json create mode 100644 examples/4-persistent-data/main.py create mode 100644 examples/4-persistent-data/readme.md diff --git a/MANIFEST.in b/MANIFEST.in index 3618ed0d..741e33b7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include README.md include LICENSE graft auto_py_to_exe/web +prune examples diff --git a/README.md b/README.md index fb0cf740..6d0eaace 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,15 @@ Instead of inserting the same data into the UI over and over again, you can expo This JSON config export action does not save the output directory automatically as moving hosts could mean different directory structures. If you want to have the output directory in the JSON config, add the directory under `nonPyinstallerOptions.outputDirectory` in the JSON file (will need to create a new key). +## Examples + +The [examples/](./examples/) directory offers some examples of how to write your scripts and package them with auto-py-to-exe. + +- [Basic (console application)](./examples/1-basic/readme.md) +- [No Console (as typically desired for GUI-based applications)](./examples/2-no-console/readme.md) +- [Images and other non-.py files (static files to be included)](./examples/3-images-and-other-non-py-files/readme.md) +- [Persistent data (like databases)](./examples/4-persistent-data/readme.md) + ## Video If you need something visual to help you get started, [I made a video for the original release of this project](https://youtu.be/OZSZHmWSOeM); some things may be different but the same concepts still apply. diff --git a/examples/1-basic/auto-py-to-exe-config.json b/examples/1-basic/auto-py-to-exe-config.json new file mode 100644 index 00000000..a42ad7de --- /dev/null +++ b/examples/1-basic/auto-py-to-exe-config.json @@ -0,0 +1,17 @@ +{ + "version": "auto-py-to-exe-configuration_v1", + "pyinstallerOptions": [ + { + "optionDest": "filenames", + "value": "./main.py" + }, + { + "optionDest": "onefile", + "value": true + }, + { + "optionDest": "console", + "value": true + } + ] +} diff --git a/examples/1-basic/main.py b/examples/1-basic/main.py new file mode 100644 index 00000000..ea7bc7d8 --- /dev/null +++ b/examples/1-basic/main.py @@ -0,0 +1,4 @@ +import sys + +print("Hello world") +print(f"Running with Python {sys.version}") diff --git a/examples/1-basic/readme.md b/examples/1-basic/readme.md new file mode 100644 index 00000000..5b2009c0 --- /dev/null +++ b/examples/1-basic/readme.md @@ -0,0 +1,36 @@ +# Example 1 - Basic + +[This example](./main.py) is a basic Hello World application. Nothing is out of the ordinary in this example. + +## Packaging + +To package this, you can use `auto-py-to-exe` and use "Console Based". + +- "Console Based" is needed because we need to be able to output the `print` call. If we were to use "Window Based", we would no longer have access to stdout and it would be like we were running the script as a .pyw file - in this case `print` would error. + +### Using the Configuration + +An auto-py-to-exe config is [supplied here](./auto-py-to-exe-config.json). + +1. Open a terminal in this directory (`examples/1-basic`) +2. Execute `auto-py-to-exe --config auto-py-to-exe-config.json` to open auto-py-to-exe with the supplied config +3. Click the big blue convert button at the bottom +4. When done, click the big blue "OPEN OUTPUT FOLDER" to view the output exe + +## Running + +Run the output exe using the terminal. If you double-click on it, it will run, but the console will close immediately. Running the exe from the terminal will allow you to see the output. + +To run the exe using the terminal in Windows (similar for other OS'): + +1. Open cmd +2. cd to the directory that the exe was generated in +3. Execute `main.exe` to run the executable. + +Here is an example of the output: + +``` +C:\Users\USER\Repos\auto-py-to-exe\examples\1-basic\output>main.exe +Hello world +Running with Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] +``` diff --git a/examples/2-no-console/auto-py-to-exe-config.json b/examples/2-no-console/auto-py-to-exe-config.json new file mode 100644 index 00000000..0f94485d --- /dev/null +++ b/examples/2-no-console/auto-py-to-exe-config.json @@ -0,0 +1,17 @@ +{ + "version": "auto-py-to-exe-configuration_v1", + "pyinstallerOptions": [ + { + "optionDest": "filenames", + "value": "./main.py" + }, + { + "optionDest": "onefile", + "value": true + }, + { + "optionDest": "console", + "value": false + } + ] +} diff --git a/examples/2-no-console/main.py b/examples/2-no-console/main.py new file mode 100644 index 00000000..8d1b2089 --- /dev/null +++ b/examples/2-no-console/main.py @@ -0,0 +1,11 @@ +import tkinter as tk + +# Setup the window +window = tk.Tk() + +# Add the label +greeting = tk.Label(text="Hello from Tkinter", padx=40, pady=15) +greeting.pack() + +# Keep the script running until the GUI closes +window.mainloop() diff --git a/examples/2-no-console/readme.md b/examples/2-no-console/readme.md new file mode 100644 index 00000000..27079c1c --- /dev/null +++ b/examples/2-no-console/readme.md @@ -0,0 +1,22 @@ +# Example 2 - No Console + +[This example](./main.py) is a basic GUI application. + +## Packaging + +To package this, you can use `auto-py-to-exe` and use "Window Based". + +- Make sure "Window Based" is used otherwise a blank terminal will also appear (which we do not need as we are not calling `print`). + +### Using the Configuration + +An auto-py-to-exe config is [supplied here](./auto-py-to-exe-config.json). + +1. Open a terminal in this directory (`examples/2-no-console`) +2. Execute `auto-py-to-exe --config auto-py-to-exe-config.json` to open auto-py-to-exe with the supplied config +3. Click the big blue convert button at the bottom +4. When done, click the big blue "OPEN OUTPUT FOLDER" to view the output exe + +## Running + +You can run the exe using a terminal or by double-clicking it. Since we have used `window.mainloop()`, the application will keep running until the window is closed. diff --git a/examples/3-images-and-other-non-py-files/assets/data.json b/examples/3-images-and-other-non-py-files/assets/data.json new file mode 100644 index 00000000..08d74514 --- /dev/null +++ b/examples/3-images-and-other-non-py-files/assets/data.json @@ -0,0 +1,5 @@ +{ + "data1": 1, + "data2": 2, + "data3": 3 +} diff --git a/examples/3-images-and-other-non-py-files/assets/image.gif b/examples/3-images-and-other-non-py-files/assets/image.gif new file mode 100644 index 0000000000000000000000000000000000000000..d4a557bec590f27d7f28e8a020f16e91c275af6f GIT binary patch literal 11262 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 X$HDrKBaWj}yQA~h2M{zF04V(*Ud{^# literal 0 HcmV?d00001 diff --git a/examples/3-images-and-other-non-py-files/auto-py-to-exe-config.json b/examples/3-images-and-other-non-py-files/auto-py-to-exe-config.json new file mode 100644 index 00000000..6450ab14 --- /dev/null +++ b/examples/3-images-and-other-non-py-files/auto-py-to-exe-config.json @@ -0,0 +1,21 @@ +{ + "version": "auto-py-to-exe-configuration_v1", + "pyinstallerOptions": [ + { + "optionDest": "filenames", + "value": "./main.py" + }, + { + "optionDest": "onefile", + "value": true + }, + { + "optionDest": "console", + "value": false + }, + { + "optionDest": "datas", + "value": "./assets;assets/" + } + ] +} diff --git a/examples/3-images-and-other-non-py-files/main.py b/examples/3-images-and-other-non-py-files/main.py new file mode 100644 index 00000000..009485ed --- /dev/null +++ b/examples/3-images-and-other-non-py-files/main.py @@ -0,0 +1,34 @@ +import os +import sys +import tkinter as tk +from pathlib import Path + + +def resource_path(relative_path): + """Get the absolute path to the resource, works for dev and for PyInstaller""" + try: + # PyInstaller creates a temp folder and stores path in _MEIPASS + base_path = sys._MEIPASS + except Exception: + # If we are still in dev mode, make our paths start from the folder this file is in + base_path = Path(__file__).parent + + return os.path.join(base_path, relative_path) + + +# Setup the window +window = tk.Tk() + +# Show the image +image = tk.PhotoImage(file=resource_path("assets/image.gif")) +image_label = tk.Label(window, image=image) +image_label.pack() + +# Show the contents of the JSON file +with open(resource_path("assets/data.json")) as f: + data = f.read() + data_label = tk.Label(text=data, padx=40, pady=15) + data_label.pack() + +# Keep the script running until the GUI closes +window.mainloop() diff --git a/examples/3-images-and-other-non-py-files/readme.md b/examples/3-images-and-other-non-py-files/readme.md new file mode 100644 index 00000000..7ab3d842 --- /dev/null +++ b/examples/3-images-and-other-non-py-files/readme.md @@ -0,0 +1,28 @@ +# Example 3 - Images and Other Non-.py Files + +[This example](./main.py) is a GUI application that also references a GIF (image) and a JSON file. + +## Packaging + +To package this, you can use `auto-py-to-exe` and use "Window Based". To add the GIF and JSON files, in the "Additional Files" section, click "Add Folder" and select the "assets" folder in this directory. + +- Make sure "Window Based" is used otherwise a blank terminal will also appear (which we do not need as we are not calling `print`). +- Adding the assets folder to the "Additional Files" section will make sure all files in that folder are included. When using "One Directory", you will be able to see the folder within the "\_internal" folder. +- You can use either "One Directory" or "One File" for this. The usage of `resource_path` in main.py means both will work. + +### Using the Configuration + +An auto-py-to-exe config is [supplied here](./auto-py-to-exe-config.json). + +1. Open a terminal in this directory (`examples/3-images-and-other-non-py-files`) +2. Execute `auto-py-to-exe --config auto-py-to-exe-config.json` to open auto-py-to-exe with the supplied config +3. Click the big blue convert button at the bottom +4. When done, click the big blue "OPEN OUTPUT FOLDER" to view the output exe + +## Running + +You can run the exe using a terminal or by double-clicking it. Since we have used `window.mainloop()`, the application will keep running until the window is closed. + +## Notes + +If you have used "One File" mode, any changes made to the JSON file will be overwritten every time. See example 4 for how to stop this. diff --git a/examples/4-persistent-data/auto-py-to-exe-config.json b/examples/4-persistent-data/auto-py-to-exe-config.json new file mode 100644 index 00000000..a42ad7de --- /dev/null +++ b/examples/4-persistent-data/auto-py-to-exe-config.json @@ -0,0 +1,17 @@ +{ + "version": "auto-py-to-exe-configuration_v1", + "pyinstallerOptions": [ + { + "optionDest": "filenames", + "value": "./main.py" + }, + { + "optionDest": "onefile", + "value": true + }, + { + "optionDest": "console", + "value": true + } + ] +} diff --git a/examples/4-persistent-data/main.py b/examples/4-persistent-data/main.py new file mode 100644 index 00000000..eabf1a58 --- /dev/null +++ b/examples/4-persistent-data/main.py @@ -0,0 +1,41 @@ +import json +import os +from pathlib import Path + +DEFAULT_DATA = {"count": 0} + +# First we identify where the persistent data should sit. +# It cannot be packaged inside our exe because if "One File" mode is used, it will be overwritten every time. +# For this example, I put the data file in the following folder: +# - If Windows: C:/Users/Brent/AppData/Local/AutoPyToExeDemo +# - If something else: The users home folder +# For your implementation, you can pick somewhere else - as long as it isn't in the project. +if os.name == "nt": + data_folder_location = Path.home() / "AppData/Local/AutoPyToExeDemo" +else: + data_folder_location = Path.home() / "AutoPyToExeDemo" + +# We create the directory if it doesn't exist. We also make sure to create any parents if they don't exist. +data_folder_location.mkdir(parents=True, exist_ok=True) + +# Next we check if the file exists. If not, we create it and put default data into it. +data_file_location = data_folder_location / "data.json" +if not data_file_location.exists(): + print(f"Data file doesn't exist. Creating at {data_file_location}") + with open(str(data_file_location), "w") as f: + json.dump(DEFAULT_DATA, f, indent=2) +else: + print(f"Data file exists at {data_file_location}") + +# We read the file in (as we know it exists now) +with open(str(data_file_location), "r") as f: + data = json.load(f) +print(f"Current contents: {data}") + +# We update the contents of the file +data["count"] += 1 + +# We write the file back +with open(str(data_file_location), "w") as f: + json.dump(data, f, indent=2) +print(f"Saved new contents: {data}") diff --git a/examples/4-persistent-data/readme.md b/examples/4-persistent-data/readme.md new file mode 100644 index 00000000..74d1c86c --- /dev/null +++ b/examples/4-persistent-data/readme.md @@ -0,0 +1,64 @@ +# Example 4 - Persistent Data + +[This example](./main.py) demonstrates how you can manage persistent data outside your executable. This is needed when you have something like a SQLite database or something else used to store data between application runs. + +When using "One File" mode, you should not store files you want to persist beside the executable because they will be overwritten on the next run. If you are using "One Directory", this is not an issue as the executable doesn't have to extract itself every time. + +## Packaging + +To package this, you can use `auto-py-to-exe` and use "Console Based". + +- "Console Based" is needed because we need to be able to output the `print` call. If we were to use "Window Based", we would no longer have access to stdout and it would be like we were running the script as a .pyw file - in this case `print` would error. + +> "Console Based" is only required for the demonstration as `print` calls are made. If you do not need stdout (like `print` does) in your application, you can use "Window Based". + +### Using the Configuration + +An auto-py-to-exe config is [supplied here](./auto-py-to-exe-config.json). + +1. Open a terminal in this directory (`examples/4-persistent-data`) +2. Execute `auto-py-to-exe --config auto-py-to-exe-config.json` to open auto-py-to-exe with the supplied config +3. Click the big blue convert button at the bottom +4. When done, click the big blue "OPEN OUTPUT FOLDER" to view the output exe + +## Running + +Run the output exe using the terminal. If you double-click on it, it will run, but the console will close immediately. Running the exe from the terminal will allow you to see the output. + +To run the exe using the terminal in Windows (similar for other OS'): + +1. Open cmd +2. cd to the directory that the exe was generated in +3. Execute `main.exe` to run the executable. + +When running the exe, you will see: + +- The target folder gets created if it doesn't exist +- The data file gets created with default data if it doesn't exist +- Even run increments the `count` value in the JSON file + +Here is an example of the output: + +``` +C:\Users\USER\Repos\auto-py-to-exe\examples\4-persistent-data\output>main.exe +Data file doesn't exist. Creating at C:\Users\USER\AppData\Local\AutoPyToExeDemo\data.json +Current contents: {'count': 0} +Saved new contents: {'count': 1} + +C:\Users\USER\Repos\auto-py-to-exe\examples\4-persistent-data\output>main.exe +Data file exists at C:\Users\USER\AppData\Local\AutoPyToExeDemo\data.json +Current contents: {'count': 1} +Saved new contents: {'count': 2} + +C:\Users\USER\Repos\auto-py-to-exe\examples\4-persistent-data\output>main.exe +Data file exists at C:\Users\USER\AppData\Local\AutoPyToExeDemo\data.json +Current contents: {'count': 2} +Saved new contents: {'count': 3} + +C:\Users\USER\Repos\auto-py-to-exe\examples\4-persistent-data\output>main.exe +Data file exists at C:\Users\USER\AppData\Local\AutoPyToExeDemo\data.json +Current contents: {'count': 3} +Saved new contents: {'count': 4} + +C:\Users\USER\Repos\auto-py-to-exe\examples\4-persistent-data\output> +```