Tweepy Stream client Termination on button click - python

ive been trying to create a stream client using tweepy to fetch new tweets under a user-given hashtag. I've managed to achieve this using the following code successfully.
import tweepy
class IDPrinter(tweepy.StreamingClient):
def on_tweet(self,tweet):
#now = datetime.now()
#current_time = now.strftime("%H:%M:%S")
#print("Current Time =", current_time)
print(f"{tweet.id} \n {tweet.created_at} \n {tweet.author_id} \n {tweet.text}")
#https://docs.tweepy.org/en/v3.4.0/streaming_how_to.html
def on_error(self, tweet_code):
if tweet_code == 420:
return False
def cleanUP(self,printer):
print("test")
rule_ids = []
rules = printer.get_rules()
if str(rules).find("id") == -1:
print(rules)
return
else:
for rule in rules.data:
rule_ids.append(rule.id)
if(len(rule_ids) > 0):
printer.delete_rules(rule_ids)
print("rules have been reset")
else:
print("no rules to delete")
def Caller(self,value,printer):
#print("test")
printer.add_rules(tweepy.StreamRule(f"#{value} lang:en -is:retweet"))
printer.filter(expansions="author_id", tweet_fields="created_at")
But I want the user to be able to stop the stream of new tweets whenever he wants to. Ive been testing the following code but I can't get the tweepy stream loop to terminate on button click. This is my current attempt but I can't understand why is not working.
def on_button_clicked(event):
global break_cicle
break_cicle = False
print("Button pressed: break_cicle:", break_cicle)
class IDPrinter(tweepy.StreamingClient):
def on_tweet(self,tweet):
print(f"{tweet.id} \n {tweet.created_at} \n {tweet.author_id} \n {tweet.text}")
#https://docs.tweepy.org/en/v3.4.0/streaming_how_to.html
def on_error(self, tweet_code):
if tweet_code == 420:
return False
def cleanUP(self,printer):
print("test")
rule_ids = []
rules = printer.get_rules()
if str(rules).find("id") == -1:
print(rules)
return
else:
for rule in rules.data:
rule_ids.append(rule.id)
if(len(rule_ids) > 0):
printer.delete_rules(rule_ids)
print("rules have been reset")
else:
print("no rules to delete")
def Call(self,value,printer):
while break_cicle:
button.on_click(on_button_clicked)
printer.add_rules(tweepy.StreamRule(f"#{value} lang:en -is:retweet"))
printer.filter(expansions="author_id", tweet_fields="created_at")
time.sleep(1)
printer = IDPrinter("bearer key")
printer.cleanUP(printer)
hashtag = input("Give a hashtag: ")
button = widgets.Button(description="STOP!")
output = widgets.Output()
display(button, output)
break_cicle = True
button.on_click(on_button_clicked)
threading.Thread(target=printer.Call(hashtag,printer)).start()
basically i tried to create a button which on event click will change the variable break_circle and terminate the while loop onside def call.

Related

Below is code is for a soundboard attached to a 10-key. The sound loops when I press a key- how do I make it only play once?

