словарь Python ориентирован на многопотоковое исполнение?

Хорошо. Я решил эту проблему. Я делюсь своими кодами, чтобы помочь другим. Просто используйте лямбда-функцию:

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()
24
задан artbristol 29 December 2012 в 10:55
поделиться

3 ответа

Два понятия совершенно разные. Потокобезопасность означает, что два потока не могут изменять один и тот же объект одновременно, в результате чего система находится в несогласованном состоянии.

Тем не менее, вы не можете изменять словарь, перебирая его. См. Документацию . .

Словарь p не должен изменяться во время итерации. Безопасно (начиная с Python 2.1) изменять значения ключей во время итерации по словарю, но только до тех пор, пока набор ключей не изменится.

28
ответ дан deinst 28 November 2019 в 22:09
поделиться

Нет. Последняя версия 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

Обратите внимание, что вам не нужно использовать темы, чтобы увидеть это

14
ответ дан John La Rooy 28 November 2019 в 22:09
поделиться

В других ответах уже правильно рассмотрен ваш настоящий вопрос:

Означает ли это, что я могу или не могу изменить элементы в словаре, пока итерация по нему?

, объясняя, что безопасность потоков не имеет ничего общего с проблемой, и в любом случае, нет, вы не можете изменить 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, поэтому все различные реализации языка должны его сохранять.

63
ответ дан 28 November 2019 в 22:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: