APScheduler run a job for a specific amount of times - python-3.6

Python 3.6.0
APScheduler 3.3.1
I have a program that I have just modified to implement APScheduler.
The program is working exactly as intended.
Here is the code snippet where I added in APScheduler:
def main():
sched = BackgroundScheduler()
sched.start()
sched.add_job(errordetect)
sched.add_job(errordetect, 'interval', minutes=5)
input("Press enter to exit.")
The job runs 'right now' and then every 5 minutes. My issue is this:
I have to stop the job manually by pressing 'Enter'.
Is there a way to say either:
1) Stop running after X amount of time (say one hour) or
2) stop after X iterations (say twelve iterations)
What I am wanting is to run the job every 5 minutes for one hour, so I
want it to stop on it's own after twelve iterations (or one hour -- effectively the same thing). I am not finding anything like that in the documentation, but I am hoping that I am either missing something in the docs or that there is another way to accomplish what I am after.
Thanks.

I solved it like this:
x = 0
starttime = time.time()
while x < 5:
i = 0
for a_connection in ssh_conns:
errordetect(a_connection, ip_addrs[i])
i += 1
x += 1
if x == 5:
break
time.sleep(15.0 - ((time.time() - starttime) % 15.0))

Related

Robotframework run for x amount of minutes

Im trying to run a test that is repeated for x amount of minutes.
My idea for the keyword:
*** Keywords ***
Run test looped
FOR ${i} IN RANGE 9999
Do something
Exit For Loop If ${ELAPSED} > ${MAX_DURATION}
END
Im trying to find how to calculate the elapsed time in minutes.
I found the datetime type for robotframework but dont know how to get minutes elapsed. How can I get the elapsed time in minutes?
In builtin library there's Repeat Keyword - it does exactly what you need:
Repeat Keyword 2 minutes Do Something arg1 arg2
For more info see: http://robotframework.org/robotframework/latest/libraries/BuiltIn.html#Repeat%20Keyword
It's easier to work with epoch for such use cases - get it before the loop, and compare the current value inside it:
Run test looped
${start}= Evaluate time.time() time
FOR ${i} IN RANGE 9999
Do something
${now}= Evaluate time.time() time
Exit For Loop If (${now} - ${start})/60 > ${MAX_DURATION} # divide the runtime seconds by 60, as ${MAX_DURATION} is in minutes
END

Responding to multiple mouse clicks to produce a different output - Tkinter

I'm working on a problem requiring me to create a GUI (in Tkinter) which shows a different word in the label (referencing from a list) each time the button is pressed.
I've tried researching and have found similar problems but haven't found a working solution yet. I have tried 'for each' and 'while' loops, and 'if' statements, but haven't been able to get the code working correctly.
the_window.counter = 0
if the_window.counter == 0:
top_label['text'] = words [0]
the_window.counter + 1
elif the_window.counter == 1:
top_label['text'] = words [1]
the_window.counter + 1
the code shown above produces the first word in the list only, and multiple clicks don't have any effect. does anyone have any ideas?
Thanks.
You need need to keep a global counter, and update it each time it is clicked.
The following code illustrates the technique:
# initialized to -1, so that the first time it is called
# it gets set to zero
the_window_counter = -1
def handle_click():
global the_window_counter
the_window_counter += 1
try:
top_label.configure(text=words[the_window_counter])
except IndexError:
top_label.configure(text="no more words")

How can set an inbuilt timer in RStudio to execute snippets of code?

