Accessing pexpect's internal "countdown" remainder? - python

I am wondering if it is possible to get a script to grab the "remaining time" in the "timeout counter" or whatever is used internally by pexpect:
index, match_obj, text = session.expect(["New Software Release is ready -- Version"], timeout=int(DOWNLOAD_TIMEOUT))
if match_obj:
logger.info('Download to primary card complete.')
logger.debug('Download took %d seconds', SOMETHINGGOESHERE)
else:
logger.critical('Download to primary card took too long.')
quit(session)
For the life of me, I can't seem to find any attempt to do this anywhere here or via Google :)
I assume I can do something more complicated where I keep track of my own timer, but I was hoping for a simpler solution, given that pexpect is already keeping track of a time value, in seconds.

pexpect source code shows that the remaining time is kept in a local variable therefore it is not accessible outside of the function after it returns.
It is not complicated to keep track of the remaining time yourself:
end_time = time.time() + timeout
index = child.expect([..], timeout=timeout)
remaining_time = end_time - time.time()
If you need to do it multiple times, you could subclass pexpect.spawn class and override expect() method to return the remaining time together with the index.

Related

how can i trigger an action when a variable change it value in this case time?

I need to detect when the minutes of the clock/time change and do something,
This is mi code so far, for the clock but still can figuruate out in python how to detect the value has change and do action after. Any help will be apreciated i come from a c++ backgorund my implementations seems so far not working.
while True:
now = datetime.now()
print(now.strftime("%M), end = " ", flush = true)
time.sleep(1)
currentMin = now.srtftime("%M")
that worked for me:
from datetime import datetime
import time
past_min = None
while True:
#current min
now_min = int(datetime.now().strftime("%M"))
#first iteration
if not past_min:
past_min = now_min
if now_min != past_min:
#call your function here
print("Min change detected")
past_min = now_min
#print the seconds
print(datetime.now().strftime("%S"))
time.sleep(1.5)
I think you can create a class (in the below example Minute) with a property currenMin to store the current minute value. By using #<property>.setter function, when the property <property> is changed, it will trigger the setter function
from datetime import datetime
import time
class Minute(object):
def __init__(self):
self._currenMin = ''
#property
def currentMin(self):
return self._currenMin
#currentMin.setter
def currentMin(self, value):
if value != self._currenMin:
# ACTION CODE BELOW
print('Minute changed')
self._currenMin = value
minute = Minute()
while True:
now = datetime.now()
print(now.strftime("%M"), end=" ", flush = True)
time.sleep(1)
minute.currentMin = now.strftime("%M")
Well, for the general case with simple variables, you can't simply do it. There are two simple options to do something similar:
if you control EVERYTHING that writes it, make them trigger that action
write code that regularly checks it and triggers the action when it changes
use language tools like a custom setter (see #user696969's answer)
The first case needs you to control everything that could modify that value. At that point, you might not even need a variable, and just pass the new value (and you can reverse this by having a variable that is always updated). This is a very common pattern, called Event-driven programming, and heavily used for example in UIs, websites (client-side, see a list of DOM events for example) and game frameworks (see pygame's documentation on events)
The second-case of writing a loop or checking it regularly can also work, however, there are some downsides to it as well. You probably don't want to write an infinite loop waiting for it to change, especially not in a way that also blocks the changing of that variable, and thus dead-locking the entire program as it's preventing something it's waiting for. If you just check it regularly between other, it might be hard to ensure it will be checked regardless of what else is the program doing. You might use multiple threads for it, but that brings it's own set of problems. You also have to store and update the previous value, so you can compare it. This might be slow or memory-consuming if the variable holds too much data.
You can also use language tools with custom setters. This is clean, but can not be used for any variable, just for class attributes, so you still need some control over the rest of the program.
Generally I'd use the event-driven approach or the setter one, depending on the wider context. However, for such simple cases, the checking is also fine. The simplest solution might event be to remove the need for this entirely.

Question with python, music and events, is there a more elegant way of programming this?

Goal: To create a program that will be able to turn off and on lights to music based on events that are triggered from midi notes.
Hello all, I am hoping that this isn't too broad of a question to ask. I am working on a project where I get events from a midi file and turn those events into time. I take a note from the midi file and append it to a list as the time it was placed
Example:
https://imgur.com/swZsrk9
I take all of those and place them into a list. Don't worry about how I do that as that is not my main goal to discuss. I've just substituted the list with a hard-coded one on my example code.
I now have a list of times that I want lights to either turn on or off, now I just need to set an infinite loop with a timer that starts at 0 seconds (with the start of the song) and when the timer == (the next time in the list) it will print out a line. Here is my code:
import socket
import sys
import random
import time
from pygame import mixer
from mido import MidiFile
masterList = [12.37, 14.37, 15.12, 15.62,16.36, 17.61, 18.11, 19.11, 19.61, 20.35,]
mixer.init()
song = mixer.Sound('song.wav')
startTime = time.time()
endTime = startTime + song.get_length()
print(masterList)
print('Starting song.')
song.play()
print('Playing song, timer:',startTime)
while time.time() <= endTime:
#print(round(time.clock(),1),masterList[0])
if round(time.clock(),2) == masterList[0]:
print(round(time.clock(),2),"<-",masterList[0],"------------------")
del masterList[0]
#print('playing...')
time.sleep(.01)
mixer.quit()
Here is a video of it runing:
https://www.youtube.com/watch?v=VW-eNoJH2Wo&feature=youtu.be
Ignore the deprecation warnings
It works but sometimes, due to the nature of programming, the time.clock() does not always == the next item in the list. I knew that this would be a problem going in as you can't rely on how long the code takes to execute. Sometimes it takes a few more milliseconds than usual to complete a while loop so then when you call the time.clock() method it != the next time in the list. Then the list does not remove it's first item and then it will never equal that first item.
I tried going by 10 milliseconds (.1) but it doesn't give me the accuracy I need.
Also, it seems clunky, sometimes the events are delayed a few milliseconds and it makes the effect not as pleasing. As you can see from my video the times of the prints aren't lined up completely where they need to be, even though they are perfectly placed on where they need to be in the midi file.
Question: Is there a more elegant way of tackling this? I seem to keep finding ways of patching it to work better and then it always goes back to the nature of programming, where the cpu always is unreliable. I've been trying to think of different ways of doing this but I can't come up with any. Your help would be much appreciated!!
Since you're deleting the notes as you play them, have you tried using >= instead of ==?
E.g.,:
while time.time() <= endTime:
#print(round(time.clock(),1),masterList[0])
if round(time.clock(),2) >= masterList[0]:
print(round(time.clock(),2),"<-",masterList[0],"------------------")
del masterList[0]
That way the note will play as soon as possible after the specified time, and remove it from the queue. Only way to know actual performance is to test it, but at the very least it won't skip notes.

Getting information from long running background process in Django

I would like to have a computational simulation running on a background process (started with redis rq) where I can query its current state, as well as change parameters using Django.
For the sake of simplicity: let's say I want to run the following code for a long time (which I would set up through a python worker):
def simulation(a=1):
value = 0
while a != None:
value += a
time.sleep(5)
Then, by visiting a URL, it would tell me the current value of value. I could also POST to a URL to change the value of a i.e. a=None to stop the simulation or a=-10 to change the behavior.
What is the best way to do this?
This best way I've found to do this is using cache
from django.core.cache import cache
def simulation(a=1):
value = 0
while a != None:
value += a
cache.set('value', value, 3600)
time.sleep(5)
a = cache.get('a', None)
This does work, but it's quite slow for my needs. Perhaps there's a method using sockets, but I wasn't abe to get it to work. The socket is blocked in the background process.

Python Multithreaded Messenger Simulation. Stuck on timerThread update. What do?

I have a piece of code that simulates a system of messengers (think post office or courier service) delivering letters in a multithreaded way. I want to add a way to manage my messengers "in the field" to increase the efficiency of my system.
tl;dr: How do I update my tens-to-hundreds of timerthreads so they wait longer before calling their function?
Here's what the code I've written so far is supposed to do in steps.
Someone asks for a letter
We check to see if there are any available messengers. If none, we say "oops, sorry. can't help you with that"
If at least one is available, we send the messenger to deliver the letter (new timer thread with its wait param as the time it takes to get there and back)
When the messenger gets back, we put him in the back of the line of available messengers to wait for the next delivery
I do this by removing Messenger objects from a double ended queue, and then adding them back in after a timerthread is done waiting. This is because my Messengers are all unique and eventually I want to track how many deliveries each has had, how far they have traveled, and other stuff.
Here's a pseudoish-codesnippet of the larger program I wrote for this
numMessengers=5
messengerDeque=deque()
pOrder=0.0001
class Messenger:
def __init__(self):
for i in range(numMessengers):
messenger=Messenger()
messengerDeque.append(messenger)
def popDeque():
messenger=idleDeque.popleft()
print 'messenger #?, sent'
return messenger
def appendDeque(messenger):
print 'messenger #?, returned'
messengerDeque.append(messenger)
def randomDelivery():
if numpy.random.randint(0,10000)<=(pOrder*10000):
if len(messengerDeque)!=0:
messenger=popDeque()
tripTime=distance/speed*120
t=threading.Timer(tripTime,appendDeque,args=[messenger])
t.start()
else:
print "oops, sorry. can't help you with that"
The above works in my program.
What I would like to add is some way to 'reroute' my messengers with new orders.
Lets say you have to deliver a letter within an hour of when you get it. You have five messengers and five orders, so they're all busy. You then get a sixth order.
Messenger 2 will be back in 20 minutes, and order six will take 30 minutes to get to the delivery destination. So instead of saying "oops, we can't help you". We would say, ok, Messenger 2, when you get back, immediately go deliver letter six.
With the code I've written, I think this could be done by checking the active threads to see how long until they call their functions, pick the first one you see where that time + how long your new delivery takes is < 1 hr, cancel it, and start a new thread with the time left plus the new time to wait.
I just don't know how to do that.
How do you check how long is left in a timerthread and update it without making a huge mess of your threads?
I'm also open to other, smarter ways of doing what I described.
YAY PYTHON MULTITHREADING!!!!!
Thanks for the help
Using the class threading.Timer wont fulfill your needs. Although there is a "interval" member in Timer instances, once the Timer(thread) started running any changes in interval (time-out) are not considered.
Furthermore you need to know how much time is still left for the timer to be triggered, for which there isn't a method as far as I know.
Furthermore you probably also need a way to identify which Timer instance you need to update with the new timeout value, but this is up-to you.
You should implement your own Timer class, perhaps something along the lines of:
import threading
import time
class MyTimer(threading.Thread):
def __init__(self, timeout, event):
super(MyTimer, self).__init__()
self.to = timeout
self.evt = event
def setTimeout(self, v):
self.end = time.time() + v
def run(self):
self.start = time.time()
self.end = time.time() + self.to
while self.end > time.time():
time.sleep(0) # instead of thread.yield
self.evt()
def getRemaining(self):
return self.end - time.time()
def hi(): print "hi"
T=MyTimer(20,hi)
T.start()
for i in range(10):
time.sleep(1)
# isAlive gives you True if the thread is running
print T.getRemaining(), T.isAlive()
T.setTimeout(1)
for i in range(3):
time.sleep(1)
print T.getRemaining(), T.isAlive()

Efficient way to timeout waiting for a state change (variable change)?

I'm sure this is somewhat common, so I am curious what are the accepted/efficient ways of doing this in Python.
Put simply, I am just busy-waiting for a variable to be updated. At the same time I need a timeout scheme, but I feel there must be a better way of doing this.
Currently I do something like this:
wait_start = time.time()
while state != NEW_STATE:
if time.time() - wait_start > timeout:
print "Timed out!"
# Do something
# Continuing on...
I obviously just can't sleep, because I need to know when the state has changed.
So what is an efficient method of implementing a timeout for a state (variable) change?
Condition variables and events are often used for this type of thing. Both require cooperation from the side that's changing the variable.

Categories

Resources