python module keep crashing - python-3.x

I am trying to create a doorbell with a raspberry pi zero. When I press the button it will send a picture to telegram. The module works but, after a few pressed the button the module crash.
and see an error in terminal:
* Error in `python3': double free or corruption (out): 0x01f306e8 *
or I get this error:
python3: malloc.c:2406: sysmalloc: Assertion `(old_top == initial_top
(av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE &&
prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) ==
0)' failed.
I hope somebody know how to fix the problem
thanks alot!
python
import time
import random
import datetime
import telepot
from telepot.loop import MessageLoop
from picamera import PiCamera
import pygame
from settings import getstring
import RPi.GPIO as GPIO
camera = PiCamera()
bot = telepot.Bot('TOKEN')
ring = 'tones/doorbell.mp3'
pin = 22
pressed = 0
pygame.mixer.init()
pygame.mixer.music.load(ring)
def sendpic(chat_id):
camera.resolution = (1024, 768)
camera.capture('snapshots/test.jpg')
photo = open('snapshots/test.jpg', 'rb')
bot.sendPhoto(chat_id, photo)
def handle(msg):
chat_id = msg['chat']['id']
command = msg['text']
print('Got command: %s' % command)
if command == '/roll':
bot.sendMessage(chat_id, random.randint(1,6))
elif command == '/time':
bot.sendMessage(chat_id, str(datetime.datetime.now()))
pygame.mixer.music.play()
sendpic(chat_id)
MessageLoop(bot, handle).run_as_thread()
print('I am listening ...')
# Define GPIO -pins as standard
GPIO.setmode(GPIO.BCM)
# Define pin X as input and enable internal resistors
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# function for button press
while True:
input_state = GPIO.input(pin)
if input_state == False:
pressed = 1
else:
if pressed == 1:
print('Someone at the door.')
pygame.mixer.music.play()
pressed = 0
while 1:
time.sleep(10)

Related

How to break countdown with keyboard in python3?

In the middle of some process I have a pause with countdown (for loop with time.sleep(1) inside). I'd like to be able to break it with keyboard to be able to continue earlier than countdown got finished.
Is it possible with python3 (cross-platform without Linux root access)? Can I get some information about key pressed in this case ?
Related to this question: Use getch in while (1) python
Solution: use kbhit() and getch(): https://docs.python.org/3.10/library/msvcrt.html#console-i-o
Working example:
import msvcrt
from time import sleep
def a():
for n in range(10):
if msvcrt.kbhit():
return msvcrt.getch()
sleep(1)
Note that it has a reaction delay of up to 1 second
Here is my "cross-platform" very simplified solution.
def my_sleep(wait_sec):
current_platform = platform.system()
if current_platform == "Windows":
import msvcrt
elif current_platform == "Linux":
import termios
from select import select
# save the terminal settings
fd = sys.stdin.fileno()
new_term = termios.tcgetattr(fd)
old_term = termios.tcgetattr(fd)
# switch to normal terminal
def set_normal_term():
termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)
# switch to unbuffered terminal
def set_curses_term():
termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)
def kbhit():
dr, dw, de = select([sys.stdin], [], [], 0)
return dr != []
set_curses_term()
# new terminal setting unbuffered
new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)
set_curses_term()
for sec_left in range(wait_sec, 0, -1):
if current_platform == 'Windows':
if msvcrt.kbhit():
# print(f':: {msvcrt.getch()}')
break
elif current_platform == 'Linux':
if kbhit():
ch = sys.stdin.read(1)
# print(f':: {ch}')
break
print(sec_left)
time.sleep(1)
if current_platform == "Linux":
set_normal_term()

Multi - threading click macro / click recorder

