Python threads, keylog
Что должно получится в результате?
Запускается программа. Считывает все нажатия клавиш, записывая их например в список(пример ниже, но эта часть не так важна, так как я её уже написал, она исправно работает). Но параллельно, например, каждую минуту включалась нужная функция и весь тот результат(список) записывала, скидывала, сохраняла куда угодно, в общем чтобы включалась функция(функционал так же не столь важен). Как мне подсказали - использовать многопоточность.
пример: ['enter', 'd', 'h', 'F1', 'capslock', 'y'...]
Что не выходит?
Не могу правильно разобраться и структурировать код чтобы работало правильно.
Какая ошибка?
После запуска python main.py функция start() - опускается, поток не запускается соответственно функция send_data() которую должен был запустить поток - игнорируется.
Код?
from threading import Thread
from win32api import LoadKeyboardLayout
import keyboard
import time
class App:
def __init__(self):
self.list = list()
keyboard.hook(self.key_logger)
keyboard.wait()
def start(self):
th1 = Thread(target=self.send_data(), args=())
th1.start()
time.sleep(4)
def key_logger(self, btn): # функция которая бы сохраняла нажатия в список
res = btn.name
print(res)
def send_data(self): # функция которая бы отсылала нажатия например в файл
print('i am here')
if __name__ == '__main__':
LoadKeyboardLayout('00000409', 1) # устанавливаем англ. язык
App().start()
Очень буду благодарен если поможете с кодом и объяснениями.
P.S. Сори если для кого-то этот вопрос слишком легкий и кажется тупым.
Ответы (1 шт):
Я не пользовался модулями, которые Вы используете здесь, однако, исходя из документации, могу предположить следующее:
В конструкторе класса Вы вызываете метод keyboard.wait(), который, согласно документации, блокирует выполнение навсегда, если ему не переданы параметры. Таким образом, получаем: в данной строке App().start() сначала вызывается конструирующий метод __init__ класса App. Т.к. в этом методе содержится вызов блокирующего метода, выполнение программы блокируется, а значит вызов метода start() не происходит, т.к. конструктор ещё не вернул управление и объект до конца не создан.
Решение: убрать блокирующий метод из конструктора.
Далее, хочу ещё отметить, что при передаче в конструктор класса Thread функции, которая должна выполняться в потоке, Вы допустили ошибку, поставив скобки после неё. Вот здесь: th1 = Thread(target=self.send_data(), args=()) после send_data скобки не нужны. Когда Вы ставите скобки после имени функции, Вы производите её вызов, а значит аргументу target в данном случае будет присвоено то, что вернул Ваш метод send_data, а там должен быть сам метод, а не его возвращаемое значение. В Вашем случае метод у Вас вызовется ДО создания потока, а поток не создастся, т.к. не получит в качестве target корректного имени функции.
Решение: th1 = Thread(target=self.send_data, args=())