Чтение переменных среды ОС в порожденном процессе - PullRequest
0 голосов
/ 27 августа 2018

Это похоже на предыдущий вопрос , но для multiprocessing вместо subprocess. Кажется, что динамическое изменение PYTHONHASHSEED не имеет никакого эффекта при использовании multiprocessing, в отличие от subprocess:

#check_environ.py
import os, multiprocessing, subprocess, sys

s = 'hello'
print('parent', os.getenv('PYTHONHASHSEED'), hash(s))

if len(sys.argv) > 1:
    os.environ['PYTHONHASHSEED'] = sys.argv[1]
subprocess.call(['python', '-c', "import os;print('subprocess', os.getenv('PYTHONHASHSEED'), hash('{}'))".format(s)])
multiprocessing.Process(target=lambda:print('multiprocessing', os.getenv('PYTHONHASHSEED'), hash(s))).start()

Примеры прогонов:

# explicit PYTHONHASHSEED for subprocess/multiprocessing 
$ python check_environ.py 12

parent None 4472558296122225349
subprocess 12 -8207222429063474615
multiprocessing 12 4472558296122225349

# random PYTHONHASHSEED for subprocess/multiprocessing 
$ python check_environ.py

parent None 7990499464460966677
subprocess None 1081030409066486350
multiprocessing None 7990499464460966677

Так что, несмотря ни на что, хэш multiprocessing использует то же самое семя, что и родительский. Есть ли способ заставить подпроцессы, порожденные multiprocessing, использовать другое начальное число хешей?

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Вы можете, используя другой метод запуска, чем 'fork' для создания процесса. Ваша ОС использует fork (вы не получите PicklingError за использование лямбды в качестве цели).

Вы можете изменить метод запуска на «spawn» (по умолчанию и только в Windows) с помощью multiprocessing.set_start_method('spaw') или на «forkserver», если он доступен. Получить все доступные методы с multiprocessing.get_all_start_methods().

#check_environ.py
import sys, os, subprocess
import multiprocessing as mp


def show(s):
    print('multiprocessing', os.getenv('PYTHONHASHSEED'), hash(s))


if __name__ == '__main__':

    mp.set_start_method('spawn')

    s = 'hello'
    print('parent', os.getenv('PYTHONHASHSEED'), hash(s))

    if len(sys.argv) > 1:
        os.environ['PYTHONHASHSEED'] = sys.argv[1]

    cmd = "import os; " \
          "print('subprocess', os.getenv('PYTHONHASHSEED'), hash('{}'))"
    subprocess.call(['python', '-c', cmd.format(s)])
    p = mp.Process(target=show, args=(s,))
    p.start()
    p.join()

Выход на клемме:

$ python check_environ.py 12

parent None 4279361553958749032
subprocess 12 -8207222429063474615
multiprocessing 12 -8207222429063474615

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

ctx = mp.get_context('spawn')
p = ctx.Process(target=foo, args=(var,))

Но будьте готовы заплатить огромный штраф времени за использование другого метода запуска, кроме форка. Я показал, как только запускаю процесс python на моей машине с Ubuntu 18.04 с:

  • вилка 1,59 мс
  • forkserver 289,83 мс
  • спавн 348,20 мс

Но это не обязательно относится к вашему случаю использования.

0 голосов
/ 27 августа 2018

Каждый из python процессов запускается в новой среде ОС, тогда как в случае multiprocessing существует только один , общий и наследуемый от родительского процесса .

...