I am working on a script that will listen to keystrokes till the 'q' button is pressed, afterwards it should stop the script and print out the mouse positions that were saved in 2 seconds intervals. I can't manage the threads and I am still learning this topic. Each time I run the code nothing happens but the process is running:
from pynput.keyboard import Listener
import pyautogui
from multiprocessing import Process
import time
mouse_positions = []
def func1():
while True:
time.sleep(2)
mouse_positions.append(pyautogui.position())
cordinates = []
quit_status = False
keystrokes = []
def on_press(key):
if "q" in str(key) :
print('q was pressed!')
exit("Stopped running")
#qprint(key)
keystrokes.append(key)
print(keystrokes)
#print(keystrokes)
if __name__ == '__main__':
p1 = Process(target=func1)
p1.start()
p1.join()
with Listener(on_press=on_press) as listener: # Create an instance of Listener
listener.join() # Join the listener thread to the main thread to keep waiting for keys
EDIT :
To anyone intrested, here is a click macro I built, script I built previously was more like mouse capture movement. The script below will record your mouse clicks and afterwards will replay them. Much better.
from pynput.keyboard import Listener
import pyautogui
from pynput import mouse
import time
x_pos = []
y_pos = []
both_pos = []
pressed_key = None
def on_click(x, y, button, pressed):
if pressed:
#print ("{0} {1}".format(x,y))
print(pressed_key)
if pressed_key == "1":
both_pos.append("{0}".format(x,y))
both_pos.append("{1}".format(x,y))
#print("test" + x_pos + y_pos)
print (x_pos + y_pos)
else:
pass
if pressed_key == 'q':
return False
def on_press(key):
print("To replay press 'q' , to stop recording press '1' , to record again press '1' .")
global pressed_key
if 'Key.esc' in str(key):
return False
if '1' in str(key):
pressed_key= None if pressed_key == '1' else '1'
if 'q' in str(key):
print("Replaying actions")
print(str(len(both_pos)))
for point in range(0,len(both_pos),2):
time.sleep(3)
print("clicking")
pyautogui.click(x=int(both_pos[point]),y=int(both_pos[point+1]))
print("done...")
return False
mouse_listener = mouse.Listener(on_click=on_click)
mouse_listener.start()
with Listener(on_press=on_press) as listener: # Create an instance of Listener
listener.join()
#print(mouse_listener.mouse_positions)
Hi you can use threading module.
I have created class MouseListener which inherit from threading.Thread class. Everything what you want to run put into run method. As thread stopper I used still_run attribute.
When you are typing, I pass to on_press function pressed key and mouse_listener. If q is pressed I set mouse_listener.still_run to False, what leads to stop the mouse listener.
mouse_positions I moved from global scope to MouseListener.
import threading
from pynput.keyboard import Listener
import pyautogui
import time
class MouseListener(threading.Thread):
still_run = True
mouse_positions = []
def run(self):
self.func()
def func(self):
while self.still_run:
time.sleep(2)
self.mouse_positions.append(pyautogui.position())
print(self.mouse_positions)
coordinates = []
quit_status = False
keystrokes = []
def on_press(key, mouse_listener):
print('kp')
if "q" in str(key):
print('q was pressed!')
mouse_listener.still_run = False
print(key)
exit("Stopped running")
keystrokes.append(key)
print(keystrokes)
print(keystrokes)
if __name__ == '__main__':
mouse_listener = MouseListener()
mouse_listener.start()
with Listener(on_press=lambda key: on_press(key, mouse_listener)) as listener: # Create an instance of Listener
listener.join()
print(mouse_listener.mouse_positions)

Menu in RPi Python choice and run two subprocess and kill it

RPi + Python3. I need a menu with 4 options.
When option 'AA' -> blink_LED33, option 'BB' -> blink_LED35, option 'CC' -> stop_blink _LED33, option 'DD' -> stop_blink_LED35
I need a while loop in blinkLED33.py and blinkLED35.py
blinkLED33.py
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BOARD)
GPIO.setup(33, GPIO.OUT, initial=GPIO.LOW)
while True:
GPIO.output(33, GPIO.HIGH)
print("ON_33.")
sleep(1)
GPIO.output(33, GPIO.LOW)
print("OFF_33.")
sleep(1)
blinkLED35.py
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BOARD)
GPIO.setup(35, GPIO.OUT, initial=GPIO.LOW)
while True:
GPIO.output(35, GPIO.HIGH)
print("ON_35.")
sleep(1)
GPIO.output(35, GPIO.LOW)
print("OFF_33.")
sleep(1)
menu.py
import sys
import time
import subprocess
import os
(...)
class My_Keyboard:
(...)
if __name__ == "__main__":
(...)
if clickkey == 'AA':
#exec(open("blinkLED33.py").read());
#subprocess.run(["blinkLED33.py"])
#os.system('python blinkLED33.py')
p1 = subprocess.Popen(['python', 'blinkLED33.py'])
if clickkey == 'BB':
#exec(open("blinkLED35.py").read());
#subprocess.run(["blinkLED35.py"])
#os.system('python blinkLED35.py')
p2 = subprocess.Popen(['python', 'blinkLED35.py'])
if clickkey == 'CC':
p1.terminate()
if clickkey == 'DD':
p2.terminate()
(...)
Change python for python3.
p1 = subprocess.Popen(['python3', 'blinkLED33.py'])
p2 = subprocess.Popen(['python3', 'blinkLED35.py'])

How to pause/interupt with keyboard