Please let me know if I need to provide more info. This is for a soundboard setup- it's a raspberry-pi 4 with an attached 10-key. It works insofar as it plays the correct sound when I press a key, but the sound plays on a loop.
I see a section that says "Play an audio track indefinitely" but I have no idea if this is what I need to edit. Is this correct?
#!/usr/bin/python3
import os
import sys
import vlc
import time
inputs = ['\'1\'', '\'2\'', '\'3\'', '\'4\'', '\'5\'', '\'6\'', '\'7\'', '\'8\'', '\'9\'', '\'0\'']
special = ['\'*\'', '\'+\'', '\'-\'', '\'+\'', '\'/\'', '\'.\'']
instance = vlc.Instance('--input-repeat=999999')
player = instance.media_player_new()
def loadPresets():
''' Get all the Presets in the current directory '''
l = []
for file in os.listdir(os.getcwd()):
if file.endswith(".preset"):
print("Preset Found:", os.path.join(os.getcwd(), file))
l.append(os.path.join(os.getcwd(), file))
return l
def getPresetTracks(preset):
''' Get all the links inside of a preset track '''
l = []
with open(preset) as file:
for line in file:
# Need to get rid of those pesky \n's
print(str(len(l)) + ': ', line[:-1])
l.append(line[:-1])
if len(l) < 10:
print("Too little links. Cannot correctly populate.")
l = []
elif len(l) > 10:
print("Too many links. Cannot correctly populate.")
l = []
return l
def isYouTubeAudio(link):
import re
if re.match(r'http[s]:\/\/www\.youtube\.com/watch\?v=([\w-]{11})', link) == None:
return False
else:
return True
def getYouTubeAudioTrack(link):
''' Get Audio track of a link '''
import pafy
video = pafy.new(link)
bestaudio = video.getbestaudio()
# print(bestaudio.url)
return bestaudio.url
def playQuick(num):
''' Make quick sound '''
l = ['up.mp3', 'down.mp3', 'preset_change.mp3', 'startup.mp3']
s = instance.media_new(os.path.join(os.getcwd(), l[num]))
player.set_media(s)
player.play()
if num == 3:
time.sleep(4)
else:
time.sleep(1)
player.stop()
def switchPresets(readyPresets):
playQuick(2)
print("Ready to swap the preset. Loaded presets:")
i = 0
for link in readyPresets:
print(i, "-", link)
i += 1
newPreset = input("What would you like your preset to be?: ")
if newPreset.isdigit() and int(newPreset) < len(presetList):
# Number preset. We're goood
numPre = int(newPreset)
print("New Preset: ", numPre)
playQuick(0)
return numPre
else:
# It's a character. Stop
print("Invalid preset. Skipping.")
playQuick(1)
return None
def playTrack(track):
''' Play an audio track indefinetly. Also awaits response so it can detect a change in information '''
from readchar import readkey
# Load and add media file
media = instance.media_new(track)
player.set_media(media)
# Play
player.play()
# Pause before getting the status, to update everything
print(str(player.get_state()) + " ", end='\r')
sys.stdout.flush()
time.sleep(1)
print(str(player.get_state()) + " ")
if __name__ == '__main__':
presetList = loadPresets()
preset = getPresetTracks(presetList[0])
# Start Up and initial setup
active = False
playQuick(3)
import readchar
keyInput = '\'0\''
# Start Main loop
print("Ready for input")
while keyInput not in inputs or keyInput not in special:
keyInput = repr(readchar.readkey())
# Sanitize input
if keyInput in inputs:
# Play sound
santized = int(keyInput[1])
player.stop()
active = True
# print(preset[santized])
if isYouTubeAudio(preset[santized]):
playTrack(getYouTubeAudioTrack(preset[santized]))
else:
playTrack(preset[santized])
# Special Characters
elif keyInput == special[0]: # '\'*\'
# Preset
active = False
player.stop()
np = switchPresets(presetList)
if np != None:
preset = getPresetTracks(presetList[np])
elif keyInput == special[1]: # '\'+\''
# Play/Pause. +
if active:
player.pause()
active = False
else:
player.play()
active = True
elif keyInput == special[2]: # '\'-\''
pass
elif keyInput == '\'x\'':
# End case
exit()

Alexa Skills Kit "Skill execution returned an exception for requestId" error

