真是太好了!
我试图使用pyautogui来运行一些简单的检查,我试图让主进程检测到视觉输入,然后启动一个子进程,在共享变量在屏幕上移动时,用不同图像的Y位置不断更新它,直到它消失。
不幸的是,我还不是一个程序员,所以我一直被困在执行上,所以我想寻求帮助。这是我写的代码,
import pyautogui
import time
import importlib
foobar = importlib.import_module("cv2")
foocat = importlib.import_module("concurrent")
import numpy
import concurrent.futures
with concurrent.futures.ProcessPoolExecutor() as executor:
CheckingInput = executor.submit(CheckPositionInput)
CheckingImage = executor.submit(CheckPositionImage)
print(XMark, YMark)
print(time.time() - startingtime)
def CheckPositionInput():
Checked = False
global XImage, YImage, XMark, YMark, AreaOnScreen
while not Checked:
print('Searching')
if pyautogui.locateCenterOnScreen('Area.png', confidence=0.8) != None:
Checked = True
AreaOnScreen = True
XMark, YMark = pyautogui.locateCenterOnScreen('Area.png', confidence=0.8)
def CheckPositionImage():
global XImage, YImage, XMark, YMark, AreaOnScreen
print('start')
while not AreaOnScreen:
print('Waiting')
while AreaOnScreen:
if pyautogui.locateCenterOnScreen('Image.png', confidence=0.6) != None:
XMark, YMark = pyautogui.locateCenterOnScreen('Image.png', confidence=0.6)
print(YMark)
print('Checking')
我遇到的问题从CheckPositionImage
中的while循环在一个循环后关闭并死亡,到CheckPositionImage
中的whire循环被卡住并停止检查位置过程,无论我尝试什么,我都无法在过程之外正确更新关键的Ymark
变量。
重要的是要理解全局变量不能在多个进程之间进行读/写共享。子进程可以继承这样的变量值(取决于您运行的平台(并读取其值,但一旦进程为该变量分配了新值,这种更改就不会反映回任何其他进程。这是因为每个进程都在自己的地址空间中运行,并且只能修改全局变量的副本。您需要使用主进程创建并传递给其子进程的共享内存变量。但让我们暂时忽略这个基本问题,并假设全局变量是可共享的。
如果我正确地遵循你的代码,这就是你似乎在做的事情:
- 主进程将两个任务提交给多处理池,由辅助函数
CheckPositionInput
和CheckPositionImage
处理,然后等待这两个任务完成,以打印出全局变量XMark
和YMark
,这可能是由CheckPositionImage
函数设置的 CheckPositionImage
有效地不执行任何操作,直到CheckPositionInput
将全局变量AreaOnScreen
设置为True
,这仅发生在调用pyautogui.locateCenterOnScreen('Area.png', confidence=0.8)
返回非None
的值之后。发生这种情况时,checked
设置为True
,循环终止,从而有效地终止了任务- 当变量CCD_ 17被设置为CCD_。函数
CheckPositionImage
最终进入调用pyautogui.locateCenterOnScreen('Image.png', confidence=0.6)
的循环。当此函数返回一个不是None
的值时,将发出两条打印语句,并重新迭代循环
就我的分析是正确的而言,我有一些评论:
- 此
CheckPositionImage
任务永远不会结束,因为变量AreaOnSCreen
既不会重置为False
,也不会在循环中发出return
或break
语句。我认为这是一个疏忽,一旦我们从对pyautogui.locateCenterOnScreen
的调用中返回了一个非None
值,我们就应该返回。我的假设是基于这样一个事实,即如果不发生这种终止,以concurrent.futures.ProcessPoolExecutor() as executor:
开始的主进程块将永远不会完成(隐含地等待所有提交的任务完成(,因此您永远不会陷入后续的print
语句 - 您永远不会初始化变量
startingtime
- 函数
CheckPositionInput
设置全局变量XMark
和YMark
,它们的值从未被主进程或函数pyautogui.locateCenterOnScreen('Image.png', confidence=0.6)
引用。用相同的参数第二次调用这个函数来设置这些永远不会读取的变量有什么意义
您有进程在运行,但实际处理基本上是顺序的:主进程什么都不做,直到它创建的两个子进程都结束,一个子进程什么都没做,直到另一个子进程在终止时设置标志。因此,我认为根本没有理由使用多处理。您的代码可以很简单(注意,我已经根据Python的PEP8编码约定重命名了变量和函数:
import pyautogui
import time
# What is the purpose of these next 3 commented-out statements?
#import importlib
#foobar = importlib.import_module("cv2")
#foocat = importlib.import_module("concurrent")
def search_and_check():
print('Searching...')
while True:
if pyautogui.locateCenterOnScreen('Area.png', confidence=0.8) != None:
# What is the purpose of this second call, which I have commented out?
# Note that the values set, i.e. xMark and yMark, are never referenced.
#xMark, yMark = pyautogui.locateCenterOnScreen('Area.png', confidence=0.8)
break
print('Checking...')
while True:
result = pyautogui.locateCenterOnScreen('Image.png', confidence=0.6)
if result != None:
return result
starting_time = time.time()
xMark, yMark = search_and_check()
print(xMark, yMark)
print(time.time() - starting_time)
是否可以/应该并行执行对pyautogui.locateCenterOnScreen
的两个不同调用