[Python] pyautogui 멀티모니터에서도 잘 동작시키기 – python 자동화

pyautogui는 파이썬을 이용해 키보드와 마우스를 조작할 수 있는 오토메이션 툴이다.

이미 수많은 고수분들이 pyautogui에 대한 글을 많이 올려주시고 있고,
구글링을 하면 수십만개의 글이 쏟아지므로 배우고 활용하는 데 큰 어려움은 없다.

다만 pyautogui는 공식적으로 (아직) 멀티모니터를 지원하지 않는다.
조금 더 구체적으로 말하면 메인모니터에서만 동작한다.
이게 왜 문제가 되냐면,

pyautogui는 멀티모니터를 지원하지 않음

→ windows는 어떤 프로그램이 최종 실행되고 종료된 모니터를 기억하고 있음
→ 만약 어떤 프로그램을 실행시켰는데 서브모니터에서 실행되면
→ pyautogui는 아무 역할을 하지 못함

근데 난 멀티모니터를 쓰잖아. 어떡하지?
답은 구글링에 있다.

https://github.com/asweigart/pyautogui/issues/321
(Use LocateOnScreen with Multiple Monitors)

위의 github 글을 보면 수많은 Genius들이 멋진 해결책을 올려주었다. 그 중 가장 잘 동작하는 것을 소개한다.
pascallo님이 2020년 5월 18일에 올려주신 방법.


참고로 굉장히 Specific한 경우로,
locateOnScreen 함수를 쓸 때 적용된다.


*locateOnScreen 함수는,

– 화면에서 특정 이미지가 있는지 확인한 뒤
– 해당 좌표를 반환해주는 함수이다.

문제 해결 핵심: pyscreeze 폴더 내부의 init.py를 수정

  • pyscreeze 위치: python설치폴더/Lib/site-packages
  • Windows에서만 동작함

1. 함수 _screenshot_win32은 아래와 같다.

def _screenshot_win32(imageFilename=None, region=None):
...
    im = ImageGrab.grab()  

위 코드에서 im = ImageGrab.grab() 을 아래와 같이 변경한다.

def _screenshot_win32(imageFilename=None, region=None):
...
    im = ImageGrab.grab(all_screens= True)

2. 함수 locateOnScreen은 아래와 같다.

def locateOnScreen(image, minSearchTime=0, **kwargs):
...
    retVal = locate(image, screenshotIm, **kwargs)

내부에 있는 retVal (아래 참고) 직전에 다음과 같은 내용을 추가한다.

def locateOnScreen(image, minSearchTime=0, **kwargs):
...
   if retVal and sys.platform == 'win32':
        # get the lowest x and y coordinate of the monitor setup
        monitors = win32api.EnumDisplayMonitors()
        x_min = min([mon[2][0] for mon in monitors])
        y_min = min([mon[2][1] for mon in monitors])
        # add negative offset due to multi monitor
        retVal = Box(left=retVal[0] + x_min, top=retVal[1] + y_min, width=retVal[2], height=retVal[3])
    retVal = locate(image, screenshotIm, **kwargs)

3. __init__.py의 최상단 import들이 모여있는 곳에 다음 내용을 추가한다.

if sys.platform == 'win32': # TODO - Pillow now supports ImageGrab on macOS.
    import win32api # used for multi-monitor fix
    from PIL import ImageGrab

4. 이제 locateOnScreen 함수를 쓰면 멀티모니터를 잘 왔다갔다 한다.

아래는 원문.

Leave a Comment