Глобальная переменная Python в многопроцессорной обработке

В следующем коде я объявляю GlobalCount, который должен стать глобальной переменной. Затем я запускаю методprocess() с многопроцессорной обработкой, которая увеличивает GlobalCount каждую секунду. Если я установлю там точку останова, значение увеличится нормально. Затем параллельно я запрашиваю GETSTATUS, который должен вернуть значение GlobalCount. Однако это всегда 0! Что я делаю неправильно? Спасибо.

Обновленный код:

import multiprocessing
import socket
import time

from multiprocessing import Value

#globals
GlobalCount = Value('i', 0)  # 'i' stands for integer

def main():

    server_ip = "127.0.0.1"
    server_port = 2222

    # Create a UDP socket
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_address = (server_ip, server_port)
    server_socket.bind(server_address)

    response = ""

    print("UDP server is listening on {}:{}".format(*server_address))

    while True:
        
        # Receive data from the client
        data, client_address = server_socket.recvfrom(256)

        if data:

            data_str = data.decode('utf-8') 
            arrayParams = data_str.split(';')

            if arrayParams[0] == "PROCESS":

                server_socket.sendto(response.encode(), client_address)

                # Start the process in parallel
                training_process = multiprocessing.Process(target=process)
                training_process.start()

            elif arrayParams[0] == "GETSTATUS":
                current_value = GlobalCount.value
                response = str(current_value) #here GlobalCount is always 0
                server_socket.sendto(response.encode(), client_address)

            else:
                print("")



def process():

    for i in range(100):
        
        with GlobalCount.get_lock():  # Ensure thread-safety when updating the value
            GlobalCount.value += 1
        time.sleep(1)


#Execute at start
if __name__ == '__main__':
    main()

Многопоточность, вероятно, лучше подойдет для этого.

DarkKnight 18.09.2023 10:29
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В Python многопроцессорная обработка создает не поток, а процесс с собственным пространством памяти.

Вы можете попробовать что-то подобное, используя multiprocessing.Value :

from multiprocessing import Value

GlobalCount = Value('i', 0)  # 'i' stands for integer

# In your process function:
def process():
    for i in range(100):
        with GlobalCount.get_lock():  # Ensure thread-safety when updating the value
            GlobalCount.value += 1
        time.sleep(1)

# When reading the value:
current_value = GlobalCount.value

Редактировать после комментария:

import multiprocessing
import socket
import time

def main():
    # Use multiprocessing.Value to create a shared variable
    GlobalCount = multiprocessing.Value('i', 0)

    server_ip = "127.0.0.1"
    server_port = 2222
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_address = (server_ip, server_port)
    server_socket.bind(server_address)
    print("UDP server is listening on {}:{}".format(*server_address))

    while True:
        data, client_address = server_socket.recvfrom(256)
        if data:
            data_str = data.decode('utf-8') 
            arrayParams = data_str.split(';')
            if arrayParams[0] == "PROCESS":
                response = "Started processing"
                server_socket.sendto(response.encode(), client_address)
                training_process = multiprocessing.Process(target=process, args=(GlobalCount,))
                training_process.start()
            elif arrayParams[0] == "GETSTATUS":
                response = str(GlobalCount.value)
                server_socket.sendto(response.encode(), client_address)

def process(GlobalCount):
    for i in range(100):
        # Modify the shared variable using GlobalCount.value
        GlobalCount.value += 1
        time.sleep(1)

if __name__ == '__main__':
    main()

Должен ли я продолжать устанавливать в метод «глобальный GlobalCount»?

Jaume 18.09.2023 10:01

Нет, вместо глобального GlobalCount -> multiprocessing.Value

drino 18.09.2023 10:03

Та же проблема. GlobalCount всегда равен 0 при запросе значения. Я обновил код на основе вашего предложения.

Jaume 18.09.2023 10:21

Синхронизированный объект не является итерируемым... multiprocessing.Process(target=process, args=(GlobalCount))

Jaume 18.09.2023 11:05

тот же подход, что и в чатгпт... который я тоже пробовал сначала. Не работает

Jaume 18.09.2023 11:10

GPT предлагает подход с многопроцессорной обработкой. Для меня очередь. Я думаю, это не подходит. Не могли бы вы предоставить больше результатов вашего адаптированного кода?

drino 18.09.2023 11:13

Спасибо, многопоточность вместо многопроцессорности решила проблему.

Jaume 18.09.2023 11:20

Приятно знать, спасибо.

drino 18.09.2023 11:22
Ответ принят как подходящий

Совместно использовать синхронизированные объекты можно только посредством наследования. Вот пример:

from multiprocessing import Value, Pool

N = 100

def ipp(v):
    global gCount
    gCount = v

def process(_):
    with gCount.get_lock():
        gCount.value += 1

def main():
    gCount = Value('Q', 0) # unsigned long long
    with Pool(initializer=ipp, initargs=(gCount,)) as pool:
        pool.map(process, range(100))
    print(gCount.value == N)

if __name__ == '__main__':
    main()

Выход:

True

Я перешел на многопоточность, как вы предложили... И при том же подходе глобального var все работает как положено! Спасибо

Jaume 18.09.2023 11:19

Другие вопросы по теме

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