How do I set up this threaded socket read properly? - python

UPDATE: I found the source of the program hanging. In my pdthread it calls mysocket1.sendall(mydata). It doesn't seem to be able to get past this. Does anyone know why this might be an issue?
I have the following code:
mysocket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket1.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
mysocket1.connect(('127.0.0.1', 10001))
while mysocket1:
try:
msg = mysocket1.recv(4092)
msg = pickle.loads(msg)
print(msg)
for pd in pd_objects:
if msg[0] == pd.cam_ip and str(msg[1]) == 'ON' and pd.pd_active == False:
pd.pd_active = True
pdthread = Thread(target=get_pd_data(pd.cam_ip))
pdthread.daemon = True
pdthread.start()
print("testing1")
elif msg[0] == pd.cam_ip and msg[1] == 'OFF':
pd.pd_active = False
print("testing else")
print("testing2")
except:
traceback.print_exc(file=sys.stdout)
break
print("reached end")
I have another python program connected on the other end. This connects and runs perfectly the first time I press a button to activate it. I have my data sending over in the pdthread and all works swell. It's what happens afterwards that's the problem. Future button presses are NOT picked up by this side. The data is being sent over the socket just fine from the other end, it's just not being received here.
I've put in some prints for testing and I found a few interesting things that I cannot explain which is why I'm asking here:
The print("testing1") is never printed. Ever. Not even after the first successful click. Which makes me think that pdthread.start() is behaving like pdthread.join()... which confuses me.
The print("testing else") is never printed. This is expected given my testing but I wanted to rule it out.
Here's the weirdest one. I have two items in my pd_objects list. When I click the button that sends the pd.cam_ip of the first item, print("testing2") does not print, but it DOES print if I click the one for the second item in the list.
Can anyone help explain this bizarre behaviour?
EDIT: the final print is also never printed

Related

python - while loop structure

I need help to construct a working while loop.
my code goes like this
class Bot():
def __init__(self):
self.woke = False
while self.woke == False:
self.wake_word() # --> when it predicts wake word self.woke changes to True
while self.woke == True:
self.voice_recognition() # --> takes audio turns it to a spoke.txt file
break
self.chat() # --> reads the spoke.txt and finds a response
self.respond() # --> speaks the responds using pyttsx3
the code works perfectly but only for one time..it does what I want it to do but for once and then the script stops.
I need to run it until I give the command to stop it using
sys.exit(0) # in a function
meaning when it responses it starts listening again (self.voice_recognition() function) and again does the chat() and finds a respond().
Not exactly sure what you are looking for, but try this -
class Bot():
def __init__(self):
self.woke = False
while self.woke == False:
self.wake_word() # --> when it predicts wake word self.woke changes to True
while self.woke == True:
self.voice_recognition() # --> takes audio turns it to a spoke.txt file
self.woke=False
break
self.chat() # --> reads the spoke.txt and finds a response
self.respond() # --> speaks the responds using pyttsx3
I had a problem with the way I'm capturing audio.. (I had to close the stream).
what happened was that each time the voice_recognition() was called the stream was already open so the data didn't change and that causes an infinite loop inside the function which caused it to not work how it was supposed to
the final code the was correctly working is this
self.wake_word()
while True:
self.voice_recognition()
self.chat()
self.respond()
really simple and straight forward, the problem was with it the function not the while loop structure.
Thanks for anyone who took the time and tried to answer I'm sure your answers / comments were correct as this wasn't about the while loop structure yet a simple unrecognized missing code.

PyFirmata digital input receives None while working well on debug

I'm studying pyFirmata protocol with some examples. As an exercise I'm doing PIR sensor system. When I'm running the code pyFirmata always outputs 'None' value. However if I'm doing debugging in PyCharm everything works as it should be. On Arduino the StandardFirmata sketch is uploaded. Anyone knows what is the cause of this behaviour?
The code:
import pyfirmata
from time import sleep
def blinkled(pin, message):
print(message)
board.digital[pin].write(1)
sleep(1)
board.digital[pin].write(0)
sleep(1)
port = '/dev/cu.usbmodem1411'
board = pyfirmata.Arduino(port)
it = pyfirmata.util.Iterator(board)
it.start()
pirPin = board.get_pin('d:7:i')
redPin = 12
greenPin = 13
while True:
value = pirPin.read()
while value is None:
print("None")
sleep(1)
pass
if value is True:
blinkled(redPin, "Motion Detected.")
else:
blinkled(greenPin, "No Motion Detected.")
board.exit()
Ok, found that "while" statement should be replaced by "if". Then everything working. Do not understand this behaviour.
Why program stuck with "while" on receiving None?
Why in debug mode everything is fine?
I will appreciate if anyone can explain.
The code resolved this issue:
if value is None:
print("None")
In addition to switching to the if clause as OP pointed out, a continue statement should be used to continue at the top of the loop:
if value is None:
print("None")
continue
This would result in the code logic not running through the additional clauses after it fails the initial "None value" test.

cleaning up function looping

