Tip*_*kek 4 python user-interface multiprocessing
我正在制作一个 GUI 应用程序来跟踪每个前台窗口所花费的时间。我尝试对每个被监视的进程进行循环来执行此操作:
class processes(object):
def __init__(self, name, pid):
self.name = name
self.pid = pid
self.time_spent = 0
self.time_active = 0
p1 = multiprocessing.Process(target=self.loop, args=())
p1.start()
def loop(self):
t = 0
start_time = time.time()
while True:
#While the process is running, check if foreground window (window currently being used) is the same as the process
h_wnd = user32.GetForegroundWindow()
pid = wintypes.DWORD()
user32.GetWindowThreadProcessId(h_wnd, ctypes.byref(pid))
p = psutil.Process(pid.value)
name = str(p.name())
name2 = str(self.name)
if name2 == name:
t = time.time() - start_time
#Log the total time the user spent using the window
self.time_active += t
self.time_spent = time.perf_counter()
time.sleep(2)
def get_time(self):
print("{:.2f}".format(self.time_active) + " name: " + self.name)
Run Code Online (Sandbox Code Playgroud)
我在 GUI 中选择所需的进程,并通过其名称在列表中找到它。一旦找到,我就调用函数 get_time() ,该函数应该打印所选进程在前台运行的时间。
def display_time(Lb2):
for s in Lb2.curselection():
for e in process_list:
if Lb2.get(s) == e.name:
e.get_time()
Run Code Online (Sandbox Code Playgroud)
问题是每次打印时time_active都是0。
我已经调试了该程序,并且可以看出它在某种程度上工作(并不完美,当程序不在前台时它仍然记录时间)并更新循环内的变量。但是,当打印出来时,该值仍为 0。我认为我在理解多处理方面遇到了困难,如果有人可以消除困惑的话
@TheLizzard 提供了最简单的解决方案,即仅使用线程而不是多处理:
import threading
...
#p1 = multiprocessing.Process(target=self.loop, args=())
p1 = threading.Thread(target=self.loop, args=())
Run Code Online (Sandbox Code Playgroud)
但这并不能解释为什么创建一个流程却不起作用。发生的情况是,您的process.__init__代码首先创建了几个属性,例如self.time_active、self.time_spent等。该代码在主进程中执行。但是当你执行下面两条语句时......
p1 = multiprocessing.Process(target=self.loop, args=())
p1.start()
Run Code Online (Sandbox Code Playgroud)
...process创建的对象现在必须序列化/反序列化到新的地址空间Process,您刚刚创建的新实例必须在其中运行。因此,在loop方法中,当您执行诸如 之类的语句时,您正在更新子进程地址空间中“生存”self.time_active += t的实例。self.time_active但是打印出 的值的代码self.time_active是在主进程的地址空间中执行的,因此仅打印出该属性的原始值。
如果您必须使用多处理,因为您的loop方法是 CPU 密集型的,并且需要与其他进程并行,那么解决方案是在共享内存中创建self.time_active和,self.time_spent以便主进程和子进程都可以访问相同的内存,共享属性:
class processes(object):
def __init__(self, name, pid):
self.name = name
self.pid = pid
# Create shared floating point values:
self.time_spent = multiprocessing.Value('f', 0)
self.time_active = multiprocessing.Value('f', 0)
...
def loop(self):
...
self.time_active.value += t
self.time_spent.value = time.perf_counter()
...
def get_time(self):
print("{:.2f}".format(self.time_active.value) + " name: " + self.name)
Run Code Online (Sandbox Code Playgroud)