Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading Python 2.7-使用线程时,如何为单个subprocess.call()任务生成单独的Windows控制台?_Multithreading_Shell_Python 2.7_Console_Subprocess - Fatal编程技术网

Multithreading Python 2.7-使用线程时,如何为单个subprocess.call()任务生成单独的Windows控制台?

Multithreading Python 2.7-使用线程时,如何为单个subprocess.call()任务生成单独的Windows控制台?,multithreading,shell,python-2.7,console,subprocess,Multithreading,Shell,Python 2.7,Console,Subprocess,我已经探讨了这个问题,并在这里对stackoverflow进行了研究。我在这些线程中遵循了建议,但到目前为止还没有任何结果(我认为我不理解一些基本的东西): 我有一个脚本,它运行一个模拟列表(使用一个单独的Windows程序),并使用线程并行运行n个模型,而不是像普通Windows批处理文件那样完全按顺序运行。该模型通常会向Windows控制台输出一组信息,以便您可以监视其进度。在我的例子中,我希望主Python脚本在一个窗口/控制台中运行,然后我希望每个模型/模拟生成自己的窗口/控制台,

我已经探讨了这个问题,并在这里对stackoverflow进行了研究。我在这些线程中遵循了建议,但到目前为止还没有任何结果(我认为我不理解一些基本的东西):

我有一个脚本,它运行一个模拟列表(使用一个单独的Windows程序),并使用线程并行运行n个模型,而不是像普通Windows批处理文件那样完全按顺序运行。该模型通常会向Windows控制台输出一组信息,以便您可以监视其进度。在我的例子中,我希望主Python脚本在一个窗口/控制台中运行,然后我希望每个模型/模拟生成自己的窗口/控制台,以便可以独立地监视每个模拟(或者通过关闭窗口来暂停/停止/终止)

当我在编辑器中运行Python脚本时(我已经尝试了Enthound Canopy和IDLE),该脚本完全按照预期工作,为每个模拟生成单独的窗口。但是,如果通过在Windows资源管理器中双击Python脚本或从Windows命令提示符调用它来运行Python脚本,则各个模拟不会生成自己的窗口。它们都将输出直接转储到同一个窗口中,造成混乱(也不允许我通过关闭单个窗口来终止模拟)

为了解决我的问题,我尝试了以上链接中的所有建议。这包括使用shell=True、使用Windows“start”命令、重定向输出管道等各种不同的组合。这些解决方案都不适合我

我觉得我不明白为什么我的脚本在Canopy/IDLE中按预期工作,但在直接从命令提示符运行时不工作

我的脚本如下:

from time import sleep
import threading
from subprocess import call

def runmodel(arg):
    call(arg)
    sGlobal.release()

if __name__ == '__main__':    

    n = 6 # maximum number of simultaneous runs
    s = 15 # delay between starts in seconds

    simulations = [] # big list of simulations to run in here - each item in list is another list containing the seperate arguments in the command line

    threads = []
    global sGlobal

    sGlobal = threading.Semaphore(n)

    for arg in simulations:
        sGlobal.acquire()
        t = threading.Thread(target=runmodel, args=(arg,))
        threads.append(t)
        t.start()
        sleep(s)

    for t in threads:
        t.join()
作为参考,运行模拟的Windows命令行如下所示(在我的实际脚本中有一个很大的列表-在Python脚本中,每个命令都作为列表而不是字符串传递给subprocess.call):

“”-some-flags-此处“”
我将非常感谢任何有助于我更好地理解或解决我的问题的意见

编辑:阐明每个命令行都作为列表而不是字符串传递给subprocess.call

编辑2:感谢J.F.塞巴斯蒂安在下面的评论,我现在有了工作代码。关键是在命令行的开头使用“cmd.exe/c start“NAME”,将所有内容作为字符串而不是列表连接起来,然后将命令行字符串传递给subprocess.call(),shell=True。因此,工作守则是:

from time import sleep
import threading
from subprocess import call

def runmodel(arg):
    call(arg, shell=True) # not the addition of shell=True - this is now required as the command line is being passed as a string rather than a list - I could not get the syntax with quotation marks and everything else to work without using a string and shell=True.
    sGlobal.release()

if __name__ == '__main__':    

    n = 6 # maximum number of simultaneous runs
    s = 15 # delay between starts in seconds

    simulations = ['cmd.exe /c start "NAME" "<full file path to model exe>" -some -flags -here "<full file path to model control file>"'] # big list of simulations to run in here - each item in list is a string that represents the full command line to run a simulation

    threads = []
    global sGlobal

    sGlobal = threading.Semaphore(n)

    for arg in simulations:
        sGlobal.acquire()
        t = threading.Thread(target=runmodel, args=(arg,))
        threads.append(t)
        t.start()
        sleep(s)

    for t in threads:
        t.join()
from time import sleep
import threading
from subprocess import call

def runmodel(arg):
    call(arg, shell=True) # not the addition of shell=True - this is now required as the command line is being passed as a string rather than a list - I could not get the syntax with quotation marks and everything else to work without using a string and shell=True.
    sGlobal.release()

