изменил данный список внутри функции - PullRequest
2 голосов
/ 31 августа 2011

Я хотел бы назначить новые значения в список, который я передаю своим функциям. В случае get_p_values это работает нормально, но при `read_occupation 'нет (я получаю в качестве вывода: [[0], [0], [0], [0]] вместо [[1,2,3 ], [1,2,3], [1,2,3], [1,2,3]]).

Замечание, причина, по которой я перехожу к функции read_occupation в списке matrix[ index ], заключается в том, что в других случаях мне нужно будет использовать acquire() и release() из Lock.

#!/usr/bin/python
# Filename: untitled.py
# encoding: utf-8

from __future__ import division
from multiprocessing import Process

def read_occupation( matrix ):
    matrix = [ [1,2,3] ]

def get_p_values( p):
    for index,value in enumerate( xrange(0,3,1)):
        p[index] = value

def main():
    p         = [ [0] ] * 3 
    matrix    = [ [0] ] * 4

    get_p_values( p )
    print p

    for index in xrange(0,3,2):
            p1 = Process( target=read_occupation, args=( matrix[ index     ] ) )
            p2 = Process( target=read_occupation, args=( matrix[ index + 1 ] ) )

            p1.start()
            p2.start()

            p1.join()
            p2.join()

    print matrix


if __name__ == '__main__':
    main()

Ответы [ 4 ]

3 голосов
/ 31 августа 2011

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

Вы можете попробовать следующий пример.

from multiprocessing import Process

def modify(idx, li):
    li[idx] = 'hello'

a = [0] * 3 

p = Process(target=modify, args=(1, a))
p.start()
p.join()
print a

modify(1, a)
print a

Результат будет:

[0, 0, 0]
[0, 'hello', 0]
2 голосов
/ 31 августа 2011

Существует множество причин, по которым он не работает.

Во-первых, в функции read_occupation вы меняете привязку локальной переменной.Оригинальный объект остается нетронутым.Напротив, в get_p_values вы модифицируете объект (оператор [] вызывает функцию __setitem__ объекта, который изменяет внутреннее представление).Лучшей идеей в этом случае будет использование правильного объекта.

Если вы хотите изменить все содержимое списка в read_occupation, вы можете использовать оператор объединения списков, чтобы назначить весь список:

def read_occupation(matrix):
    matrix[:] = [ [1, 2, 3] ]

Кстати, если вы вызовете функцию read_occupation, вызывающая сторона, вероятно, будет ожидать, что она не изменит свой параметр.Вам, вероятно, следует переименовать его update_occupation или что-то в этом роде.

Во-вторых, когда вы создаете свои переменные посредством умножения, вы получаете list, где каждый индекс содержит ссылку на один и тот же элемент.Код p = [ [0] ] * 3 эквивалентен:

>>> l = [0]          # Naming the list for more clarity
>>> p = [ l, l, l ]  # Each index points to the same list `l`

В-третьих, класс Process ожидает tuple (или фактически объект, следующий за повторяемым протоколом) для своего параметра args.Вы не передаете кортеж, а один элемент, который оказывается list из одного int (именно поэтому вы получаете исключение TypeError).Вам нужно использовать следующий синтаксис для передачи tuple:

# Please note the comma after the closing bracket, it is important
p1 = Process( target=read_occupation, args=( matrix[ index     ], ) )

# In python, the syntax for a tuple is weird for tuple of size < 2
#  . tuple of 0 item:  ()
#  . tuple of 1 item:  (1,)
#  . tuple of 2 items: (1, 2)

В-четвертых, вы используете multiprocessing.Process, который порождает новый процесс, в котором выполняется ваш код.В вашем коде нет связи (я не знаю, возможно ли вернуть информацию из этого процесса в исходный).Таким образом, переменная в исходном коде не изменяется.

1 голос
/ 31 августа 2011

mp.Manager предоставляет возможность совместно использовать список Python для нескольких процессов:

from __future__ import division
import multiprocessing as mp   

def read_occupation( matrix,i ):
    matrix[i]=[1,2,3]

def main():
    manager=mp.Manager()
    matrix=manager.list([ [0] ] * 4)

    for index in xrange(0,3,2):
        p1 = mp.Process( target=read_occupation, args=(matrix,index) )
        p2 = mp.Process( target=read_occupation, args=(matrix,index+1) )

        p1.start()
        p2.start()

        p1.join()
        p2.join()

    print matrix

if __name__ == '__main__':
    main()

приводит к

[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
0 голосов
/ 31 августа 2011

Этот блок вводит в заблуждение:

p         = [ [0] ] * 3 
matrix    = [ [0] ] * 4

попробуйте выполнить p [0] .append (0), и вы получите:

[[0, 0], [0, 0], [0, 0]]

, потому что [[0]] *3 создает список из трех объектов, каждый из которых указывает на один и тот же список.

Хуже: я не уверен, что ваша программа будет работать, если вы исправите это +, что сказал sylvain, потому что p1 и p2 будут пытаться получить доступ ктот же список.Вы должны внимательно прочитать документ multiprocessing перед его использованием.Это очень сложная библиотека, полная неприятных ловушек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...