Как сделать секундомер, который начинает отсчет при запуске подпроцесса и останавливается по его завершению

Я сделал лаунчер для игр на Линукс Debian, потому что не хотел каждый раз заходить в директорию и вводить команду. Хотел бы добавить в него секундомер, который бы запускался при открытии игры, переставал считать при ее закрытии и сбрасывался при новом запуске игры. Попытка найти решение в сети или с помощью ChatGPT не увенчалась успехом.

Текущий код:

#!/usr/bin/env python3

import tkinter as tk
import subprocess


bash_script1 = "/home/dimon/Документы/лаунчер/launcherterarria"
bash_script2 = "/home/dimon/Документы/лаунчер/launcherundatrale"


def terraria():
    subprocess.run(bash_script1)

def undertale():
    subprocess.run(bash_script2)

root = tk.Tk()
root.resizable(False, False)

greeting = tk.Label(text="Во что будем играть?")

timer = tk.Label(text ="Текущая сеция длилась: 00:00")


terraria_button = tk.Button(text = "Терария!", command = terraria)
undertale_button = tk.Button(text = "Андертейл", command = undertale)


greeting.pack()
undertale_button.pack()
terraria_button.pack()
timer.pack()
root.mainloop()

Мне нужно, чтобы при запуске игры включался секундомер, при выключении он тоже переставал работать, при повторном запуске игры сбрасывался и снова включался.


Ответы (2 шт):

Автор решения: Fox Fox

Пример простейшего счётчика времени выполнения:

import time

# Запоминаем стартовое время:
start_time = time.time()

# Здесь выполняется некий код, например:
time.sleep(3)  # Замените эту строку вашим кодом

# Вычисляем количество секунд, потраченных на выполнение скрипта:
elapsed_time = time.time() - start_time

print(f"Скрипт выполнялся {elapsed_time:.2f} секунд")
→ Ссылка
Автор решения: Serge3leo

Вариант секундомера с кнопками:

  1. Во время работы процессов метка timer изменяется в mainloop каждую секунду;
  2. Процессы запускаются в отдельных потоках, что бы не блокировать mainloop;
  3. На время работы процессов, кнопки запрещаются.
import tkinter as tk
import subprocess
from threading import Thread, Lock

class terraria_undertale:
    terraria_args = ["sleep", # "/home/dimon/Документы/лаунчер/launcherterarria"
                     "5"
                    ]
    undertale_args = ["sleep", # "/home/dimon/Документы/лаунчер/launcherundatrale"
                      "3"
                     ]
    def __init__(self):
        self.mutex = Lock()
        self.thread = None
        self.state = "stop"
        self.counter = 0

    def work_args(self, args):
        subprocess.run(args)
        with self.mutex:
            self.state = "finish"

    def callback_by_second(self):
        with self.mutex:
            if "finish" == self.state:
                self.thread.join()  # Если видим "finish", значит work_args() 
                                    # уже освободил mutex, можно его ждать
                self.terraria_button.config(state=tk.NORMAL)
                self.undertale_button.config(state=tk.NORMAL)
                self.state = "stop"
                return
            self.counter += 1
            self.timer.config(text=f"Длительность: {self.counter}")
            self.root.after(1000, self.callback_by_second)

    def start_timer_et_all(self, args):
        with self.mutex:
            self.state = "start"
            self.thread = Thread(target=self.work_args, args=[args])
            self.thread.start()
            self.terraria_button.config(state=tk.DISABLED)
            self.undertale_button.config(state=tk.DISABLED)
        self.callback_by_second()
    
    def terraria(self):
        self.start_timer_et_all(self.terraria_args)
    
    def undertale(self):
        self.start_timer_et_all(self.undertale_args)

    def mainloop(self):
        self.root = tk.Tk()
        self.root.resizable(False, False)
        self.greeting = tk.Label(text="Во что будем играть?")
        self.timer = tk.Label(text ="Длительность: 0")
        self.terraria_button = tk.Button(text = "Терария!", command = self.terraria)
        self.undertale_button = tk.Button(text = "Андертейл", command = self.undertale)
        self.greeting.pack()
        self.undertale_button.pack()
        self.terraria_button.pack()
        self.timer.pack()
        self.root.mainloop()

tu = terraria_undertale()
tu.mainloop()
print("Stop")
→ Ссылка