Weird one (checking last time a python file was executed) - python

Weird one. I have an applescript that calls a python file every time the laptop wakes from a sleep. The apple script opens the terminal and calls the python file. The python file has functions in it that run certain code if it is a certain time of the day. like this:
now = datetime.datetime.now().hour
if 9 <= now <= 10 :
then do python stuff...
now = datetime.datetime.now().hour
if 15<= now <= 18 :
then do python stuff...
now = datetime.datetime.now().hour
if 22<= now <= 23 :
then do python stuff...
So as you can see above there are certain times of the day that specific python functions will be executed. My problem is that i want to only run the python functions once within that timeframe. At the moment if the laptop wakes up twice within the time frames above then the python functions will be run twice.
Is there a way to solve this in the python file that i am calling?
I know there are probably many ways to attack this problem i.e applescripts, terminal commands or python files. to be honest i dont know where to start so i guessed id start with python and work backwards.
I am thinking if we could check when the python file was last executed and stopping it if it was evicted within the specified time frame already. Then this could be a way of stoping it running twice?

Save the time of the last execution to a file:
...
with open('path/to/file', 'w') as f:
f.write(str(now.timestamp()))
In the top of the script, attempt to read from said file:
try:
with open('path/to/file') as f:
last_execution_time = datetime.fromtimestamp(float(f.read()))
except FileNotFoundError: # will happen in the first execution, obviously
last_execution_time = now
# do whatever logic you want to perform with `last_execution_time` and `now`
...

Related

Automation of program execution on linux

I have to perform several experiments in order to analyse certain results for a class assignment. For each result, I have to run a line of code by varying the parameters from terminal. I was wondering if there is a way to automate this and thus save me the trouble of running the program and changing the values each time. Attached is the line of code that I have to execute each time:
teaa/examples/scripts/run-python.sh teaa/examples/python/rf_mnist.py \
--numTrees 10 --maxDepth 7 --pcaComponents 40
I would like these lines of code to be executed n times automatically and that in each execution, the parameters 'numTrees, maxDepth and pcaComponents' change in a set range of values.
I have not really tried any solutions yet. I have never programmed in terminal and I have no idea where to start.
For more involved process operations, one should use the subprocess module in stdlib Python... but if you just want a one-off run of this command line, you can just use plain old os.system function - The followin code:
import os
for nt in range(1,21):
for md in range(1,11):
for pc in range(20,100,10):
os.system(f'teaa/examples/scripts/run-python.sh teaa/examples/python/rf_mnist.py --numTrees {nt} --maxDepth {md} --pcaComponents {pc}')
will run your program for numTrees = 1,2...20, maxDepth = 1,..10 and pcaComponents = 20,...90

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.

What's the most efficient way to pause during a loop in python?