I'm using the following script to play all the WAV files in the current path. I will be modifying it to print the output of some text files. That part is easy.
Need to know how/where in the loop of playing the WAV files, where to add some code to pause/interupt the execution of the code with the keyboard.
#!/usr/bin/python3
import vlc
import time
import glob
wav_files = glob.glob("*.wav")
instance=vlc.Instance(["--no-sub-autodetect-file"])
# You should not recreate a player for each file, just reuse the same
# player
player=instance.media_player_new()
for wav in wav_files:
player.set_mrl(wav)
player.play()
playing = set([1,2,3,4])
time.sleep(5) #Give time to get going
duration = player.get_length() / 1000
mm, ss = divmod(duration, 60)
print("Playing", wav, "Length:", "%02d:%02d" % (mm,ss))
while True:
state = player.get_state()
if state not in playing:
break
continue
Steal the getch right out of vlc.py
I've added the windows option, as you didn't specify an OS.
#!/usr/bin/python3
import vlc
import time
import glob
import sys
import termios, tty
try:
from msvcrt import getch # try to import Windows version
except ImportError:
def getch(): # getchar(), getc(stdin) #PYCHOK flake
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
return ch
wav_files = glob.glob("*.wav")
print("Play List")
for f in wav_files:
print(f)
instance=vlc.Instance(["--no-sub-autodetect-file"])
# You should not recreate a player for each file, just reuse the same
# player
player=instance.media_player_new()
for wav in wav_files:
player.set_mrl(wav)
player.play()
playing = set([1,2,3,4])
time.sleep(1) #Give time to get going
duration = player.get_length() / 1000
mm, ss = divmod(duration, 60)
print("Playing", wav, "Length:", "%02d:%02d" % (mm,ss))
while True:
state = player.get_state()
if state not in playing:
break
k = getch()
if k in ["N","n"]:#Next
player.stop()
break
elif k in ["Q","q"]:#Quit
player.stop()
sys.exit()
break
elif k == " ":#Toggle Pause
player.pause()
else:
print("[Q - Quit, N - Next, Space - Pause]")
continue

can't open device: Too many open files Error

Hi I Have Terrible codes in Raspberry Pi 3. I am trying to read 4 RC522 Module and i can do it. But after few minutes I got "can't open device: Too many open files" Error, and my while loop terminated.
I didnt share all the functions. I guess important part is while loop. I create instance in every loop. I guess this is big mistake. I cant add delay. I tried assign null to my object but i got still same error. My Codes are Below
Note: I have 4 SPI address, and i create instance with them.
#!/usr/bin/env python
# -*- coding: utf8 -*-
import time
import sys
import os
import RPi.GPIO as GPIO
import MFRC522
import signal
from time import gmtime, strftime
from time import sleep
import requests
#import xml.etree.ElementTree as ET
#import xmltodict, json
from lxml import objectify
from bs4 import BeautifulSoup
continue_reading = True
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
GPIO.setup(37, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
global continue_reading
print "Ctrl+C captured, ending read."
continue_reading = False
GPIO.cleanup()
kullanici = "xxxx"
sifre = "xxxx"
birim = "xxxx"
ogrKEY = " "
def end_read(signal,frame):
global continue_reading
print "Ctrl+C captured, ending read."
continue_reading = False
GPIO.cleanup()
# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)
# Create an object of the class MFRC522
#
adresler = ["/dev/spidev0.0", "/dev/spidev0.1", "/dev/spidev1.0","/dev/spidev1.1"]
# Welcome message
print "Welcome to the MFRC522 data read example"
print "Press Ctrl-C to stop."
j = 0
# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:
MIFAREReader = None
pin = 0
if j == 100:
j = 0
i = j % 4
if i == 0:
MIFAREReader = MFRC522.MFRC522(adresler[0], 16)
pin = 15
elif i == 1:
MIFAREReader = MFRC522.MFRC522(adresler[1], 18)
pin = 13
elif i == 2:
MIFAREReader = MFRC522.MFRC522(adresler[2], 33)
pin = 7
else:
MIFAREReader = MFRC522.MFRC522(adresler[3], 31)
pin = 37
# Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
# If a card is found
if status == MIFAREReader.MI_OK:
print "Card detected"
# Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()
# If we have the UID, continue
if status == MIFAREReader.MI_OK:
# print "su okuyucudan okundu" % i
# Print UID
print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])
# This is the default key for authentication
key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
# Select the scanned tag
MIFAREReader.MFRC522_SelectTag(uid)
# Authenticate
status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 10, key, uid)
# Check if authenticated
if status == MIFAREReader.MI_OK:
MIFAREReader.MFRC522_Read(10)
ogrKEY = MIFAREReader.returnOGR()
sonuc = parser(ogrKEY)
if sonuc == True:
openTurnsTile(pin)
else:
sonuc = personelKontrol(ogrKey)
if sonuc == True:
openTurnsTile(pin)
MIFAREReader.MFRC522_StopCrypto1()
else:
print "Authentication error"
j = j + 1
When you create the MFRC522 object it actually calls spi.openSPI() but never closes it. This python library is good for single instance but now that you are dealing with multiple instance where FDs are opened, needs to be closed as well using spi.closeSPI(), else you will get the error "Too many open FDs".
To check how many open FDs are there for your PID.

Resources