PyAutoGUIの入力速度の超高速化
これは自己責任です
灰文字ではなく明示的に黒文字で、しかもh2で書きます。
あなたの使っているコンピューターが壊れても、私は一切の責任を負いません。このページを参考にしてプログラムを書き換えて、コンピューターをダメにしてもそれは私の責任ではないので、自分で対処してください。
はじめに
面倒なことはPythonにやらせたい!
これはPythonistaならよく思うことだと思います。
キーボード入力でラクするためにPyAutoGUIを使うことも多いはずです。
しかし、PyAutoGUI(以下、pguiと略します)の入力速度は遅い! もっと早くしたい!
そんな人のためのページです笑
結構すぐ読み終わります。
環境
- macOS Catalina(10.15.5)
- MacBook Air (13-inch, 2017)
- Python 3.8.0
- PyAutoGUI 0.9.48
Windowsでもまあたぶんできますが、実際に私は実行していないので分かりません。
また、私はvimmerなのでIDEのことは知りません。知ってても知りません()
なので、IDEで実際にできるかを調べていないので、Anacondaとかでやってる場合は自分で確認してください。
な、何をするんですか!?
具体的なフローはこんな感じです。
- ライブラリーpguiがどこに入っているのか調べる
- pguiの中に入っているファイルを書き換える。具体的には、
_pyautogui_osx.py
を書き換える(今回はmacOSで実行しているのでこうなります)
手順はめっちゃ少ないです。
1. ライブラリーpguiがどこに入っているのか調べる
import pyautogui as pgui
if __name__ == '__main__':
prin(f'{pgui.__file__=}')
で出力はこんな感じになりました(適宜伏字にしています)
pgui.__file__='****/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyautogui/__init__.py'
では、出力されたディレクトリーのパス****/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyautogui
を開いてみましょう。
こんな感じで出力されていると思います。
パスによっては、開けないかもしれませんが、そこは適宜chmodするなりして書き換えられるようにしてください。
2. pguiの中に入っているファイルを書き換える
次に、_pyautogui_osx.py
のファイルを開きます。
time.sleep(0.01)
と書かれている行が4箇所あるのですが、そのうちの1行をコメントアウトするなり削除するなりして、読み飛ばすように書き換えます。
import time
import sys
...
def _normalKeyEvent(key, upDown):
assert upDown in ('up', 'down'), "upDown argument must be 'up' or 'down'"
try:
if pyautogui.isShiftCharacter(key):
key_code = keyboardMapping[key.lower()]
event = Quartz.CGEventCreateKeyboardEvent(None,
keyboardMapping['shift'], upDown == 'down')
Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
# Tiny sleep to let OS X catch up on us pressing shift
time.sleep(0.01)
else:
key_code = keyboardMapping[key]
event = Quartz.CGEventCreateKeyboardEvent(None, key_code, upDown == 'down')
Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
time.sleep(0.01)
# TODO - wait, is the shift key's keyup not done?
# TODO - get rid of this try-except.
except KeyError:
raise RuntimeError("Key %s not implemented." % (key))
...
def _dragTo(x, y, button):
if button == LEFT:
_sendMouseEvent(Quartz.kCGEventLeftMouseDragged , x, y, Quartz.kCGMouseButtonLeft)
elif button == MIDDLE:
_sendMouseEvent(Quartz.kCGEventOtherMouseDragged , x, y, Quartz.kCGMouseButtonCenter)
elif button == RIGHT:
_sendMouseEvent(Quartz.kCGEventRightMouseDragged , x, y, Quartz.kCGMouseButtonRight)
else:
assert False, "button argument not in ('left', 'middle', 'right')"
time.sleep(0.01) # needed to allow OS time to catch up.
def _moveTo(x, y):
_sendMouseEvent(Quartz.kCGEventMouseMoved, x, y, 0)
time.sleep(0.01) # needed to allow OS time to catch up.
これを……、
import time
import sys
...
def _normalKeyEvent(key, upDown):
assert upDown in ('up', 'down'), "upDown argument must be 'up' or 'down'"
try:
if pyautogui.isShiftCharacter(key):
key_code = keyboardMapping[key.lower()]
event = Quartz.CGEventCreateKeyboardEvent(None,
keyboardMapping['shift'], upDown == 'down')
Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
# Tiny sleep to let OS X catch up on us pressing shift
time.sleep(0.01)
else:
key_code = keyboardMapping[key]
event = Quartz.CGEventCreateKeyboardEvent(None, key_code, upDown == 'down')
Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
#time.sleep(0.01)
# TODO - wait, is the shift key's keyup not done?
# TODO - get rid of this try-except.
except KeyError:
raise RuntimeError("Key %s not implemented." % (key))
...
def _dragTo(x, y, button):
if button == LEFT:
_sendMouseEvent(Quartz.kCGEventLeftMouseDragged , x, y, Quartz.kCGMouseButtonLeft)
elif button == MIDDLE:
_sendMouseEvent(Quartz.kCGEventOtherMouseDragged , x, y, Quartz.kCGMouseButtonCenter)
elif button == RIGHT:
_sendMouseEvent(Quartz.kCGEventRightMouseDragged , x, y, Quartz.kCGMouseButtonRight)
else:
assert False, "button argument not in ('left', 'middle', 'right')"
time.sleep(0.01) # needed to allow OS time to catch up.
def _moveTo(x, y):
_sendMouseEvent(Quartz.kCGEventMouseMoved, x, y, 0)
time.sleep(0.01) # needed to allow OS time to catch up.
こう!
2行目だけをコメントアウトすることを推奨します。
プログラムのコメントアウトにも書いてあるとおり、シフトを使う文字、例えば「?」や「!」に関しては条件分岐しています。
0.01秒はどうやら、シフトを外すために必要な時間だそうです。
ここをコメントアウトして試してみましたが、ロクなことになりませんでした。
で、何をしたの?
実はpguiではtime.sleep(0.01)
という処理によって、打速を単位秒あたり100打(以下)しかキーを打てない構造になっているのです。これは驚き。
この部分を削除すると文字通り、入力速度の超高速化が実現できるわけです。
実行例のプログラム
実際に実行してみたところ、800字くらいなら1秒で入力することができました。速すぎて実際にちゃんと実行しているのかも分かりませんでした。
import pyautogui as pgui
from time import sleep
if __name__ == '__main__':
print('プログラムを5秒待ってから実行します')
sleep(5)
pgui.write('abcdefgh' * 100)
さいごに
今回はpguiの超高速化について考えました。
1秒に100打よりも圧倒的に速い入力を実現できたと思います。
ただし自己責任です。
- 前の記事
イチから始める30日HSK 2020.07.24
- 次の記事
フォロワー20人を21人にするラクな方法 2020.07.27