I'm very new to the Alexa Skills Kit. And I`ve been trying to make a simple music player skill on a web hosted server in https://www.pythonanywhere.com. When I try to make a request a
"SKILL_ENDPOINT_ERROR"
is captured in the device log with the following description:
"Skill execution returned an exception for requestId
amzn1.echo-api.request.e08ec414-0a30-4e95-87bb-28f315c8d4eb".
This is my skill request handler code:
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.utils import is_intent_name, is_request_type
from flask import Flask
from flask_ask_sdk.skill_adapter import SkillAdapter
from ask_sdk_model.ui import SimpleCard
app = Flask(__name__)
sb = SkillBuilder()
#VARIABLES
Current_song = ""
silent_mode = False
"""/////////////////////////
// Request Handlers //
////////////////////////"""
#Launch request
#sb.request_handler(can_handle_func=is_request_type("LaunchRequest"))
def launch_request_handler(handler_input):
speech_text = "What do you wish to play?"
return handler_input.response_builder.speak(speech_text).set_card(
SimpleCard("Hello World", speech_text)).set_should_end_session(
False).response
#Session Ended Request
#sb.request_handler(can_handle_func=is_request_type("SessionEndedRequest"))
def session_ended_request_handler(handler_input):
return handler_input.response_builder.response
"""/////////////////////////
// ASK Intent Handlers //
////////////////////////"""
#Help Intent
#sb.request_handler(can_handle_func=is_intent_name("AMAZON.HelpIntent"))
def help_intent_handler(handler_input):
speech_text = "You can ask me to play something on your server!"
return handler_input.response_builder.speak(speech_text).ask(
speech_text).set_card(SimpleCard(
"Wha can I do", speech_text)).response
#Stop Skill intent
#sb.request_handler(
can_handle_func=lambda handler_input:
is_intent_name("AMAZON.CancelIntent")(handler_input) or
is_intent_name("AMAZON.StopIntent")(handler_input))
def cancel_and_stop_intent_handler(handler_input):
speech_text = "Goodbye!"
return handler_input.response_builder.speak(speech_text).set_card(
SimpleCard("Hello World", speech_text)).response
#FallBack Intent
#sb.request_handler(can_handle_func=is_intent_name("AMAZON.FallbackIntent"))
def fallback_handler(handler_input):
speech = (
"I can't help you with that. "
"You can ask me to play music!")
reprompt = "You can ask me to play music!"
handler_input.response_builder.speak(speech).ask(reprompt)
return handler_input.response_builder.response
"""/////////////////////////
// Bot Intent Handlers //
////////////////////////"""
#Play Intent
#sb.request_handler(can_handle_func=is_intent_name("PlayIntent"))
def Play_intent_handler(handler_input):
song_value = handler_input.request_envelope.request.intent.slots["music"].value
if song_value:
speak_output = "Now playing {} on our server.".format(song_value)
Current_song = song_value
else:
speak_output = "I dont know what you want to play."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).ask(speak_output).set_card(SimpleCard("Playing {}...".format(song_value), speak_output))
return handler_input.response_builder.response
#Pause Intent
#sb.request_handler(can_handle_func=is_intent_name("PauseIntent"))
def Pause_intent_handler(handler_input):
speak_output = "Paused."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Pause", speak_output))
return handler_input.response_builder.response
#Loop Intent
#sb.request_handler(can_handle_func=is_intent_name("LoopIntent"))
def Loop_intent_handler(handler_input):
speak_output = "Song loop enabled."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Loop", speak_output))
return handler_input.response_builder.response
#Restart Intent
#sb.request_handler(can_handle_func=is_intent_name("RestartIntent"))
def Restart_intent_handler(handler_input):
speak_output = "Restarting current song"
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Restart", speak_output))
return handler_input.response_builder.response
#Resume Intent
#sb.request_handler(can_handle_func=is_intent_name("ResumeIntent"))
def Resume_intent_handler(handler_input):
speak_output = "Resumed."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Resume", speak_output))
return handler_input.response_builder.response
#Now Playing Intent
#sb.request_handler(can_handle_func=is_intent_name("NowPlayingIntent"))
def Now_Playing_intent_handler(handler_input):
if Current_song:
speak_output = "Now playing {}.".format(Current_song)
else:
speak_output = "There is nothing playing at the moment"
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Now Playing", speak_output))
return handler_input.response_builder.response
#Print Intent
#sb.request_handler(can_handle_func=is_intent_name("PrintIntent"))
def Print_intent_handler(handler_input):
speak_output = "Printed."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Print", speak_output))
return handler_input.response_builder.response
#Remove Number Intent
#sb.request_handler(can_handle_func=is_intent_name("RemoveNumIntent"))
def Remove_Num_intent_handler(handler_input):
num_value = handler_input.request_envelope.request.intent.slots["MusicNum"].value
if num_value:
speak_output = "Removed song number {} from queue".format(num_value)
else:
speak_output = "There is no song in number {}".format(num_value)
if silent_mode == False:
handler_input.response_builder.speak(speak_output).ask(speak_output).set_card(SimpleCard("Remove", speak_output))
return handler_input.response_builder.response
#Remove Position Intent
#sb.request_handler(can_handle_func=is_intent_name("RemovePosIntent"))
def Remove_Pos_intent_handler(handler_input):
pos_value = handler_input.request_envelope.request.intent.slots["MusicPos"].value
if pos_value:
speak_output = "Removed {} song from queue.".format(pos_value)
else:
speak_output = "There is no {} song in queue.".format(pos_value)
if silent_mode == False:
handler_input.response_builder.speak(speak_output).ask(speak_output).set_card(SimpleCard("Remove", speak_output))
return handler_input.response_builder.response
#Remove All Intent
#sb.request_handler(can_handle_func=is_intent_name("RemoveALLIntent"))
def Remove_All_intent_handler(handler_input):
speak_output = "All songs removed from queue"
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Remove", speak_output))
return handler_input.response_builder.response
#Back Intent
#sb.request_handler(can_handle_func=is_intent_name("BackIntent"))
def Back_intent_handler(handler_input):
speak_output = "Went back a song in queue."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Back", speak_output))
return handler_input.response_builder.response
#Skip Intent
#sb.request_handler(can_handle_func=is_intent_name("SkiptIntent"))
def Skip_intent_handler(handler_input):
speak_output = "Skipped."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Skip", speak_output))
return handler_input.response_builder.response
#Shuffle Intent
#sb.request_handler(can_handle_func=is_intent_name("ShuffleIntent"))
def Shuffle_intent_handler(handler_input):
speak_output = "Shuffled queue."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Shuffle", speak_output))
return handler_input.response_builder.response
#Skip to number Intent
#sb.request_handler(can_handle_func=is_intent_name("SkipToNumIntent"))
def Skip_To_Num_intent_handler(handler_input):
num_value = handler_input.request_envelope.request.intent.slots["MusicNum"].value
if num_value:
speak_output = "Skiped to song number {}.".format(num_value)
else:
speak_output = "There is no {} song in queue.".format(num_value)
if silent_mode == False:
handler_input.response_builder.speak(speak_output).ask(speak_output).set_card(SimpleCard("Skip To", speak_output))
return handler_input.response_builder.response
#Skip to position Intent
#sb.request_handler(can_handle_func=is_intent_name("SkipToPosIntent"))
def Skip_To_Pos_intent_handler(handler_input):
pos_value = handler_input.request_envelope.request.intent.slots["MusicPos"].value
if pos_value:
speak_output = "Skiped to {} song in queue.".format(pos_value)
else:
speak_output = "There is no {} song in queue.".format(pos_value)
if silent_mode == False:
handler_input.response_builder.speak(speak_output).ask(speak_output).set_card(SimpleCard("Skip To", speak_output))
return handler_input.response_builder.response
#Loop queue Intent
#sb.request_handler(can_handle_func=is_intent_name("LoopQueueIntent"))
def Loop_Queue_intent_handler(handler_input):
speak_output = "Looped queue."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Loop Queue", speak_output))
return handler_input.response_builder.response
#Silent Mode Intent
#sb.request_handler(can_handle_func=is_intent_name("SilentModeIntent"))
def Silent_Mode_intent_handler(handler_input):
silent_mode = True
return handler_input.response_builder.response
#Disconnect Intent
#sb.request_handler(can_handle_func=is_intent_name("DisconnectIntent"))
def Disconnect_intent_handler(handler_input):
speak_output = "Disconnected."
if silent_mode == False:
handler_input.response_builder.speak(speak_output).set_card(SimpleCard("Disconnect", speak_output))
return handler_input.response_builder.response
sa = SkillAdapter(skill=sb.create(), skill_id="amzn1.ask.skill.e5e95d9a-6047-41aa-96f1-879b88421432", app=app)
"""/////////////////////////
// Exception Handlers //
////////////////////////"""
#Exception Handler
#sb.exception_handler(can_handle_func=lambda i, e: True)
def all_exception_handler(handler_input, exception):
speech = "Sorry, there was some problem. Please try again!!"
handler_input.response_builder.speak(speech).ask(speech)
return handler_input.response_builder.response
#app.route("/")
def invoke_skill():
return sa.dispatch_request()
I first assumed the problem was that I didn't have an Exeption Handler, but there was no change in the result since I implemented one.
Has anyone solved this issue or has any idea what my code is missing?