if __name__ == '__main__':    

    n = 6 # maximum number of simultaneous runs
    s = 15 # delay between starts in seconds

    simulations = ['cmd.exe /c start "NAME" "<full file path to model exe>" -some -flags -here "<full file path to model control file>"'] # big list of simulations to run in here - each item in list is a string that represents the full command line to run a simulation

    threads = []
    global sGlobal

    sGlobal = threading.Semaphore(n)

    for arg in simulations:
        sGlobal.acquire()
        t = threading.Thread(target=runmodel, args=(arg,))
        threads.append(t)
        t.start()
        sleep(s)

    for t in threads:
        t.join()
从时间导入睡眠
导入线程
从子流程导入调用
def运行模式(参数):
call(arg,shell=True)#不是添加shell=True-现在需要这样做,因为命令行是作为字符串而不是列表传递的-如果不使用字符串和shell=True,我无法使用带引号的语法和其他所有内容。
sGlobal.release()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
n=6#同时运行的最大次数
s=15#启动之间的延迟(秒)
simulations=['cmd.exe/c start“NAME”“”-some-flags-here”“]#要在此处运行的模拟的大列表-列表中的每个项目都是一个字符串,表示运行模拟的完整命令行
线程=[]
全球
sGlobal=threading.Semaphore(n)
对于模拟中的arg:
sGlobal.acquire()
线程(target=runmodel,args=(arg,))
threads.append(t)
t、 开始()
睡眠
对于螺纹中的t:
t、 加入

多亏了J.F.塞巴斯蒂安的评论,我现在有了工作代码。关键是在命令行的开头使用“cmd.exe/c start“NAME”,将所有内容作为字符串而不是列表连接起来,然后将命令行字符串传递给subprocess.call(),shell=True。因此,工作守则是:

from time import sleep
import threading
from subprocess import call

def runmodel(arg):
    call(arg, shell=True) # not the addition of shell=True - this is now required as the command line is being passed as a string rather than a list - I could not get the syntax with quotation marks and everything else to work without using a string and shell=True.
    sGlobal.release()

if __name__ == '__main__':    

    n = 6 # maximum number of simultaneous runs
    s = 15 # delay between starts in seconds

    simulations = ['cmd.exe /c start "NAME" "<full file path to model exe>" -some -flags -here "<full file path to model control file>"'] # big list of simulations to run in here - each item in list is a string that represents the full command line to run a simulation

    threads = []
    global sGlobal

    sGlobal = threading.Semaphore(n)

    for arg in simulations:
        sGlobal.acquire()
        t = threading.Thread(target=runmodel, args=(arg,))
        threads.append(t)
        t.start()
        sleep(s)

    for t in threads:
        t.join()
from time import sleep
import threading
from subprocess import call

def runmodel(arg):
    call(arg, shell=True) # not the addition of shell=True - this is now required as the command line is being passed as a string rather than a list - I could not get the syntax with quotation marks and everything else to work without using a string and shell=True.
    sGlobal.release()

if __name__ == '__main__':    

    n = 6 # maximum number of simultaneous runs
    s = 15 # delay between starts in seconds

    simulations = ['cmd.exe /c start "NAME" "<full file path to model exe>" -some -flags -here "<full file path to model control file>"'] # big list of simulations to run in here - each item in list is a string that represents the full command line to run a simulation

    threads = []
    global sGlobal

    sGlobal = threading.Semaphore(n)

    for arg in simulations:
        sGlobal.acquire()
        t = threading.Thread(target=runmodel, args=(arg,))
        threads.append(t)
        t.start()
        sleep(s)

    for t in threads:
        t.join()
从时间导入睡眠
导入线程
从子流程导入调用
def运行模式(参数):
call(arg,shell=True)#不是添加shell=True-现在需要这样做,因为命令行是作为字符串而不是列表传递的-如果不使用字符串和shell=True,我无法使用带引号的语法和其他所有内容。
sGlobal.release()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
n=6#同时运行的最大次数
s=15#启动之间的延迟(秒)
simulations=['cmd.exe/c start“NAME”“”-some-flags-here”“]#要在此处运行的模拟的大列表-列表中的每个项目都是一个字符串,表示运行模拟的完整命令行
线程=[]
全球
sGlobal=threading.Semaphore(n)
对于模拟中的arg:
sGlobal.acquire()
线程(target=runmodel,args=(arg,))
threads.append(t)
t、 开始()
睡眠
对于螺纹中的t:
t、 加入

看起来您正在创建线程,每个线程生成单个子进程。您是否尝试从主线程生成多个进程?将命令作为列表而不是字符串提供。请使用
shlex.split(cmd)
,谢谢您的回复。对于您的第一个评论,我必须使用线程,因为这是我成功地在任何两个连续模型运行的开始之间引入固定时间延迟的唯一方法(对于每个模型都必须访问的共享文件的原因很重要)。在您的第二条注释中,该命令已经作为列表传递(否则我理解subprocess.call将不起作用)。正如我所说,该脚本在Canopy和IDLE中完全按照预期工作(只是在独立运行时不这样)。@MaciejLach:
shlex.split()
不适用于Windows:(1)它使用了不同的语法(2)字符串是本地接口