循环执行不终止的批处理脚本

6
我将尝试在Python循环中执行多个批处理脚本。然而,这些批处理脚本包含“cmd /K”,因此不会“终止”(缺乏更好的词)。因此,Python调用第一个脚本并永远等待......以下是伪代码,可以了解我要做什么:
import subprocess

params = [MYSCRIPT, os.curdir]    
for level in range(10):
    subprocess.call(params)  

我的问题是:“有没有一种Pythonic的解决方案来获取控制台命令并恢复循环?”
编辑:我现在知道可以使用Popen(params,shell=False,stdin=None,stdout=None,stderr=None,close_fds=True)启动子进程并继续而不等待它们返回。 但是,这将几乎同时启动我的整个循环。 有没有一种方法可以等待子进程执行其任务,并在命中cmd /K并变为空闲时返回。

注意:如果有人问我为什么不从脚本中删除 cmd /K,我有几个原因。最容易解释的是这些脚本与我的同事共享,我不想搞乱它们。 - snake_charmer
2
看起来这个答案可能适合你。 - joebeeson
谢谢Joeb!看起来DETACHED_PROCESS跳过了整个批处理的执行。建议用于Popen的其他选项,即shell=True, stdin=None, stdout=None, stderr=None, close_fds=True非常有用。脚本不等待子进程终止。当我想要将10个脚本作为并行线程运行时,这将非常有用。 然而,我认为我正在寻找一种方法,在子进程执行其任务并命中cmd /K并变为空闲状态时等待它返回。这可能吗?我应该编辑我的问题以反映这一点吗? - snake_charmer
2个回答

3

没有内置的方法,但这是您可以实现的功能。

示例是使用bash进行的,因为我无法访问Windows机器,但对于cmd \K应该类似。

这可能很简单:

import subprocess

# start the process in the background
process = subprocess.Popen(
    ['bash', '-i'],
    stdout=subprocess.PIPE,
    stdin=subprocess.PIPE
)

# will throw IO error if process terminates by this time for some reason
process.stdin.write("exit\n")
process.wait()

这将向shell发送一个“exit”命令,当脚本终止时应该被处理,从而退出(有效地取消“\K”)。以下是更详细的答案,以防您需要检查某些输出:
import subprocess

# start the process in the background
process = subprocess.Popen(
    ['bash', '-i'],
    stdout=subprocess.PIPE,
    stdin=subprocess.PIPE
)

    # Wait for the process to terminate
    process.poll()
    while process.returncode is None:
        # read the output from the process
        # note that can't use readlines() here as it would block waiting for the process
        lines = [ x for x in process.stdout.read(5).split("\n") if x]
        if lines:
            # if you want the output to show, you'll have to print it yourself
            print(lines )
            # check for some condition in the output
            if any((":" in x for x in lines)):
                # terminate the process
                process.kill()
                # alternatively could send it some input to have it terminate
                # process.stdin.write("exit\n")
        # Check for new return code
        process.poll()

这里的复杂性在于读取输出时,如果尝试读取超过可用的内容,进程将会阻塞。


太棒了!这正是所需之物。我不需要任何输出,但我很欣赏你的彻底性,希望它对有类似问题的人有所帮助。 - snake_charmer

2

这里是我使用的一些内容,用于启动一堆进程(在此示例中为2个),并在程序终止前等待它们。可以修改以在不同时间等待特定进程(请参见注释)。在此示例中,一个进程打印出%path%,另一个打印目录内容。

import win32api, win32con, win32process, win32event

def CreateMyProcess2(cmd):
    ''' create process width no window that runs sdelete with a bunch of arguments'''
    si         = win32process.STARTUPINFO()
    info = win32process.CreateProcess(
        None,      # AppName
        cmd,       # Command line
        None,      # Process Security
        None,      # Thread Security
        0,         # inherit Handles?
        win32process.NORMAL_PRIORITY_CLASS,
        None,      # New environment
        None,      # Current directory
        si)        # startup info
    return info[0]
# info is tuple (hProcess, hThread, processId, threadId)

if __name__ == '__main__' :
    handles       = []

    cmd = 'cmd /c "dir/w"'
    handle = CreateMyProcess2(cmd)
    handles.append(handle)

    cmd = 'cmd /c "path"'
    handle = CreateMyProcess2(cmd)
    handles.append(handle)

    rc = win32event.WaitForMultipleObjects(
        handles, # sequence of objects (here = handles) to wait for
        1,       # wait for them all (use 0 to wait for just one)
        15000)   # timeout in milli-seconds
    print rc
    # rc = 0   if all tasks have completed before the time out  

大致输出(已编辑以便更清晰):

PATH=C:\Users\Philip\algs4\java\bin;C:\Users\Philip\bin;C:\Users\Philip\mksnt\ 等等......

C驱动器的卷标为空。 卷序列号为4CA0-FEAD
C:\Users\Philip\AppData\Local\Temp的目录
[.]
[..]
FXSAPIDebugLogFile.txt
等等....
1个文件,0字节
3个目录,305,473,040,384字节空闲

0 <-- "rc"的值


有趣的答案,尽管它有一个明显的限制,即用户应该先估计运行时间。 我尝试了一种稍微不同的方法,一次只运行一个句柄 handle = CreateMyProcess2( cmd ) ; rc = win32event.WaitForSingleObject(handle, 30000) 但是我无法将我的 subprocess.call 参数排列成 Windows 能够理解的 cmd 字符串。有没有一种方法可以创建一个 subprocess 对象而不调用它,然后将其转换为句柄? - snake_charmer
你可以使用2147483647。 - Marichyasana
你是什么意思?2147483647是什么? - snake_charmer
2147483647。这是32位操作系统上有符号整数的最大正值。那可真是很长的时间啊。 - Marichyasana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接