I am looping a function in python as I created my own constant listener. My question is how can I ensure I don't overflow / crash? Logically this is telling me I am leaving a lot of open functions in the background. Once parameters of my application are met I exit(0) for a clean shut down. but how can I ensure this doesn't eat up memory?
This code works fine btw, but I am simply trying to improve it because it feels really wrong to me that I am calling the function within its self without closing the previous use of it and it just feels dirty. constructive comments please.
e.g. (this is now my actual code)
import serial
import sys
import time
def enterdata():
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r")
time.sleep(0.5)
while True:
data = ser.read(ser.inWaiting())
if (len(data) > 0):
a = []
for i in range(len(data)):
a.append(data[i])
if "Please press Enter to activate this console." in "".join(a):
print ("1")
exit(0)
break
ser.close()
enterdata()
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r\n")
enterdata()
NEW VERSION SO FAR FROM POSTS MADE:
import serial
import sys
import time
def enterdata():
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r")
time.sleep(0.5)
while True:
data = ser.read(ser.inWaiting())
if (len(data) > 0):
a = []
for i in range(len(data)):
a.append(data[i])
if "Please press Enter to activate this console." in "".join(a):
print ('1')
return True
exit(0)
break
ser.close()
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r\n")
state = False
while state is not True:
state = enterdata()
This code you showed will give a "RuntimeError: maximum recursion depth exceeded" Error because of Python sets a default value for how many recursions can occur in one function at a time.
Any yours is infinite and definitely will cause problems even if you change this default limit.
Why not make a loop yourself and call the function at will ?
found = False
while not found:
extracted_data = lookfordata()
if extracted_data == "I want it to be equal to this":
found = True
I see you edited the post. Whatever you are trying to do, that method is not efficent, not recommended and not pretty. All the good reasons not to use it.
Imagine that you will handle some data larger than you are using now, you won't know if the recursion stopping condition will come to pass before you exceed the limit. It's also no use to increase limit all the time you encounter a bigger data. I think it should be any programmer's goal to avoid repetition and coming up with programs that can handle any type of unexpected input.
You updated your post again. This way of input handling is much better than raw recursion. Just to mention, instead of;
for i in range(len(data)):
a.append(data[i])
use
for i in data:
a.append(i)

stuck in while loop python

I am creating a chat server in python and got quite far as a noob in the language. I am having 1 problem at the moment which I want to solve before I go further, but I cannot seem to find how to get the problem solved.
It is about a while loop that continues..
in the below code is where it goes wrong
while 1:
try:
data = self.channel.recv ( 1024 )
print "Message from client: ", data
if "exit" in data:
self.channel.send("You have closed youre connection.\n")
break
except KeyboardInterrupt:
break
except:
raise
When this piece of code get executed, on my client I need to enter "exit" to quit the connection. This works as a charm, but when I use CTRL+C to exit the connection, my server prints "Message from client: " a couple of thousand times.
where am I going wrong?
You're pressing Ctrl-C on the client side. This causes the server's self.channel to get closed.
Since calling recv() on a closed channel immediately returns a blank string, your server code gets stuck in an infinite loop.
To fix this, add the following line to your server code:
data = self.channel.recv ( 1024 )
if not data: break # <<< ADD THIS
Or, as suggested by #sr2222, you can combine both this and your current check into one:
if not data or 'exit' in data:
This will exit the loop if the channel has been closed.

Google Wave Robot / Python Variable question

I'm experimenting/having a little fun with wave robot python apiv2.
I made a little 8ball app for the robot which works fine, and now I'm trying to make a trivia app.
I've never programmed in Python but I'm pretty sure my syntax is correct. Here is the relevant code:
elif (bliptxt == "\n!strivia"):
reply = blip.reply()
if (triviaStatus != "playing"):
reply.append("Trivia Started!")
triviaStatus = "playing"
else:
reply.append("Trivia is already running!")
elif (bliptxt == "\n!etrivia"):
reply = blip.reply()
if (triviaStatus == "playing"):
reply.append("Trivia Ended!")
triviaStatus = "stopped"
else:
reply.append("Trivia is not running! To start trivia, type !strivia")
else: (snipped out)
Okay so basically I want it to work so that when someone blips "strivia" the bot recognizes that someone wants to play so it first checks a variable called triviaStatus to see if we are already playing and goes from there. Pretty simple stuff.
In order for this to work (and, actually, this code is really meant to test this question out) the variables would need to effectively be like the php $_SESSION variables - that is, it remembers the value of the variable every time someone blips and does not reset each time.
Nevertheless, whether or not that is the case (if it isn't then I assume I can do the same thing by saving variable settings in a txt file or something) I am baffled because the code above does not work at all. That is to say, the robot is not replying on !strivia or on !etrivia. If the variables didn't save then if anything the robot should just reply with "Trivia Started" or with "Trivia is not running!" each time. But it just does not reply at all.
If I remove the check for triviaStatus, the robot DOES reply. But then there's no logic and I can't test my question out.
I also tried making a !trivstatus where it would reply back with
"Trivia status is " + triviaStatus
but that ALSO choked up. Why is it that every time I want to USE triviaStatus, the bot just dies? Note that I am able to SET triviaStatus fine (I just can't ever check what the output is by replying with it....)
So, to sum this up...how come the above code does not work but the following code DOES work:
elif (bliptxt == "\n!strivia"):
reply = blip.reply()
reply.append("Trivia Started!")
trivia_status = "playing"
elif (bliptxt == "\n!etrivia"):
reply = blip.reply()
reply.append("Trivia Ended!")
trivia_status = "stopped"
Thanks!
It seems that you should rename triviaStatus to trivia_status and make sure that trivia_status has some value e.g., bind it to None before the first use. Otherwise your code might raise UnboundLocalError or NameError exceptions due to triviaStatus/trivia_status doesn't refer to any object.

Categories