Not able to break from loop while running a Telegram Bot

I am creating a Telegram Bot using pyTelegramBotAPI that sends real-time updates of ongoing cricket matches. I want to break the loop whenever the user enters the "/stop" command. I've looked up various sources and also tried several methods to achieve the same but all in vain. The loop continues to iterate. The closest I've reached is by exiting the program by raising an error. Also, while inside the loop, the getUpdates method always returns an empty list. I've also written an issue for the same on GitHub.
def loop(match_url):
prev_info = ""
flag = 1
#continuously fetch data
while flag:
response = requests.get(match_url)
info = response.json()['score']
#display only when the score updates
if str(info) != prev_info:
prev_info = str(info)
send_msg(info)
else:
pass
send_msg(info)
#this handler needs to be fixed
#bot.message_handler(commands=['stop', 'end'])
def stop(message):
#code to break the loop
flag = 0
return
Since this was not working, I willingly used this wrong method:
while flag:
response = requests.get(match_url)
info = response.json()['score']
if str(info) != prev_info:
prev_info = str(info)
send_msg(info)
else:
pass
send_msg(info)
#bot.message_handler(commands=['stop', 'end'])
def stop(message):
bot.polling.abort = True #an arbitrary function that raises error and exits the program
Here's the whole code. I've also added my GitHub link of this code:
import requests, json, telebot
token = <TOKEN>
bot = telebot.TeleBot(token)
#parsing data from cricapi.com
def live_matches():
#here I'm using the KEY obtained from cricapi.com
curr_matches_url = "https://cricapi.com/api/cricket?apikey=<KEY>"
curr_matches = requests.get(curr_matches_url)
match_data = curr_matches.json()['data']
global unique_id_arr, score_arr
unique_id_arr, score_arr = [], []
match_details = ""
for i in match_data:
unique_id_arr.append(i["unique_id"])
for i in range(len(match_data)):
score_arr.append(match_data[i]["title"])
score_arr[i] += "\n"
match_details += str(i+1) + ". "
match_details += score_arr[i]
send_msg(match_details)
def send_msg(msg):
url2 = 'https://api.telegram.org/bot'+token+'/sendMessage'
data = {'chat_id': chat_id, 'text': msg}
requests.post(url2, data).json()
#bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
bot.reply_to(message, "Howdy, how are you doing?")
global chat_id
chat_id = message.chat.id
msg = bot.reply_to(message, "Welcome to test project\nEnter the match number whose updates you want to receive")
live_matches()
bot.register_next_step_handler(msg, fetch_score)
def fetch_score(message):
chat_id = message.chat.id
match_no = message.text
#checking if the number entered is present in the displayed list
if not match_no.isdigit():
msg = bot.reply_to(message, 'Error1!\nSelect a no. from the above list only')
return bot.register_next_step_handler(msg, fetch_score)
elif 1 <= int(match_no) <= len(score_arr):
unique_id = unique_id_arr[int(match_no)-1]
global match_url
#get the data of the desired match
match_url = "https://cricapi.com/api/cricketScore?unique_id="+unique_id+"&apikey=<KEY>"
loop(match_url)
else:
msg = bot.reply_to(message, "Error2!\nSelect a no. from the above list only")
return bot.register_next_step_handler(msg, fetch_score)
def loop(match_url):
prev_info = ""
flag = 1
#continuously fetch data
while flag:
response = requests.get(match_url)
info = response.json()['score']
#display only when the score updates
if str(info) != prev_info:
prev_info = str(info)
send_msg(info)
else:
pass
send_msg(info)
#this handler needs to be fixed
#bot.message_handler(commands=['stop', 'end'])
def stop(message):
#an arbitrary function that raises error and then exits
bot.polling.abort = True
bot.polling()
"""
#currently not using
def receive_msg():
url1 = 'https://api.telegram.org/bot'+token+'/getUpdates'
response = requests.get(url1)
text = response.json()['result']
if len(text) > 0:
user_msg = text[-1]['message']['text']
return user_msg
return text
"""
You are using telebot(pyTelegramBotAPI) package in the wrong way:
Why did you create your own function send_msg where there is already send_message method in telebot exists?
You are redeclaring your "stop" handler in the loop, which is wrong!
My suggestion to you is to learn how to use the pyTelegramBotAPI properly!
Here is a demonstration code, that solves your problem:
import telebot
from time import sleep
bot = telebot.TeleBot(BOT_TOKEN)
flag = 1
#bot.message_handler(commands=['loop'])
def loop(msg):
while flag:
bot.send_message(msg.chat.id, "ping")
sleep(1)
#bot.message_handler(commands=['stop', 'end'])
def stop(msg):
global flag
flag = 0
bot.send_message(msg.chat.id, "stopped")
bot.polling(none_stop=True)
Explanation:
Declared flag as a global variable and set it to 1
"loop" handler for starting the loop that sends you "ping" message every second
"stop" handler that changes flag to 0, which terminates your running loop

