[Python] exe化ツール v0.0.2 標準出力のデコード

前回の波カッコの問題は標準出力をデコードすることで解決しました。

実行前、distディレクトリ内に関連する旧ファイルがあれば手動で削除しておく必要があります(コードでは権限を変えても削除できませんでした)。

これでとりあえず完成でしょうか。

ただし、このコード自身をexe化してもうまく動作しないです。他のコードに対しては正常にexe化できます。カレントディレクトリを変更したりするのが良くないのかもしれません。

<関連箇所のみ>

def exe_make(path):
    # ソースコードの作業ディレクトリへのコピー
    working_dir = '/test_app/'
    new_path = working_dir + (path.split('test_GUI/'))[1]
    print(f'new_path {new_path}')
    shutil.copy2(path, new_path)

    # buildディレクトリ内関連ディレクトリの削除
    filename = (path.split('test_GUI/'))[1][:-3]
    remove_dir = '/test_app/build/' + filename + '/'
    try:
        shutil.rmtree(remove_dir)
    except:
        pass

    # 作業ディレクトリ内specファイルの削除
    all_files2 = [path for path in glob.glob('/test_app/*.spec')]
    remove_files2 = [path for path in all_files2 if filename in path]
    print(remove_files2)
    if len(remove_files2) != 0:
        for path in remove_files2:
            os.remove(path)

    # カレントディレクトリを作業ディレクトリへ変更
    os.chdir('/test_app/')

    # exeファイル作成コマンド実行
    def run(cmd):
        proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        while True:
            line = proc.stdout.readline()
            if line:
                yield line
            if not line and proc.poll() is not None:
                break

    cmd = f"pyinstaller {new_path} --onefile --noconsole"
    lines = []
    for line in run(cmd):
        sys.stdout.buffer.write(line)
        lines.append(line.decode('utf-8'))
    lines_con = ''.join(lines)
    list_text()[0].insert(tk.END,'exeファイル作成完了\n')

    return lines_con

# Button設定
btn = ttk.Button(frame, text="実行",command=lambda:[list_text()[0].insert(tk.END,exe_make(entry.get())),auto_scroll()],width=8,style= 'MyWidget.TButton')
btn.grid(row=0,column=2,sticky=tk.W,padx=10)

[Python] exe化ツール v0.0.1 全標準出力の取得

pyinstallerを使ってソースコードから実行ファイルを作成するツールです。

標準出力を全て取得してTextウィジェットに表示するところで手間取りました。

標準出力を1行ずつ取得してリストにしたものをそのまま表示しているため、波カッコが目障りです。できれば消去したいです。

import subprocess,datetime,os,sys,shutil,glob
import tkinter as tk
import tkinter.font as font
from tkinter import ttk

# 16進数カラーコード
# #EDFFBE #C2EEFF #7B3CFF

