编辑1 - 添加了更多代码 我不确定是否需要proc.communicate,这是我从其他一些stackoverflow代码中找到的建议之一。(抱歉,昨晚我累了,在提问之前没想太多。)
我应该补充一点,我不是一位经验丰富的编码员(机械工程师),你可以从我的代码中看出来
在我的Gui中,我有一个按钮来调用子进程
子进程(screenshot-cmd.exe)创建了一个裁剪的屏幕截图,但在出现错误或按钮点击事件结束之前,它实际上不会生成文件。
这让我觉得在事件结束之前子进程实际上并没有运行
我想在按下一个按钮后多次调用该过程,并在每个按钮生成后移动它生成的文件
如果我使用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)
答案 0 :(得分:0)
Barnaby,您可能会过度复杂化您的子流程使用。 Popen通常用于在运行期间需要与进程通信时。从它的声音,你不需要这样做,所以可能想要使用更高级别的功能。请参阅子流程上的the docs'各种调用,也许尝试使用调用方法。您需要 shell = True ,详见this one等问题。
答案 1 :(得分:0)
我发现错误是在我调用子进程时。
我正在使用:
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而不指定窗口。
这解决了所有问题,但不清楚为什么会导致问题