2016-07-13 3 views
2

Я хочу создать два (или более) потока и в каждом из них выполнить другую внешнюю программу, допустим, aaa и bbb. Эти внешние программы нуждаются в библиотеках, расположенных в разных каталогах, скажем, в /aaalib и /bbblib, поэтому перед выполнением их необходимо установить переменную окружения LD_LIBRARY_PATH. Я хочу избежать использования оболочки, поэтому такие решения, как выполнение LD_LIBRARY_PATH=/aaalib aaa, не очень хорошие.Как установить переменную среды, специфичную для потока, в Python?

Вопрос: как установить os.environ['LD_LIBRARY_PATH'] таким образом, чтобы он имел разные значения в разных потоках?

PS. Я попробовал решение os.environ['...'] = threading.local() описанный here, но он не в следующим образом:

In [1]: import os, threading 
In [2]: os.environ['LD_LIBRARY_PATH'] = threading.local() 
----------------------- 
TypeError   Traceback (most recent call last) 
<ipython-input-2-a2c8ef0b901b> in <module>() 
----> 1 os.environ['LD_LIBRARY_PATH'] = threading.local() 
/usr/lib/python2.7/os.pyc in __setitem__(self, key, item) 
471     self.data = environ 
472    def __setitem__(self, key, item): 
--> 473     putenv(key, item) 
474     self.data[key] = item 
475    def update(self, dict=None, **kwargs): 
TypeError: must be string, not thread._local 

ответ

1

вы можете попробовать использовать subprocess модуль и сделать что-то вроде этого:

import subprocess 
import os 

env = os.environ.copy() 
env['LD_LIBRARY_PATH'] = '/aaalib' 
aaa_process = subprocess.Popen(['aaa'], env=env) 

env = os.environ.copy() 
env['LD_LIBRARY_PATH'] = '/bbblib' 
bbb_process = subprocess.Popen(['bbb'], env=env) 
0

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

каждый процесс должен иметь этот вид функции

def target(some_value): 
    os.environ['FOO'] = some_value 
    # some_code_here 

some_value, чтобы проходить через икру процесса

p = multiprocessing.Process(name=,target=target,args=(some_value,)) 
p.start() 
0

Используя замечательную plumbum библиотеку:

from plumbum import local 
with local.env(LD_LIBRARY_PATH = '/aaalib'): 
    execute_external_program() 

См. docs.

Обратите внимание, что вы также должны использовать plumbum для execute_external_program, то есть не используйте subprocess (или его альтернативы) напрямую. Например, чтобы проверить это ENV-настройку логики, вы можете сделать:

from plumbum import local 
with local.env(LD_LIBRARY_PATH = '/aaalib'): 
    print(local.python("-c", "import os;print os.environ['LD_LIBRARY_PATH']")) 

Чтобы был ясен, это решение гарантирует, что команды, которые выполняются в подпроцессах (с помощью Plumbum) см окр вы хотите, и вас не нужно изменять env vars родительского процесса, чтобы достичь этого, и вам не нужно напрямую использовать модуль «raw» subprocess.

Смежные вопросы