Хорошо. Я решил эту проблему. Я делюсь своими кодами, чтобы помочь другим. Просто используйте лямбда-функцию:
from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk
class Program:
def __init__(self):
self.window = tk.Tk()
self.window.title("Welcome")
self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
self.window.mainloop()
def quit_window(self):
self.icon.stop()
self.window.destroy()
def show_window(self):
self.icon.stop()
self.window.after(0, self.window.deiconify)
def withdraw_window(self):
self.window.withdraw()
image = Image.open("microphone.ico")
menu = (item('Quit', lambda: self.quit_window()), item('Show', lambda: self.show_window()))
self.icon = pystray.Icon("name", image, "title", menu)
self.icon.run()
run=Program()
Два понятия совершенно разные. Потокобезопасность означает, что два потока не могут изменять один и тот же объект одновременно, в результате чего система находится в несогласованном состоянии.
Тем не менее, вы не можете изменять словарь, перебирая его. См. Документацию . .
Словарь p не должен изменяться во время итерации. Безопасно (начиная с Python 2.1) изменять значения ключей во время итерации по словарю, но только до тех пор, пока набор ключей не изменится.
Нет. Последняя версия python вызовет исключение, если вы попытаетесь перебрать словарь, размер которого изменился между итерациями.
>>> d={'one':1, 'two':2}
>>> for x in d:
... d['three']=3
... print x
...
two
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
Обратите внимание, что вам не нужно использовать темы, чтобы увидеть это
В других ответах уже правильно рассмотрен ваш настоящий вопрос:
Означает ли это, что я могу или не могу изменить элементы в словаре, пока итерация по нему?
, объясняя, что безопасность потоков не имеет ничего общего с проблемой, и в любом случае, нет, вы не можете изменить dict во время итерации по нему.
Однако заголовок вашего вопроса - о безопасности потоков, и вы начинаете с:
Некоторые утверждали, что словарь Python потокобезопасность
Я не знаю, кто такие «некоторые», но, если они заявили это (а не вы неправильно поняли, что они сделали ;-) без особых оговорок, они ошибаются.
Некоторые операции, те, которые не изменяют набор ключей в dict, оказываются поточно-ориентированными в текущих реализациях CPython - но вы не должны не рассчитывать на это, если только вы строго контролируете версию Python, под которой будет работать ваш код, потому что такая потокобезопасность не гарантируется спецификацией языка Python, и поэтому другие реализации, включая будущие версии CPython, могут не предлагать ее.
Если каждый поток только «читает» словарь (индексирует его, зацикливает на нем и т. Д.), И ни один поток не выполняет для него какое-либо назначение или удаление, то такая ситуация безопасна в текущих реализациях CPython; на самом деле, если какой-то поток присваивает новое значение ключу, который уже существовал, он также является потокобезопасным (другие потоки могут видеть предыдущее значение для этого ключа или следующее, в зависимости от того, как потоки синхронизируются по времени, но в текущих реализациях CPython не будет сбоев, тупиков и появления сумасшедших значений из ниоткуда).
Однако такая операция, как d [k] + = 1
(при условии, что k было ранее, а его значение - число), не , собственно говоря, потокобезопасная (больше чем другой случай + =
!), потому что его можно увидеть как d [k] = d [k] + 1
- это может случиться, что два потоки в состоянии гонки оба читают старое значение d [k]
, затем увеличивают его на единицу и сохраняют то же новое значение в слоте ... так что общий эффект заключается в увеличении его только на один, а не два, как обычно.
Вернемся к вашему другому вопросу ... "только чтение" dict, и присвоение новых значений ключам, которые уже существовали в dict, также являются вещами, которые вы можете сделать в теле цикла который выполняет итерацию по dict - вы не можете изменить набор ключей в dict (вы не можете ни добавить ключ, ни удалить какой-либо ключ), но разрешена конкретная операция по установке нового значения для существующего ключа.Разрешенные операции в этом случае включают + =
, что было бы проблематично в ситуации многопоточности. Например:
>>> d = dict.fromkeys(range(5), 0)
>>> for k in d: d[k] += 1
...
>>> d
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1}
и это поведение гарантируется стандартизованной семантикой Python, поэтому все различные реализации языка должны его сохранять.