Python多线程多个bash子进程。但是设置一个环境变量?
再次编程与Python DOS批处理命令Python多线程多个bash子进程。但是设置一个环境变量?
有一个伟大的答案Python threading multiple bash subprocesses?
我敢肯定,这将解决我的问题,但我都试过了Popen
和multiprocessing
方法并且都不起作用。
这是我的问题:我想为每个进程中使用的Windows环境变量(如TMP
)设置一个唯一值。因此,进程1将写入文件夹1,进程2将写入文件夹2 - 并且就环境变量而言,进程1不会看到进程2看到的是什么。我的代码是answer above。变体1使用Windows set VAR=abc method
。 Variant 2使用Python的os.environ['TMP']=abc
方法,并且不应该工作,因为在由dos设置之前,python会访问TMP。 1和2都不起作用。变体3是一个全面的检查,以及工作,但并没有解决我的问题
from subprocess import Popen
import os
commands = [
# variant 1: does not work
'set TMP=C:\\Temp\\1 && echo abc1 > %TMP%\\1.log', 'set TMP=C:\\Temp\\2 && echo abc2 > %TMP%\\2.log'
# variant 2: does not work
# 'set TMP=C:\\Temp\\1 && echo abc1 > '+os.environ['TMP']+'\\1.log', 'set TMP=C:\\Temp\\2 && echo abc2 > '+os.environ['TMP']+'\\2.log'
# variant 3: works, but does not set TMP environmental variable
# 'echo abc1 > C:\\Temp\\1\\1.log', 'echo abc2 > C:\\Temp\\2\\2.log'
]
# run in parallel
processes = [Popen(cmd, shell=True) for cmd in commands]
# do other things here..
# wait for completion
for p in processes: p.wait()
这里是我的multiprocessing
方法(Python变量commands
在上面的脚本所定义的)代码:
from functools import partial
from multiprocessing.dummy import Pool
from subprocess import call
import os
pool = Pool(2) # two concurrent commands at a time
for i, returncode in enumerate(pool.imap(partial(call, shell=True), commands)):
if returncode != 0:
print("%d command failed: %d" % (i, returncode))
(我也尝试set TMP=\"C:\\Temp\\1\"
与文件夹周围双引号)
((Python的2.7.13 64位的Windows 10))
并没有涉及到我参考答案,我试过这个功能:
import os
from subprocess import check_output
def make_tmp(tmp_path):
os.environ['TMP'] = tmp_path
dos = 'echo '+tmp_path+' > '+os.environ['TMP']+'\\output.log'
check_output(dos, shell=True)
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(2)
print os.environ['TMP']
path_array = ['\"C:\\Temp\\1\"', '\"C:\\Temp\\2\"']
用下面的回溯:
Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.*
Traceback (most recent call last):
File "C:\Users\project11\Dropbox\project11\code_current\dev_folder\google_sheets\test_windows_variables.py", line 32, in <module>
results = pool.map(make_tmp, path_array)
File "C:\ProgramData\Anaconda2\lib\multiprocessing\pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "C:\ProgramData\Anaconda2\lib\multiprocessing\pool.py", line 567, in get
raise self._value
subprocess.CalledProcessError: Command 'echo "C:\Temp\1" > "C:\Temp\2"\output.log' returned non-zero exit status 1
*该进程无法访问该文件因为它正在被另一个进程使用。
也试过another answer to the same question,没有运气。
这里是工作的代码,这要归功于Chepner和JohanL评论
import subprocess, os
def make_tmp(tmp_path):
my_env = os.environ.copy()
my_env['TMP'] = tmp_path
dos = 'echo '+tmp_path[-1]+' > '+my_env['TMP']+'\\output.log'
# or run a bat script
# dos = 'C:\\Temp\\launch.bat'
subprocess.Popen(dos, env=my_env, stdout=subprocess.PIPE, shell=True)
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(2)
path_array = ['C:\\Temp\\1', 'C:\\Temp\\2', 'C:\\Temp\\3']
results = pool.map(make_tmp, path_array)
注意,path_array必须被现有的文件夹
这应该不需要'subprocess.PIPE',虽然。这在Python本身中是更好的(然后,它将需要'subprocess.PIPE',而不是'shell = True')。 – JohanL
如果你的使用情况是只输出捕获到文件,你可以让Python为你做,通过将命令输出重定向到subprocess.PIPE
,然后存储来自Python的数据。这样做的好处是您不需要使用shell=True
,从而为您自己节省一个可能的漏洞并创建额外的流程。这可以写成:
import subprocess, os
def make_tmp(tmp_path):
dos = ['echo', tmp_path[-1]]
outfile = os.path.join(tmp_path, 'output.log')
cmd_proc = subprocess.Popen(dos, stdout=subprocess.PIPE)
with open(outfile, 'w') as f:
f.write(cmd_proc.communciate[0])
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(2)
path_array = ['C:\\Temp\\1', 'C:\\Temp\\2', 'C:\\Temp\\3']
results = pool.map(make_tmp, path_array)
警告:我还没有测试上面的代码的时候,所以可能会有一些小错误。
感谢您的回答。实际上,echo是一个测试用例,并且完整的python脚本环绕一个Windows可执行文件,该文件将临时文件data.bin写入TMP文件夹。我想运行这个Windows可执行文件的多个进程,但它们都引用相同的TMP文件夹和data.bin文件。这就是为什么我想更新每个流程的TMP。 – philshem
你想使你的电话之前更新您的环境,然后使用'POPEN更新后的环境()'在https://*.com/questions/2231227/python-subprocess-popen-with-a看到修改环境 – JohanL
谢谢。我想修改os.environ [“TMP”]在这个过程中 - 所以我想你参考答案将无法正常工作 – philshem
OK,你为什么要这么做?要在原始程序中使用更新的值?因为这不能通过使用子过程来完成。 – JohanL