class FrameA(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.configure(background = '#b0e0e6')
        self.grid(row=1,column=2, sticky=tk.NSEW, padx=5, pady=5)

class FrameB(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.configure(background = '#C2EEFF',borderwidth=0)
        self.grid(row=1,column=1, sticky=tk.NSEW, padx=5, pady=5)
        # Text設定
        self.text = tk.Text(self,height=23,width=45,highlightbackground="#f0f8ff",background = '#C2EEFF',foreground = '#8b0000')
        # ハイライトを消す場合
        # self.text = tk.Text(self,height=20,width=45,highlightthickness=0,background = '#C2EEFF',foreground = '#8b0000')

        # Y方向スクロールバーの設定
        self.scrollable_frame = ttk.Frame(self.text)
        self.scrollbar_y = ttk.Scrollbar(self, orient="vertical", command=self.text.yview,style= 'Vertical.TScrollbar')
        self.scrollbar_y.pack(side=tk.RIGHT, fill="y")

        self.text.configure(yscrollcommand=self.scrollbar_y.set)
        self.text.pack(side=tk.LEFT, fill="both", expand=True)

def list_text():
    # frameB全ウィジェットのinfoを取得
    children = frameB.winfo_children()
    text_list = [entry for entry in children if type(entry)==tk.Text]

    return text_list

def exe_make(path):
    # ソースコードの作業ディレクトリへのコピー
    working_dir = '/test_app/'
    new_path = working_dir + (path.split('test_GUI/'))[1]
    print(f'new_path {new_path}')
    shutil.copy2(path, new_path)

    # buildディレクトリ内関連ディレクトリの削除
    filename = (path.split('test_GUI/'))[1][:-3]
    remove_dir = '/test_app/build/' + filename + '/'
    try:
        shutil.rmtree(remove_dir)
    except:
        pass

    # 作業ディレクトリ内specファイルの削除
    all_files2 = [path for path in glob.glob('/test_app/*.spec')]
    remove_files2 = [path for path in all_files2 if filename in path]
    print(remove_files2)
    if len(remove_files2) != 0:
        for path in remove_files2:
            os.remove(path)

    # カレントディレクトリの変更
    os.chdir('/test_app/')

    # exeファイル作成コマンド実行
    def run(cmd):
        proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        while True:
            line = proc.stdout.readline()
            if line:
                yield line
            if not line and proc.poll() is not None:
                break

    cmd = f"pyinstaller {new_path} --onefile --noconsole"
    lines = []
    for line in run(cmd):
        sys.stdout.buffer.write(line)
        lines.append(line)

    list_text()[0].insert(tk.END,'exeファイル作成完了\n')

    return lines


def list_text():
    # frameB全ウィジェットのinfoを取得
    children = frameB.winfo_children()
    text_list = [entry for entry in children if type(entry)==tk.Text]

    return text_list

def auto_scroll():
    list_text()[0].see("end")

# ウィンドウ作成
root = tk.Tk()
root.title("EXE MAKER v0.0.1")
root.geometry("555x375")
root.configure(bg='#b0e0e6')
style = ttk.Style()
style.theme_use('classic')
style.configure("MyWidget.TButton", gripcount=0,
                background="#7B3CFF", foreground="#EEFFFF",darkcolor='#7B3CFF', lightcolor="LightGreen",
                troughcolor="gray", bordercolor="gray", arrowcolor="white")
style.configure("MyWidget2.TButton", gripcount=0,
                background="#ffe4b5", foreground="#556b2f",darkcolor='#ffe4b5', lightcolor="LightGreen",
                troughcolor="gray", bordercolor="gray", arrowcolor="white")
style.configure("Vertical.TScrollbar", gripcount=0,
                background="#98fb98", foreground="#98fb98", darkcolor="#f5f5dc", lightcolor="#98fb98",
                troughcolor="#EEFFFF", bordercolor="#EEFFFF", arrowcolor="#EEFFFF")

# フォント設定
my_font = font.Font(root,family="System",size=18,weight="normal")
my_font2 = font.Font(root,family="System",size=16,weight="normal")
my_font3 = font.Font(root,family="System",size=14,weight="normal")
my_font4 = font.Font(root,family="System",size=12,weight="normal")

# Frame設定
frame = tk.Frame(root,background = '#b0e0e6')
frame.grid(row=0,column=0, sticky=tk.NSEW, padx=5, pady=10)
frameA = FrameA(master=frame)
frameB = FrameB(master=frame)

# Entry設定
entry = ttk.Entry(frame,width=45,background = '#C2EEFF',foreground = '#8b0000',font=my_font3)
entry.grid(row=0,column=1, padx=5,sticky=tk.W)

# Button設定
btn = ttk.Button(frame, text="実行",command=lambda:[list_text()[0].insert(tk.END,exe_make(entry.get())),auto_scroll()],width=8,style= 'MyWidget.TButton')
btn.grid(row=0,column=2,sticky=tk.W,padx=10)

btnA = ttk.Button(frameA, text="クリア",command=lambda:entry.delete(0,tk.END),width=8,style= 'MyWidget2.TButton')
btnA.pack(padx=5,pady=3,side=tk.TOP)

root.mainloop()