I have some code in Rstudio which sends an API request to Google Big Query to run a saved query. Then my script downloads the data back to RStudio to be modelled to a machine learning model.
Its a lot of medical data and I would like some of the process to be even more automated than before.
tags<-read.csv('patient_health_codes.csv',stringsAsFactors = FALSE)
tags<-tail(tags, 6)
this section takes a CSV to iterate over patient health groups (such as Eczema is 123456) - Section 1
MD2DS="2018-07-20"
MD2DE="2018-07-20"
This section above fills in date periods for the query execution function - Section 2
sapply(health_tags$ID, function(x) query_details (MD2_date_start=MD2SE,
MD2_date_end=MD2DE,
Sterile_tag=as.character(x)))
This section executes the query on google big query and iterates over all the different patient groups in x i.e Eczema, Asthma, Allergy Group, and so on. -Section 3
project <- "private-health-clinic"
bq_table=paste0('[private-health-clinic:medical.london_',Sterile_tag,']')
sql =paste0('SELECT * FROM ', bq_table)
This section names each table after its patient group - section 4
data <- query_exec(sql, project = project, max_pages = Inf)
write.csv(data, file =paste0("medical_", Sterile_tag, ".csv"))
This code downloads and writes the big query table as a CSV on RStudio - Section 5
My question is, how do I tell RStudio when someone executes section 3 after 1 hour in real time please execute section 4 then 5 mins after execute section 5.
In advance thank you for the help I'm not an R expert!
Just add this after section 3:
Sys.sleep(3600)
And after section 4, add:
Sys.sleep(300)
Depending on how long it takes to execute that code, it might be worthwhile to use Sys.sleep for the desired amount of waiting time minus the time spent calculating, as follows:
t0 <- Sys.time()
# section 3
t1 <- Sys.time()
Sys.sleep(3600 - (t1 - t0))
# section 4
t2 <- Sys.time()
Sys.sleep(300 - (t2 - t1))
# section 5
Otherwise the waiting time will be added to the time spent running the sections.

R script with user input from command line [duplicate]

This question already has answers here:
How to include interactive input in script to be run from the command line
(3 answers)
Closed 5 years ago.
I cannot find a solution to this particular problem, even though more or less similar questions have been questioned before in:
Run R script from command line
http://www.cureffi.org/2014/01/15/running-r-batch-mode-linux/
Running a script from bash is easy enough, however once one needs user interaction I couldn't find a solution. Please consider the example:
userInput<-function(question) {
n = 0
while(n < 1 ){
n <- readline(question)
n <- ifelse(grepl("\\D",n),-1,as.integer(n))
if(is.na(n)){break} # breaks when hit enter
}
return(n)
}
investedLow<- userInput("Invested value in low risk since last time: ")
Now if I save this script as test.R and run it for R --no-save < teste.R the entire script is run and the time for user input does not happen.
The script works fine in Rstudio, for example.
How to wait for user input in a script to be run in the command line?
Here is a total hack, repurposing a very specific purpose-built package for your more-general question:
library(getPass)
userInput<-function(question) {
n = 0
while(n < 1 ){
n <- getPass::getPass(msg = question)
n <- ifelse(grepl("\\D",n),-1,as.integer(n))
if(is.na(n)){break} # breaks when hit enter
}
return(n)
}
investedLow <- userInput("Invested value in low risk since last time: ")
print(investedLow)
Maybe the worst part about this is that getPass hides the user input. There must be a way to modify the source code to fix that.
Update: The getPass author pointed out that the solution could be as simple as using readLines slightly differently:
cat(question)
readLines(file("stdin"), n=1)

R- Excluding random numbers that have already been generated

So I'm working on a webscraping script in R and because the particular website I'm scraping doesn't take too kindly to people who scrape their data in large volumes, I have broken down my loop to handle only 10 links at a time. I still want to go through all the links, however, just in a random and slow manner.
productLink # A list of all the links that I'll be scraping
x<- length(productLink)
randomNum <- sample(1:x, 10)
library(rvest)
for(i in 1:10){
url <- productLink[randomNum[i]]
specs <- url %>%
html() %>%
html_nodes("h5") %>%
html_text()
specs
message<- "\n Temporarily unavailable\n "
if(specs == message){
print("Item unavailable")
}
else{
print("Item available")
}
}
Now the next time I run this for-loop I want to exclude all the random numbered indices that have already been tried in the previous running of the loop. That way this for loop runs through 10 new links each time until all the links have been used. There is another aspect to this that I'd like some input on. Since I can raise alarm flags by brute force scraping the particular company's website, is there any way I can slow down this loop so that it only runs every couple of minutes? I'm thinking of a timeout function or such where the code runs the for-loop once, waits a few minutes then runs it again (with new links each time as mentioned above). Any ideas?
Use something like this. Loop over all the product index randomly.
for (i in sample(1:x)){
<Your code here>
# Sleep for 120 seconds
Sys.sleep(120)
}
And if you want to do 10 at a time. Sleep for 120 seconds every 10 executions.
n = 1
for (i in sample(1:x)){
# Sleep for 120 seconds every 10 runs
if (n == 10) {Sys.sleep(120); n = 0}
n = n+1
<Your code here>
}

Resources