Я использую launchctl для запуска демона моего кода py:
launchctl load -w com.bruce2.PicUploaderHelper.plist
Затем я ps aux | grep testpynput
, демон был запущен:
root 65334 0.1 0.2 4350320 37596 ?? Ss 2:52 0:00.44 /usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python /Users/bruce/PicUploaderHelper-macOS/testpynput.py /Users/bruce/PicUploaderHelper-macOS/config2.json
Однако привязка клавиш не работает, но если я использую точно такой же код в iTerm2 (терминальное приложение на macOS), он работает, я имею в виду, что я непосредственно выполняю следующий код в iTerm2:
/usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python /Users/bruce/PicUploaderHelper-macOS/testpynput.py /Users/bruce/PicUploaderHelper-macOS/config2.json
pynput
Я понимаю, что у macOS есть некоторые ограничения ограничения для macOS , по сути, я сначала не добавил iTerm2 в System Preferences
→ Security & Privacy
→ Accessibility
, он даже не работаетЯ выполняю testpynput.py
непосредственно на iTerm2, но после добавления iTerm2 к Accessibility
этот способ работает нормально:
Поэтому я поставил
/usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Resources/Python.app
или
/usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python
в Систему System Preferences
→ Security & Privacy
→ Accessibility
, это так же, как я установил iTerm2 в право доступа ?, но ни один из двух вариантов не работает.
Итак, вы, ребята, знаете, как я могу решить эту проблему?
Я поставлю свой код здесь:
testpynput.py
:
#!/usr/bin/env /usr/local/bin/python3
from pynput import keyboard
from PIL import ImageGrab
import os
import logging
import json
import subprocess
import sys
# The currently active modifiers
current = set()
def read_config():
""" Read config from config.json """
config_file = '/etc/PicUploaderHelper-macOS/config.json'
if len(sys.argv) == 2:
config_file = sys.argv[1]
f = open(config_file, 'r')
text = f.read()
f.close()
return json.loads(text)
# Read config from config.json
config = read_config()
if config['debug'] == 1:
log_dir = "/var/log"
logging.basicConfig(filename=(log_dir + "/key_log.txt"), level=logging.DEBUG, format='%(asctime)s: %(message)s')
def get_key_combination():
""" Get key combinations from config """
tmp_list = []
key_combinations = config['key_combinations']
for items in key_combinations:
s = set()
for item in items:
if len(item) == 1:
ele = keyboard.KeyCode(char=item)
else:
ele = getattr(keyboard.Key, item)
s.add(ele)
tmp_list.append(s)
return tmp_list
def send_notification(notification_type=''):
""" Send notification with applescript """
if notification_type == "":
notification_type = 'success'
notification = config['notification'][notification_type]
title = notification['title']
subtitle = notification['subtitle']
message = notification['message']
notification_script = 'display notification "'+message+'" with title "'+title+'" subtitle "'+subtitle+'"'
applescript_command = "osascript -e '"+notification_script+"'"
# Execute shell by python
subprocess.Popen(applescript_command, shell=True)
def get_image_from_clipboard():
"""" Get image from clipboard """
# Pull image from clipboard
img_obj = ImageGrab.grabclipboard()
if img_obj is None:
return '';
else:
# Define temp dir
tmp_dir = '/var/tmp'
# Get image type from config
img_type = config['img_type']
# Tmp image path
tmp_img = tmp_dir+'/.screenshot_upload_tmp.'+img_type.lower()
# Save the image as jpg to disk
img_obj.save(tmp_img, img_type.upper())
return tmp_img
def upload_image():
""" Upload image to remote server by running shell command """
tmp_img = get_image_from_clipboard()
if tmp_img != '':
# Here goes the upload code, I currently use print instead
print('Uploading image...')
# Send macOS notification
send_notification()
else:
send_notification('no_image')
COMBINATIONS = []
COMBINATIONS = get_key_combination()
def on_press(key):
""" Listen button press event """
if config['debug'] == 1:
logging.info(str(key))
if any([key in COMBO for COMBO in COMBINATIONS]):
current.add(key)
if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
upload_image()
def on_release(key):
""" Listen button release event """
if any([key in COMBO for COMBO in COMBINATIONS]):
current.remove(key)
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
""" start a keyboard listener """
listener.join()
config2.json
:
{
"img_type": "JPEG",
"notification": {
"success": {
"title": "Upload image succeed",
"subtitle": "",
"message": "Markdown link is copied to the cliboard, you can paste now!"
},
"no_image": {
"title": "No image detected",
"subtitle": "",
"message": "No image was detected in the clipboard, please take a screenshot first!"
}
},
"key_combinations": [
["alt", "shift", "u"],
["alt", "shift", "U"]
],
"debug": 1
}
com.bruce2.PicUploaderHelper.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.bruce2.PicUploaderHelper</string>
<key>Program</key>
<string>/Users/bruce/PicUploaderHelper-macOS/testpynput.py</string>
<key>ProgramArguments</key>
<array>
<string>/Users/bruce/PicUploaderHelper-macOS/testpynput.py</string>
<string>/Users/bruce/PicUploaderHelper-macOS/config2.json</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>WorkingDirectory</key>
<string>/Users/bruce/PicUploaderHelper-macOS</string>
<key>StandardErrorPath</key>
<string>/Users/bruce/PicUploaderHelper-macOS/testpynput.log</string>
<key>StandardOutPath</key>
<string>/Users/bruce/PicUploaderHelper-macOS/testpynput.log</string>
</dict>
</plist>
введите com.bruce2.PicUploaderHelper.plist
в /Library/LaunchAgents
, убедитесь, что вам нужно установить для его владельца значение root:wheel
-rw-r--r-- 1 root wheel 894B 3 22 14:41 com.bruce2.PicUploaderHelper.plist
Затем запустите с привилегиями sudo или root:
sudo launchctl load -w com.bruce2.PicUploaderHelper.plist
Это код в файле: PicUploaderHelper-macOS.zip
Python2.7 тоже самое, я пробовал.
macOS: 10.14.1 (18B75)
python2: Python 2.7.15
python3: Python 3.7.2
iTerm2: 3.2.7