Python: Bizarre issue with imported function within While Loop - python

So I have a bit of a conundrum. Let's start with the relevant fragment of my code.
from RECORD import recordSystem
recTime = 30 #Amount of time(seconds) I want to record the audio input
while True: #I want to keep this active while system is running
#Standard raspberry Pi input sensors.
if(GPIO.input(LedPin4) == GPIO.LOW and GPIO.input(LedPin5) == GPIO.HIGH:
recordSystem(recTime) #when condition is met run the code.
So the function I am trying to run comes from another script I wrote. And it works. It records analog audio and creates a .wav file in my project folder. The problem with this code is that it was working perfectly find yesterday and now is not. Nothing has been changed or touched. It just does not want to work. What happens is that the loop starts, and when the condition is met the function is launched properly and I get my "recording" notice in the compiler. Yet it NEVER stops recording.
When I just do the following outside of the loop:
recordSystem(recTime)
The function runs through properly without any problems. So it has to do something with calling the function inside the loop. Yet, it was working without any problems for a while.
Could anyone give me a best guest on what might be going on?
Much appreciated!

Adding a break statement after your recordSystem(recTime) should do the trick! I also fixed the indentation, and removed an extra ( from the code:
from RECORD import recordSystem
recTime = 30 #Amount of time(seconds) I want to record the audio input
while True: #I want to keep this active while system is running
#Standard raspberry Pi input sensors.
if GPIO.input(LedPin4) == GPIO.LOW and GPIO.input(LedPin5) == GPIO.HIGH:
recordSystem(recTime) #when condition is met run the code.
break

Related

I created a python bind for CS:GO with pyautogui but it doesnt work

I created a simple bind script. It works on IDLE Python but it doesn't work in CS:GO. Do you know why?
Mayby it must be on background to work?
import keyboard
import pyautogui
import time
def EventListen():
while True:
try:
if keyboard.is_pressed('n'):
pyautogui.press('`')
pyautogui.typewrite('say EZ')
pyautogui.press('enter')
pyautogui.press('`')
EventListen()
except:
EventListen()
EventListen()
I don't see the need to use pyautogui since you are already using keyboard which is sufficient to perform the tasks you need. I have made some changes to your code
import time
import keyboard
def EventListen():
while True:
try:
if keyboard.is_pressed('n'):
keyboard.press('`')
keyboard.write('say EZ')
keyboard.press('enter')
keyboard.press('`')
elif keyboard.is_pressed('/'): #add something to end the process
break
except:
EventListen()
time.sleep(0.001)
EventListen()
There is no need to call the function in the while loop, as it will anyway be executed infinitely unless you kill the process. I don't see why the script wouldn't run in the background, in fact I am typing this
n`say EZ
`
using the script. What might be possible is that your previous program ran continuously, causing high CPU usage which might have competed with the game's demand. I recomend you to add a small delay before every iteration of the while loop, in this case I have added 1 ms delay, which will cause significant reduction in CPU usage. I am not sure if that solved your problem as I am unable to reproduce your exact case, let me know if it helped.
EDIT : I forgot to mention, I have added another binding of keyboard.is_pressed('/') which will make the program break out of the loop and hence terminate it when / key is pressed. You can change this as you like. If you don't want any other binding as such (which I don't recommend) then you can rely on manually killing the task.
you should make an exe with pyinstaller and you run it background

Nuke Python run the same script / node multiple times without scriptOpen and scriptClose?

I've got a python script for (Foundry) Nuke that listens to commands and for every command received executes a Write node. I've noticed that if I don't do nuke.scriptOpen(my_renderScript) before nuke.execute(writeNode,1,1) and then after do nuke.scriptClose(my_renderScript), then the write command seems to execute but nothing is written to file, despite me changing knob values before I call execute again.
The reason I want to not use scriptOpen and scriptClose every time I execute -the same node- is for performance. I'm new to nuke, so correct me if I'm wrong, but it's inefficient to unload and reload a script every time you want to run a node inside it, right?
[EDIT] Here's a simple test script. Waits for command line input and runs the function, then repeats. If I move the script open and script close outside the looping / recursive function, then it will only write to file once, the first time. On subsequent commands it will "run", and nuke will output "Total render time: " in the console (render time will be 10x faster since it's not writing / doing anything) and pretend it succeeded.
# Nuke12.2.exe -nukex -i -t my_nukePython.py render.nk
# Then it asks for user input. The input should be:
# "0,1,0,1", "1024x1024", "C:/0000.exr", "C:/Output/", "myOutput####.png", 1, 1
# then just keep spamming it and see.
import nuke
import os
import sys
import colorsys
renderScript = sys.argv[1]
nuke.scriptOpen(renderScript)
readNode = nuke.toNode("Read1")
gradeNode = nuke.toNode("CustomGroup1")
writeNode = nuke.toNode("Write1")
def runRenderCommand():
cmdArgs = input("enter render command: ")
print cmdArgs
if len(cmdArgs) != 7:
print "Computer says no. Try again."
runRenderCommand()
nuke.scriptOpen(renderScript)
colorArr = cmdArgs[0].split(",")
imageProcessingRGB = [float(colorArr[0]), float(colorArr[1]), float(colorArr[2]), float(colorArr[3])]
previewImageSize = cmdArgs[1]
inputFileLocation = cmdArgs[2]
outputFileLocation = cmdArgs[3]
outputFileName = cmdArgs[4]
startFrameToExecute = cmdArgs[5]
endFrameToExecute = cmdArgs[6]
readNode.knob("file").setValue(inputFileLocation)
writeNode.knob("file").setValue(outputFileLocation+outputFileName)
gradeNode.knob("white").setValue(imageProcessingRGB)
print gradeNode.knob("white").getValue()
nuke.execute(writeNode.name(),20,20,1)
runRenderCommand()
nuke.scriptClose(renderScript)
runRenderCommand()
The problem was between the chair and the screen. Turns out my example works. My actual code that I didn't include for the example, was a bit more complex and involved websockets.
But anyway, it turns out I don't know how python scoping sintax works ^__^
I was making exactly this error in understanding how the global keyword should be used:
referenced before assignment error in python
So now it indeed works without opening and closing the nuke file every time. Funny how local scope declaration in python in this case in my code made it look like there's no errors at all... This is why nothing's sacred in scripting languages :)
Is there a way to delete this question on grounds that the problem turns out was completely unrelated to the question?
Well that took an unexpected turn. So yes I had the global problem. BUT ALSO I WAS RIGHT in my original question! Turns out depending on the nodes you're running, nuke can think that nothing has changed (probably the internal hash doesn't change) and therefore it doesn't need to execute the write command. In my case I was giving it new parameters, but the parameters were the same (telling it to render the same frame again)
If I add this global counter to the write node frame count (even though the source image only has 1 frame), then it works.
nuke.execute(m_writeNode.name(),startFrameToExecute+m_count,endFrameToExecute+m_count, continueOnError = False)
m_count+=1
So I gotta figure out how to make it render the write node without changing frames, as later on I might want to use actual frames not just bogus count increments.

