繁体   English   中英

直到调用进程完成,Python子进程才会运行

[英]Python subprocess doesn't run until calling process finished

编辑1-添加了更多代码,我不确定是否需要proc.communicate,这是我从其他stackoverflow代码中发现的建议之一。(对不起,我昨晚很累,在问这个问题之前并没有想太多)

我应该补充一点,我不是经验丰富的编码员(机械工程师),您可能会从我的代码中看出

在我的Gui中,有一个按钮可以调用子流程

子进程(screenshot-cmd.exe)创建裁剪后的屏幕截图的png,但直到出现错误或按钮单击事件结束后,它才真正生成文件。

这让我认为直到事件结束才真正运行子流程

我想在按下一个按钮后多次调用该过程,并在每次生成后移动它生成的文件

如果我使用proc.wait(),进程将无限期挂起。

如何停止呢?

# function to take a single image called 'fileName' and place it in directory 'dir'
def takeImage(dir,fileName):

    # calculate the view to capture to get the whole display window in.
    clientRect = win32gui.GetClientRect(win32gui.GetForegroundWindow())
    windowRect = win32gui.GetWindowRect(win32gui.GetForegroundWindow())
    print(windowRect)
    windowSize = [windowRect[2]-windowRect[0],windowRect[3]-windowRect[1]]
    print(windowSize)
    print(clientRect)

    diffSize = [windowSize[0] -clientRect[2], windowSize[1] - clientRect[3]]
    lrbBorder = diffSize[0]/2
    topBorder = diffSize[1] - lrbBorder

    print("sizeDiff = " + str(diffSize))
    windowName = win32gui.GetWindowText(win32gui.GetForegroundWindow())
    handleId = win32gui.GetForegroundWindow()


    leftMar = designLabel.GetPosition()[0] + lrbBorder
    topMar = designLabel.GetPosition()[1]  + topBorder + designLabel.GetSize()[1]
    rightMar = leftMar + scene.width
    bottMar = topMar+scene.height

    margins = [leftMar,topMar,rightMar,bottMar]

    print(margins)

    # now print the view.
    #command_line = r"screenshot-cmd -wt '" + windowName + "' -rc " + str(margins[0]) + " " + str(margins[1]) + " " + str(margins[2]) + " " + str(margins[3]) + " -o " + fileName

    command_line = r"screenshot-cmd -wt '" + windowName + "' -rc " + str(margins[0]) + " " + str(margins[1]) + " " + str(margins[2]) + " " + str(margins[3]) + " -o " + fileName

    print(command_line)
    args = shlex.split(command_line)
    proc = subprocess.Popen(args)
    proc.wait() 

    wx.Yield()


    if not os.path.isdir(dir):
        os.makedirs(dir)

    newPath = os.path.join(dir,fileName)

    if os.path.exists(newPath):
        os.remove(newPath)

    oldPath = os.path.join(os.getcwd(), fileName)
    print("Old Path: " + oldPath)
    print("Exists: " + str(os.path.exists(oldPath)))
    shutil.move(oldPath,newPath)

    return

#event called upon clicking 'takeTenImag' button
def takeTenImgE(evt):
    global designNo
    global workingDirectory
    global numDesigns
    fileNameRoot = "test_"
    fileExtention = ".png"

    # check there are at least 10 designs
    if numDesigns > 9 and os.path.exists(workingDirectory):
        # find directory path to put images in 
        dir = os.path.join(workingDirectory, "images")
        # for each design

        for x in range(10):
            print("design =" + str(designNo))
            fileName = fileNameRoot + str(designNo) + fileExtention
            print("------------------")
            print("for x = " + str(x) + " "  + fileName)
            #   create image and save
            print(dir)
            takeImage(dir,fileName)
            #move to next design

            wx.PostEvent(forwardDesign, wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, forwardDesign.GetId()) ) 
            wx.Yield()
            print("design =" + str(designNo))
return

takeTenImg = wx.Button(p, label='Take Ten Images', pos=(rb + visScaleText.GetSize()[0]+10,takeImg.GetPosition()[1]+5 +takeImg.GetSize()[1]), size = (100,30))
takeTenImg.Bind(wx.EVT_BUTTON, takeTenImgE)

https://code.google.com/p/screenshot-cmd/

Barnaby,您可能使子流程的使用过于复杂。 Popen通常用于在运行期间需要与流程进行通信的情况。 从它的声音来看,您不需要这样做,因此可能要使用更高级别的功能。 请参阅有关子流程的各种调用的文档 ,并尝试使用call方法。 您将需要shell = True ,如题中所述。

我发现错误在于我对子流程的调用。

我正在使用:

command_line = r"screenshot-cmd -wt '" + windowName + ...." 
args = shlex.split(command_line)
subprocess.call(args,shell=True)

更改为:

command_line = r"screenshot-cmd -wt '" + windowName + ...." 
subprocess.call(command_line,shell=True)

解决挂起。

奇怪的是,这两个选项均不在wx按钮单击事件(即从命令行启动的python脚本)中起作用,而只有第二个选项在wx按钮单击事件中起作用。 如果有人能启发我,那将是最感激的。

编辑:经进一步调查,挂起是由于尝试在screenshot-cmd中指定活动窗口引起的。

为了解决这个问题,我使用windowRect = win32gui.GetWindowRect(win32gui.GetForegroundWindow())找到了窗口的位置

然后在不指定窗口的情况下使用screenshot-cmd。

尽管尚不清楚这会导致问题的原因,但是这可以解决所有问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM