程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了python中的异步,线程问题大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决python中的异步,线程问题?

开发过程中遇到python中的异步,线程问题的问题如何解决?下面主要结合日常开发的经验,给出你关于python中的异步,线程问题的解决方法建议,希望对你解决python中的异步,线程问题有所启发或帮助;

我有以下代码,其中我有一个无限循环,它更新在一个线程中运行的变量的状态,而在另一个线程中,我有一个无限循环,每秒打印所述变量的状态,问题是然状态在第一个线程中正确更新,但状态在第二个线程中保持不受影响。

我能做些什么来解决这个问题?我认为使用线程可以解决这个问题,而且我对异步编程不是很精通

在 main.py 中

import cv2 as cv
from utils import WindowCapture
import numpy as np
import os
import time
from threading import Thread
from threading import Event
import pyautogui
from queue import Queue


os.chdir(os.path.dirname(os.path.abspath(__file__)))

wincap = WindowCapture("DragonBallOnline")
global toggle
global enemyState

# >>> pyautogui.mouseDown(); pyautogui.mouseUp()  # does the same thing as a left-button mouse click
# >>> pyautogui.mouseDown(button='right')  # press the right button down
# >>> pyautogui.mouseUp(button='right',x=100,y=200)  # move the mouse to 100,200,then release the right button up.


def targetIsFullHealth(enemy):
    return (enemy == np.array([65,27,234])).all()


def targetIsDead(enemy):
    return (enemy == np.array([26,10,95])).all()


def targetIsUndefined(enemy):
    return (enemy != np.array([65,234])).all() and (enemy != np.array([97,155,146])).all()


def combatLoop():  # unused
    ## target enemy
    ## if target is full health attack
    ## if target is dead  wait and loot
    ## if target is undefined search new target
    pass


def bot():  # unused
    # DeBUG function not used currently
    while True:
        ##do stuff
        Enemylife = wincap.get_screenshot(902,70,120,16)
        Items = wincap.get_screenshot(621,163,662,749)
        Radar = wincap.get_screenshot(1750,53,157,157)
        cv.imshow("Enemylife",EnemylifE)
        cv.imshow("Items",Items)
        cv.imshow("Radar",Radar)
        # print(Enemylife[10][5])

        if (Enemylife[10][5] == np.array([65,234])).all():
            print("target is full health")
            rotatecursor()
        elif (Enemylife[10][5] == np.array([97,146])).all():
            print("Target is dead")
        else:
            print("No target")

        if cv.waitKey(1) == ord("-"):
            cv.destroyAllwindows()
            break

    print("Done!")


def rotatecursor():  # unused
    # pyautogui.mouseDown(button="right")
    # pyautogui.mouseUp(button="right",x=10,y=1)
    pass


def updateEnemyState(threadName):
    global toggle
    global enemyState
    toggle = True

    while True:
        Enemylife = wincap.get_screenshot(902,16)
        cv.imshow("Enemylife",EnemylifE)
        enemy = Enemylife[10][5]

        if targetIsDead(enemy):
            enemyState = "dead"

        elif targetIsFullHealth(enemy):
            enemyState = "alive"

        else:
            enemyState = "undefined"

        Event().wait(1.0 / 60)
        print("Thread1 :",enemyStatE)

        if cv.waitKey(1) == ord("-"):
            cv.destroyAllwindows()
            toggle = false
            break


def macros(threadName):

    while toggle:
        Event().wait(1.0)

        print("Thread2 :",enemyStatE)


if @R_502_4267@ == "__main__":
    print("test")
    # WindowCapture.List_window_names();

    thread1 = Thread(target=updateEnemyState,args=("Thread-1",))
    thread2 = Thread(target=macros,))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()


在 utils.py 中

import numpy as np
import win32gui,win32ui,win32con


class WindowCapture:

    # propertIEs
    w = 0
    h = 0
    hwnd = None
    cropped_x = 0
    cropped_y = 0
    offset_x = 0
    offset_y = 0

    # constructor
    def __init__(self,window_name=NonE):
        # find the handle for the window we want to capture
        if window_name is None:
            self.hwnd = win32gui.GetDesktopWindow()
        else:
            self.hwnd = win32gui.FinDWindow(None,window_Name)
            if not self.hwnd:
                raise Exception('Window not found: {}'.format(window_Name))

        # get the window size
        window_rect = win32gui.GetwindowRect(self.hwnd)
        self.w = window_rect[2] - window_rect[0]
        self.h = window_rect[3] - window_rect[1]

        # account for the window border and titlebar and cut them off
        #border_pixels = 8
        #titlebar_pixels = 30
        border_pixels = 0
        titlebar_pixels = 0
        self.w = self.w - (border_pixels * 2)
        self.h = self.h - titlebar_pixels - border_pixels
        self.cropped_x = border_pixels
        self.cropped_y = titlebar_pixels

        # set the cropped coordinates offset so we can translate screenshot
        # images into actual screen positions
        self.offset_x = window_rect[0] + self.cropped_x
        self.offset_y = window_rect[1] + self.cropped_y

    def get_screenshot(self,startX=None,startY=None,wIDth=None,height=NonE):
        if startX is None : startX = self.cropped_x
        if startY is None : startY = self.cropped_y
        if wIDth is None : wIDth = self.w
        if height is None : height = self.h


        # get the window image data
        wDC = win32gui.GetwindowDC(self.hwnd)
        dcObj = win32ui.CreateDCFromHandle(wDC)
        cDC = dcObj.CreateCompatibleDC()
        dataBitMap = win32ui.CreateBitmap()
        dataBitMap.CreateCompatibleBitmap(dcObj,wIDth,height)
        cDC.SELEctObject(dataBitMap)
        cDC.bitBlt((0,0),(wIDth,height),dcObj,(startX,startY),win32con.SRCcopY)

        # convert the raw data into a format opencv can read
        #dataBitMap.SaveBitmapfile(cDC,'deBUG.bR_157_11845@p')
        signedIntsArray = dataBitMap.GetBitmapBits(true)
        img = np.fromString(signedIntsArray,dtype='uint8')
        img.shape = (height,4)

        # free resources
        dcObj.deleteDC()
        cDC.deleteDC()
        win32gui.ReleaseDC(self.hwnd,wDC)
        win32gui.deleteObject(dataBitMap.GetHandle())

        img = img[...,:3]
        img = np.ascontiguousarray(img)

        return img

    @staticmethod
    def List_window_names():
        def winEnumHandler(hwnd,ctX):
            if win32gui.IsWindowVisible(hwnd):
                print(hex(hwnd),win32gui.GetwindowText(hwnd))
        win32gui.Enumwindows(winEnumHandler,NonE)

    # translate a pixel position on a screenshot image to a pixel position on the screen.
    # pos = (x,y)
    # WARNING: if you move the window being captured after execution is started,this will
    # return incorrect coordinates because the window position is only calculated in
    # the __init__ constructor.
    
    def get_screen_position(self,pos):
        return (pos[0] + self.offset_x,pos[1] + self.offset_y)

我提供了重新创建示例所需的所有代码,尽管最重要的部分是硬编码的,因此它是一个像素检测器,您可能需要使用另一个窗口名称以及另一个像素位置和颜色值

初始和第一个状态变化:

Thread1 : alive
Thread1 : alive
Thread1 : alive
Thread1 : alive
Thread1 : alive
Thread2 : alive
Thread1 : alive
Thread1 : alive
Thread1 : alive
Thread1 : alive
Thread1 : alive

调试信息

Thread1 : dead
Thread1 : dead
Thread1 : dead
Thread1 : dead
Thread2 : alive
Thread1 : dead
Thread1 : dead
Thread1 : dead
Thread1 : dead
Thread1 : dead
Thread1 : dead

Thread2 的敌人状态应该已经死了 我的猜测是,由于某种原因,敌人状态仍然锁定在线程 2 中。

解决方法

global 语句必须在每个更改 toogle 值的函数中。你不能只包含一次。将该语句移动到 updateEnemyState 中,它应该开始工作。 @H_668_9@macros 函数不需要那个,因为它不会改变值。你可能会修正拼写;应该是 toggle

,

经过反复试验,我发现 time.sleep() 阻塞了线程,还使用了 Threading 中的 Event().wait(1.0) 而不是队列实现,为了简单起见,我认为全局变量是最好的。

大佬总结

以上是大佬教程为你收集整理的python中的异步,线程问题全部内容,希望文章能够帮你解决python中的异步,线程问题所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。