IRC Twitch somehow start ignoring messages

I'm just trying to make a 'Twitch Plays' game. I used a tutorial for making Twitch Plays games. I need to re-run this code every five minutes as it ignores the messages. I'm making Threes game on Scratch. I checked for all the possible bugs and it works very well. This game is based on moving tiles that contain numbers on them. Any suggestions regarding the IRC twitch ignoring all messages will be highly appreciated.
The code is shown here below.
import socket
import pyautogui
import time
SERVER = "irc.twitch.tv"
PORT = 6667
PASS = "oauth:fz5kp09su0lz46vnos78sklvpjnu6l"
BOT = "TwitchBot"
CHANNEL = "olejika2016"
OWNER = "olejika2016"
message = ""
irc = socket.socket()
irc.connect((SERVER,PORT))
irc.send(( "PASS "+PASS+"\n"+
"NICK "+BOT+"\n"+
"JOIN #"+CHANNEL+"\n").encode())
def twitch():
def joinchat():
loading = True
while loading:
readbuffer_join = irc.recv(1024)
readbuffer_join = readbuffer_join.decode()
for line in readbuffer_join.split("\n")[0:-1]:
# print(line)
loading = loadingComplete(line)
def loadingComplete(line):
if ("End of /NAMES list" in line):
print("Bot has joined "+CHANNEL+"'s channel")
sendMessage(irc, "Chat Room Joined")
return False
else:
return True
def sendMessage(irc, message):
messageTemp = "PRIVMSG #" + CHANNEL + " :" + message
irc.send((messageTemp+"\n").encode())
def getUser(line):
separate = line.split(":", 2)
user = separate[1].split("!",1)[0]
return user
def getMessage(line):
global message
try:
message = (line.split(":",2))[2]
except:
message = ""
return message
joinchat()
while True:
try:
readbuffer = irc.recv(1024).decode()
except:
readbuffer = ""
for line in readbuffer.split("\r\n"):
if line == "":
continue
else:
# print("2;"+line)
user = getUser(line)
message = getMessage(line)
print(user+":"+message)
def writeUser():
time.sleep(0.1)
pyautogui.typewrite(user)
pyautogui.press('enter')
if message.lower() == "w":
pyautogui.press('up')
writeUser()
if message.lower() == "s":
pyautogui.press('down')
writeUser()
if message.lower() == "a":
pyautogui.press('left')
writeUser()
if message.lower() == "d":
pyautogui.press('right')
writeUser()
else:
pass
user = ''
message = ''
twitch()
for line in readbuffer.split("\r\n"):
if line == "":
continue
elif "PING" is line and Console(line):
msgg = "PONG tml.twitch.tv\r\n".encode()
irc.send(msgg)
print(msgg)
continue
else:
user = getUser(line)
message = getMessage(line)
print(user+":"+message)