I have a script which loops through the elements of a list. Each element is used to query an API. However, the API has a query limit (only 500 queries are permitted over a 24 hour period). I am currently managing this through a counter in a loop, which resets for each "chunk" of 500 elements and would pause the loop for a day. Is there a better way to do this?
counter = 0
for query in queries:
if counter < 500:
counter = counter + 1
api = ApiClient(api_key='secretkey')
data = api.get(q=query)
print(data)
safequery = ''.join(e for e in query if e.isalnum())
datafilename = "{} {}.txt".format(safequery,todaysdate)
with open(datafilename, 'w') as outfile:
json.dump(data, outfile)
else:
print('sleepy time')
time.sleep(86400)
counter = 0
time.sleep(86400) is asking for problems, and also makes your CPU work for nothing. If something happens during those 86400 seconds and the script crashes, nothing will restart it.
The much better option would be to save the current page/chunk somewhere (raw text file, json, DB, doesn't really matter), then load it before making the next requests.
Then you can put your script in an Operating System level/managed task scheduler (for example, cron for Unix or Task Scheduler for Windows) and run it daily.
time.sleep() is a good solution, but you can also make Python ask for input when you want to continue. That's primitive, I know.
if counter % 500 == 0: # make the counter start at 1
val = input("\nContinue? [y/n]: ")
if val == 'y':
pass # manually unpause the looping, whenever you want
elif val == 'n':
break # interrupt for loop
I would tackle this by creating a script that when ran will get the next 500 and then terminate. You might want to output a text file to store where you are up to in this sequence.
I would then schedule this script to run every 24 hours with windows task scheduler (on windows)
This means you are not having a process running doing nothing.
sleep()
should only be used for small time intervals.
I think you could make this code as a python script and execute in a batch file.
catch this batch file and schedule into a task manager to run every day at 2:00 pm for example...
usually i have a python script server that runs my robots and things that i need to do automatically.
An if else statement with a sleep is probably as simple as it gets; however it's not efficient since the process will still be alive and doing nothing for 86400 seconds.
You could look into creating a cron job to run your code one a day at the same time

Recording the time into a text file

I am trying to test how long my battery runs on my raspberry pi. All i need to do is run a while loop until the battery dies. However, I need to record the time that it starts and ends. I would like to save the data into a txt file. My current code is as follows:
import time
file = open('time','w')
x=1
while x==1:
from datetime import datetime
now = datetime.now()
file.write(now)
file.close()
If I just print the results in python i will get a result, and the current code makes a file called 'file' but there is nothing saved in the txt file. Any and all help would be appreciated.
Thank you for your time
You have an infinite loop which just gets the current time over and over again ... This loop won't break (even if your battery dies ...).
At some point, you need to break the loop or the condition in the while needs to become False. e.g.
from datetime import datetime
while x == 1:
now = datetime.now()
break
or
from datetime import datetime
while x == 1:
now = datetime.now()
x += 1
Generally speaking, you'll want to look in your system logs for when the computer decided to start up and when it decided to shut down due to lack of battery power ...
I would recomend code that looks like the following:
import time
import datetime.datetime as dt
initTime = dt.now()
while True:
with open('time.txt', 'a') as f:
f.write( str(dt.now() - initTime) )
time.sleep(1)
The couple of differences. First, you always open the file in append mode. This way, the file will be flushed every time. Next, it will always update the file with the amount of time elapsed. So even if your raspberry pi shuts down, you should be able to recover it.
No need to record these times yourself. The Pi (and almost any Linux distribution) writes those events to the /var/log/wtmp file (more about that file here). The last command can retrieve those events (also see the manual entry for last). Try the following:
last -FRx | grep -e 'boot\|shutdown'
Explanation of the flags:
-F prints the full date and times - which is handy in your case, because that's what you wanted to know.
-R suppresses the hostname in the output. You don't need that.
-x shows shutdown en runlevel changes - now that's what you wanted to know.
Finally the grep statement filters out the boot or shutdown messages.

How do I keep a variable the same across different running python scripts?

So I have a variable called "num" which begins with a value of 1 and constantly increases by 1. When I run other python scripts simultaneously, they also use "num" but they of course start from 1 because the num isn't connected to the num in the other scripts. If num is 600 in my first script which has been running for longer, num could be 5 in my other script which hasn't been running for as long.
How can I make it so that if num is 600 in script A, num automatically starts increasing from 600 in script B as soon as I run it? I need the nums to be the same throughout and increase together as one.
The most trivial way to do this is just to use the filesystem as a synchronised variable store. It is not elegant, but it can be achieved as in a quick and dirty way with two scripts:
Script one:
# This is a master script that starts everything off.
from time import sleep
count = 0
while True:
with open("myfile.txt","w+") as f:
print>>f,count
print "Script 1 count:",count
count+=1
sleep(1)
Script two:
# This is the script that you start when script one is running
import warnings
from time import sleep
try:
with open("myfile.txt","r") as f:
count = int(f.read().strip())
except Exception as error:
warnings.warn(repr(error))
count = 0
while True:
print "Script 2 count:",count
count+=1
sleep(1)
If you want an elegant solution, you could look into using sockets to set up a proper message passing system between your scripts.
One way to do this is with something called message passing. First, start up one process to hold the actual num variable, and to synchronize access to it. Then, start up other processes to talk to the first one, and ask it for the current value, then process the next one. (Of course, you'd need to arrange for several next values to be processed at the same time.)
With a very quick search, I turned up this. Hope it helps.
http://www.valuedlessons.com/2008/06/message-passing-conccurrency-actor.html

Categories