How to transfer a value from a function in one script to another script without re-running the function (python)?

I'm really new to programming in general and very inexperienced, and I'm learning python as I think it's more simple than other languages. Anyway, I'm trying to use Flask-Ask with ngrok to program an Alexa skill to check data online (which changes a couple of times per hour). The script takes four different numbers (from a different URL) and organizes it into a dictionary, and uses Selenium and phantomjs to access the data.
Obviously, this exceeds the 8-10 second maximum runtime for an intent before Alexa decides that it's taken too long and returns an error message (I know its timing out as ngrok and the python log would show if an actual error occurred, and it invariably occurs after 8-10 seconds even though after 8-10 seconds it should be in the middle of the script). I've read that I could just reprompt it, but I don't know how and that would only give me 8-10 more seconds, and the script usually takes about 25 seconds just to get the data from the internet (and then maybe a second to turn it into a dictionary).
I tried putting the getData function right after the intent that runs when the Alexa skill is first invoked, but it only runs when I initialize my local server and just holds the data for every new Alexa session. Because the data changes frequently, I want it to perform the function every time I start a new session for the skill with Alexa.
So, I decided just to outsource the function that actually gets the data to another script, and make that other script run constantly in a loop. Here's the code I used.
import time
def getData():
username = '' #username hidden for anonymity
password = '' #password hidden for anonymity
browser = webdriver.PhantomJS(executable_path='/usr/local/bin/phantomjs')
browser.get("https://gradebook.com") #actual website name changed
browser.find_element_by_name("username").clear()
browser.find_element_by_name("username").send_keys(username)
browser.find_element_by_name("password").clear()
browser.find_element_by_name("password").send_keys(password)
browser.find_element_by_name("password").send_keys(Keys.RETURN)
global currentgrades
currentgrades = []
gradeids = ['2018202', '2018185', '2018223', '2018626', '2018473', '2018871', '2018886']
for x in range(0, len(gradeids)):
try:
gradeurl = "https://www.gradebook.com/grades/"
browser.get(gradeurl)
grade = browser.find_element_by_id("currentStudentGrade[]").get_attribute('innerHTML').encode('utf8')[0:3]
if grade[2] != "%":
grade = browser.find_element_by_id("currentStudentGrade[]").get_attribute('innerHTML').encode('utf8')[0:4]
if grade[1] == "%":
grade = browser.find_element_by_id("currentStudentGrade[]").get_attribute('innerHTML').encode('utf8')[0:1]
currentgrades.append(grade)
except Exception:
currentgrades.append('No assignments found')
continue
dictionary = {"class1": currentgrades[0], "class2": currentgrades[1], "class3": currentgrades[2], "class4": currentgrades[3], "class5": currentgrades[4], "class6": currentgrades[5], "class7": currentgrades[6]}
return dictionary
def run():
dictionary = getData()
time.sleep(60)
That script runs constantly and does what I want, but then in my other script, I don't know how to just call the dictionary variable. When I use
from getdata.py import dictionary
in the Flask-ask script it just runs the loop and constantly gets the data. I just want the Flask-ask script to take the variable defined in the "run" function and then use it without running any of the actual scripts defined in the getdata script, which have already run and gotten the correct data. If it matters, both scripts are running in Terminal on a MacBook.
Is there any way to do what I'm asking about, or are there any easier workarounds? Any and all help is appreciated!
It sounds like you want to import the function, so you can run it; rather than importing the dictionary.
try deleting the run function and then in your other script
from getdata import getData
Then each time you write getData() it will run your code and get a new up-to-date dictionary.
Is this what you were asking about?
This issue has been resolved.
As for the original question, I didn't figure out how to make it just import the dictionary instead of first running the function to generate the dictionary. Furthermore, I realized there had to be a more practical solution than constantly running a script like that, and even then not getting brand new data.
My solution was to make the script that gets the data start running at the same time as the launch function. Here was the final script for the first intent (the rest of it remained the same):
#ask.intent("start_skill")
def start_skill():
welcome_message = 'What is the password?'
thread = threading.Thread(target=getData, args=())
thread.daemon = True
thread.start()
return question(welcome_message)
def getData():
#script to get data here
#other intents and rest of script here
By design, the skill requested a numeric passcode to make sure I was the one using it before it was willing to read the data (which was probably pointless, but this skill is at least as much for my own educational reasons as for practical reasons, so, for the extra practice, I wanted this to have as many features as I could possibly justify). So, by the time you would actually be able to ask for the data, the script to get the data will have finished running (I have tested this and it seems to work without fail).