Python: print function hang when printing global list of objects

I'm currently writing a Python Telegram bot which is used to monitor Raspi IOs and send messages to a channel. So basically it has a function that will update a logging variable llog.
This function (logUpdate), as it's named, will remove entries that are more than 5 mins old. In it, I tried to check the content of the global variable. Upon printing, it just hangs.
This doesn't seem to block any other functionalities of the bot because I can still call out other bot commands.
I don't think it's the bot. It must be some kind of data access problems.
I attach some code snippet below:
#!usr/bin/python
##
### RF Security bot start script
##
##
### Imports
##
import telegram as tg
import telegram.ext as tgExt
import RPi.GPIO as gpio
import time
from datetime import datetime as dt
##
### Common variables
##
NULLSENSOR = 0
PRESSENSOR = 1
MAGSENSOR = 2
sensDict = {NULLSENSOR:"No sensor",
PRESSENSOR:"Pressure sensor",
MAGSENSOR:"Magnetic sensor"}
# Event class
class ev(object):
timestamp = 0
sType = NULLSENSOR
def __init__(self, ts=0, st=NULLSENSOR):
self.timestamp = ts
self.sType = st
def toString(self):
if(sType == PRESSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Pressure sensor triggered\n")
elif(sType == MAGSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Magnetic sensor triggered\n")
else:
return ""
# Report log
llog = [] # Data log
lmutex = True # Log mutex for writing
##
### Hardware configuration
##
# GPIO callbacks
def pressureCallback(channel):
global llog
global lmutex
global trigCntGlobal
global trigCntPress
ep = ev(ts=dt.now(), st=PRESSENSOR)
print("---> Pressure sensor triggered at "+
ep.timestamp.strftime("%c"))
rfSecuBot.sendMessage('#channel', "Pressure sensor "+
"triggered.")
while(not lmutex):
pass
lmutex = False
llog.insert(0, ep)
trigCntGlobal = trigCntGlobal + 1
trigCntPress = trigCntPress + 1
lmutex = True
def magneticCallback(channel):
global llog
global lmutex
global trigCntGlobal
global trigCntMag
global rfSecuBot
em = ev(ts=dt.now(), st=PRESSENSOR)
print("---> Magnetic sensor triggered at "+
em.timestamp.strftime("%c"))
rfSecuBot.sendMessage('#channel', "Magnetic sensor "+
"triggered.")
while(not lmutex):
pass
lmutex = False
llog.insert(0, em)
trigCntGlobal = trigCntGlobal + 1
trigCntMag = trigCntMag + 1
lmutex = True
# Periodic logging function
def logUpdate():
global llog
global lmutex
updTime = dt.now()
print("---> Updating log\n")
while(not lmutex):
pass
lmutex = False
for i in llog: ########### STUCK HERE
print(i.toString()) ###########
# Check log timestamps
for i in llog:
if((updTime - i.timestamp).total_seconds() > 300):
llog.remove(i)
for i in llog: ########### WAS STUCK HERE
print(i.toString()) ########### TOO
lmutex = True
print("---> Log updated\n")
# Formatting function
def logFormat():
global llog
global lmutex
logUpdate() # Asynchronous call to logUpdate to make sure
# that the log has been updated at the time
# of formatting
while(not lmutex):
pass
lmutex = False
flog = []
cnt = 0
for i in llog:
if(cnt < 10):
flog.append(i.toString())
cnt = cnt + 1
else:
break
lmutex = True
print("----> Formatted string:")
print(flog+"\n")
return flog
def listFormat():
global llog
global lmutex
logUpdate() # Asynchronous call to logUpdate to make sure
# that the log has been updated at the time
# of formatting
while(not lmutex):
pass
lmutex = False
flog = []
flog.append(" Sensors \n")
dLen = len(sensDict.keys())
if(dLen <= 1):
flog.append(sensDict.get(NULLSENSOR))
else:
sdItr = sensDict.iterkeys()
st = sdItr.next() # Had to add extra var
while(dLen > 1):
st = sdItr.next()
trigCnt = 0
for i in llog:
if(i.sType == st):
trigCnt = trigCnt + 1
if(trigCnt < 1):
pass
else:
flog.append("-> "+st+"\n")
flog.append(" No. of times tripped: "+
trigCnt+"\n")
lmutex = True
print("----> Formatted string:")
print(flog+"\n")
return flog
##
### Software configuration
##
def blist(bot, update):
print("--> List command received\n")
listString = "List of sensor trips in the last 5 minutes:\n"
listString = listString+listFormat()
print("> "+listString+"\n")
bot.sendMessage('#channel', listString)
def log(bot, update):
print("--> Log command received\n")
logString = "Log of last 10 occurrences:\n"
logString = logString+logFormat()
print("> "+logString+"\n")
bot.sendMessage('#channel', logString)
rfSecuBotUpd.start_polling(poll_interval=1.0,clean=True)
while True:
try:
time.sleep(1.1)
except KeyboardInterrupt:
print("\n--> Ctrl+C key hit\n")
gpio.cleanup()
rfSecuBotUpd.stop()
rfSecuBot = 0
quit()
break
## Callback registration and handlers are inserted afterwards
# Just in case...
print("--> Bot exiting\n")
gpio.cleanup()
rfSecuBotUpd.stop()
rfsecuBot = 0
print("\n\n\t *** EOF[] *** \t\n\n")
quit()
# EOF []
P.S. I think someone might suggest a 'class' version of this. Think it'll work?
In the toString function, I forgot to put self in front of the should-be members sType and timestamp:
def toString(self):
if(sType == PRESSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Pressure sensor triggered\n")
elif(sType == MAGSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Magnetic sensor triggered\n")
else:
return ""
Which is why the value returned was always an empty string.
Note to self: check your variables!!!
On that note, that kind of explained why it didn't seem to block the thread.

Categories

Resources