[Pythonしたいことの前にやるべきことを実行するプログラム

## 背景
やるべきことはたくさんあるのに、気づけば遊んでしまっていることってあると思います。そんな事態を予防するためにスクリプトを作成しました。

## 概要
したいことの前にやるべきことを実行するpythonスクリプト
exeファイルを実行し、その処理が終了後、別のexeファイルを実行する

:::note warn
Windowsでのみ動作(exeファイルを使用するため)
:::

## 機能
- 実行機能
    1. やるべきことのexeファイルを実行
    1. やるべきことのexeファイルが終了するまで待つ
    1. やるべきことのexeファイルが終了後、やりたいことのexeファイルを実行する
- パス変更機能
    下記二つのファイルパスを変更
    - to_do_path: やるべきことのexeファイルパス
    - to_enjoy_path: やりたいことのexeファイルパス

## 使い方
- 実行する場合
    ```bash
    python do_before_enjoy.py
    ```
- パスを変更する場合
    ```bash
    python do_before_enjoy.py to_do_path "[やるべきことのexeパス]" to_enjoy_path "[やりたいことのexeパス]"
    ```
## コード
```python:do_before_enjoy.py
import subprocess
import sys
import os

from common import get_config_path, load_config, save_config, change_config


class DoBeforeEnjoy():
    def __init__(self, to_do_path, to_enjoy_path) -> None:
        self.to_do_path = to_do_path
        self.to_enjoy_path = to_enjoy_path

    @staticmethod
    def run_task(task_path):
        if os.path.exists(task_path):
            try:
                result = subprocess.run(task_path, check=True)
                return result.returncode
            except subprocess.CalledProcessError as e:
                print(f"タスク実行エラー {task_path}: {e}")
                return e.returncode
        else:
            print(f"{task_path} パスが存在しません")
            return -1

    def do_before_enjoy(self):
        """
        やるべきことを実行した後にやりたいことを実行する
        """
        print("Executing the task you need to do...")
        if self.run_task(self.to_do_path) == 0:
            print("やるべきこと終了! やりたいこと開始中...")
            self.run_task(self.to_enjoy_path)

    def __call__(self):
        self.do_before_enjoy()


if __name__ == "__main__":
    config_path = get_config_path()

    if len(sys.argv) == 1:
        config = load_config(config_path)
        do_before_enjoy = DoBeforeEnjoy(config["to_do_path"], config["to_enjoy_path"])
        do_before_enjoy()
    elif len(sys.argv) == 3:
        key = sys.argv[1]
        value = sys.argv[2]

        config = load_config(config_path)
        change_config(config, key, value)
        save_config(config_path, config)

    elif len(sys.argv) == 5:
        key1 = sys.argv[1]
        value1 = sys.argv[2]
        key2 = sys.argv[3]
        value2 = sys.argv[4]
        config = load_config(config_path)
        change_config(config, key1, value1)
        change_config(config, key2, value2)
        save_config(config_path, config)
```


```python:common.py
import sys
import os
import json


def get_config_path():
    if getattr(sys, 'frozen', False):
        # PyInstallerでビルドされた場合
        return os.path.join(sys._MEIPASS, 'config.json')
    else:
        # 開発環境でのパス
        return 'config.json'


def load_config(file_path):
    with open(file_path, 'r') as f:
        return json.load(f)


def save_config(file_path, config):
    with open(file_path, 'w') as f:
        json.dump(config, f, indent=4)


def change_config(config, key, value):
    if key in config:
        config[key] = value
        print(f"実行ファイルパスを変更: {key} = {value}")
    else:
        print(f"{key} は設定項目に存在しません")
```

```json:config.json
{
    "to_do_path": "C://Program Files/arduino-ide_nightly-20240630_Windows_64bit/Arduino IDE.exe",
    "to_enjoy_path": "C:/Program Files (x86)/Steam/Steam.exe"
}
```

## 応用
pyinstallerを用いることでこの実行スクリプト自体もexeすることができます。
exeファイルのアイコンも変更できるため、通常のexeファイルと全く同じ見た目にすることも可能です。

### pyinstallerでexe化する場合
- コマンド
    ```
    pyinstaller do_before_enjoy.py　--add-data "config.json;." --onefile
    ```
    - add-data: exeにデータを同梱するオプション
    - onefile: 関連ファイルをまとめるオプション
- 作成したexeファイル
    ![default_ico.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692990/75c33a16-952e-2732-fa51-dc6a485fead5.png)


### pyinstallerでexe化する場合(アイコン変更)
- コマンド
    ```
    pyinstaller do_before_enjoy.py --add-data "config.json;." --onefile --icon .\steam.ico --name steam.exe 
    ```
    - icon: アイコン変更オプション
    - name: exeファイル名変更オプション
- 作成したexeファイル
    steamのアイコンに変更した場合
    ![steam_ico.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692990/1b7678ee-7916-1eff-f48e-f074e14e55aa.png)

### 参考サイト
https://wazalabo.com/python-script.html

https://snuow.com/blog/pyinstaller%E3%81%A7%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3icon-ico%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

https://technote.flyingjunk.net/715/