Using thread in while loop causes problems with LED blink

I've been hung up on a problem for a couple of days, now. I've spent hours searching message boards and have come up empty.
I have a program that pulls data from an API, parses it with JSON, and displays it on an LCD screen. I want an LED light to blink when data meets a certain condition. I have been fairly successful so far. The issue I am running into is when a thread is called to start the blink from my main while loop, and the main while loop restarts, it appears that the thread is then called again. This causes my LEDs to start acting wacky after each subsequent while loop restart. Any suggestions?
I tried using v.isAlive() == False" in hopes that the thread wouldn't restart but that wasn't helpful. I just want the thread to start once if the condition is met and then continue blinking the LED until the condition is not met. Since I use an LCD screen, the data is on a continuous loop.
Here is a very simplified snippet of my program:
def partCloudBlink():
while True:
allLEDon()
time.sleep(2.5)
yellowLEDon()
time.sleep(1)
allLEDoff()
def partCloudBlink_start():
v = threading.Thread(target=partCloudBlink)
if v.isAlive() == False:
v.daemon = True
v.start()
RUNNING = True
try:
while RUNNING:
if weather in ("Partly Cloudy"):
partCloudBlink_start()
print "Current conditions: %s" % (conditions) #unrelated to the question, just program filler
except KeyboardInterrupt:
RUNNING = False
Thank you very much!
It's because a new thread object is created every time partCloudBlink_start is called. v.isAlive() is always False since it's a new thread.
You can create a global variable or something similar to store the thread object depending on your code structure.

Send a variable from outside the python console OR stop a script from outside

I wrote a Python script that executes an optimization and runs days to get a solution (due to the costly objective function). In all days work it will be sufficient to just stop the calculation at some point because the solution is good enough for me (but not for the optimization algorithm).
The problem is, I can always abort hitting Ctrl+C. But then there is no chance to nicely output the current best parameters, plot the data, save it etc. It would be great to stop the script in a controlled way after the next calculation of the objective function. So my thought was so question some variable (if user_stop=True) and programatically stop the optimization. But how to set such a variable? The python console is blocked during execution.
I thought about setting the content of a text file and reading it in each iteration but it's more than poor and hard to explain for other users of the script. Theoretically, I could also ask the user for an input but than the script won't run automatically (which it should until someone decides to stop).
Any ideas for my problem?
Basically that's it - stop the loop at some point but execute the print:
a = 0
while True:
a = a + 1
print(a)
If you poll your "variable" infrequently (say at most once every 20 seconds) then the overhead of testing for a file is negligible. Something like
import os
QUITFILE = "/home/myscript/quit_now.txt"
# and for convenience, delete any old QUITFILE that may exist at init time
... # days later
if os.path.isfile( QUITFILE)
# tidy up, delete QUITFILE, and exit
Then just echo please > home/myscript/quit_now.txt to tell your program to exit.
maybe you can use a do-while loop. holding your target in a varible
outside the loop and start looping the calculatio while <= your target calculation.
For Windows, I would use msvcrt.getch()
For example, this script will loop until a key is pressed, then, if it is q, prompt for the user to quit: (Note that the if statement uses 'short circuiting' to only evaluate the getch() - which is blocking - when we know that a key has been pressed.)
import msvcrt, time
while True: #This is your optimization loop
if msvcrt.kbhit() and msvcrt.getch() == 'q':
retval = raw_input('Quit? (Y/N) >')
if retval.lower() == 'y':
print 'Quitting'
break #Or set a flag...
else:
time.sleep(1)
print('Processing...')
If you place this if block at a point in the optimization loop where it will be frequently run, it will allow you to sop at a convenient point, or at least set a flag which you can check for at the end of each optimization run.
If you cannot place it somewhere where it will be frequently checked, then you can look at handling the KeyboardInterrupt raised by Ctrl-C
If you are running on Linux, or need cross-platform capability, have a look at this answer for getting the keypress.

Categories