How can I write a loop in R so that if I press esc it stops not in the middle but at the end of the loop? So to say I want to define points where it is safe to interrupt the loop.
I am running an iteration with a plot every second. If the visual results don't develop in the right direction, I want to be able to interrupt the iteration, tweak some parameters and continue the iteration. Now I am doing this by pressing esc or the stop button in the GUI. But this corrupts some data, because the interrupt takes place in the middle of a calculation. So I am not able to continue the iteration.
Here is an option using withRestarts and hijacking the "abort" restart. Try running the code and hitting "ESC" while the loop is going:
# Make up a task that takes some time
task_to_perform_in_loop <- function() for(i in 1:100) Sys.sleep(0.01)
# Run task in loop
{
stopAtEnd <- FALSE
for(i in 1:5) {
cat("Loop #", i, "\n", sep="")
withRestarts(
task_to_perform_in_loop(),
abort=function(e) {
message("Will stop when loop complete")
stopAtEnd <<- TRUE
}
)
}
if(stopAtEnd) stop("Stopping After Finishing Loop")
cat("Continuing After Finishing Loop")
}
Just keep in mind this will prevent you from truly exiting the loop short of sending a kill command to R.
Related
If I have a for loop with a try-catch block, and I interrupt the kernel, the loop will go to error block and simply proceed to the next iteration. I would like to stop the loop entirely, is there a way to do that? Currently, I'll have to kill the kernel if I want to stop the loop, which means loading up the models, etc again, which takes time.
Example: I would like to know if there's a way to interrupt the entire for loop rather than just one iteration if I made a typo.
import time
for i in range(100):
try:
time.sleep(5)
print(i)
except:
print('err')
just catch your keyboard interrupt in your try/catch.
for i in range(100):
try:
time.sleep(5)
print(i)
except KeyboardInterrupt:
print ('KeyboardInterrupt exception is caught')
raise # if you want everithings to stop now
#break # if you want only to go out of the loop
else:
print('unexpected err')
more info : https://www.delftstack.com/howto/python/keyboard-interrupt-python/
You can break out of the loop:
for i in range(100):
try:
time.sleep(5)
print(i)
except:
print('err')
break
I have a loop in R that does very time-consuming calculations. I can set a max-iterations variable to make sure it doesn't continue forever (e.g. if it is not converging), and gracefully return meaningful output.
But sometimes the iterations could be stopped way before max-iterations is reached. Anyone who has an idea about how to give the user the opportunity to interrupt a loop - without having to wait for user input after each iteration? Preferably something that works in RStudio on all platforms.
I cannot find a function that listens for keystrokes or similar user input without halting until something is done by the user. Another solution would be to listen for a global variable change. But I don't see how I could change such a variable value when a script is running.
The best idea I can come up with is to make another script that creates a file that the first script checks for the existence of, and then breaks if it is there. But that is indeed an ugly hack.
Inspired by Edo's reply, here is an example of what I want to do:
test.it<-function(t) {
a <- 0
for(i in 1:10){
a <- a + 1
Sys.sleep(t)
}
print(a)
}
test.it(1)
As you see, when I interrupt by hitting the read button in RStudio, I break out of the whole function, not just the loop.
Also inspired by Edo's response I discovered the withRestarts function, but I don't think it catches interrupts.
I tried to create a loop as you described it.
a <- 0
for(i in 1:10){
a <- a + 1
Sys.sleep(1)
if(i == 5) break
}
print(a)
If you let it go till the end, a will be equal to 5, because of the break.
If you stop it manually by clicking on the STOP SIGN on the Rstudio Console, you get a lower number.
So it actually works as you would like.
If you want a better answer, you should post a reproducible example of your code.
EDIT
Based on the edit you posted... Try with this.
It's a trycatch solution that returns the last available a value
test_it <- function(t) {
a <- 0
tryCatch(
for(i in 1:10){
a <- a + 1
message("I'm at ", i)
Sys.sleep(t)
if(i==5) break
},
interrupt = function(e){a}
)
a
}
test_it(1)
If you stop it by clicking the Stop Sign, it returns the last value a is equal to.
I want to pause and continue a loop.
Does rstudio have some options that can pause a loop and continue the loop?
Just like "stop" button can stop the loop.
I don't know if the readline() function can help:
a <- 0
for(i in 1:4) {
a <- a + i
if(readline() == "0") break
}
Now you have to insert values for each iteration.
For instance, if you want to stop at iteration 2:
1
0
> a
[1] 3
Maybe this solution does not totally meet your requirements (I haven't really understood your question), but it may help you have a control of each iteration in order to decide if and when to stop it.
to continue you can use
next
and to go out from loop you can use
break
see here for more details.
I have a piece of code in Julia in which a solver iterates many, many times as it seeks a solution to a very complex problem. At present, I have to provide a number of iterations for the code to do, set low enough that I don't have to wait hours for the code to halt in order to save the current state, but high enough that I don't have to keep activating the code every 5 minutes.
Is there a way, with the current state of Julia (0.2), to detect a keystroke instructing the code to either end without saving (in case of problems) or end with saving? I require a method such that the code will continue unimpeded unless such a keystroke event has happened, and that will interrupt on any iteration.
Essentially, I'm looking for a command that will read in a keystroke if a keystroke has occurred (while the terminal that Julia is running in has focus), and run certain code if the keystroke was a specific key. Is this possible?
Note: I'm running julia via xfce4-terminal on Xubuntu, in case that affects the required command.
You can you an asynchronous task to read from STDIN, blocking until something is available to read. In your main computation task, when you are ready to check for input, you can call yield() to lend a few cycles to the read task, and check a global to see if anything was read. For example:
input = ""
#async while true
global input = readavailable(STDIN)
end
for i = 1:10^6 # some long-running computation
if isempty(input)
yield()
else
println("GOT INPUT: ", input)
global input = ""
end
# do some other work here
end
Note that, since this is cooperative multithreading, there are no race conditions.
You may be able to achieve this by sending an interrupt (Ctrl+C). This should work from the REPL without any changes to your code – if you want to implement saving you'll have to handle the resulting InterruptException and prompt the user.
I had some trouble with the answer from steven-g-johnson, and ended up using a Channel to communicate between tasks:
function kbtest()
# allow 'q' pressed on the keyboard to break the loop
quitChannel = Channel(10)
#async while true
kb_input = readline(stdin)
if contains(lowercase(kb_input), "q")
put!(quitChannel, 1)
break
end
end
start_time = time()
while (time() - start_time) < 10
if isready(quitChannel)
break
end
println("in loop # $(time() - start_time)")
sleep(1)
end
println("out of loop # $(time() - start_time)")
end
This requires pressing and then , which works well for my needs.
For the following code: I can't figure out why j does not print on every outside loop iteration.
x = 0
for (j in 1:15)
{
for (i in 1:100000)
{
x = x + 1
}
print(j)
}
What R seems to be doing is running the the whole thing, and at the end print out all the js, not one by one as when every loop iterates.
It seems to be that j should be printing after every loop iteration, what am I missing here?
Is there a way to make it such that j in printed on every outside loop iteration?
Thank You
I'm guessing you are using the Windows Rgui, which buffers its console output, and then writes it out in chunks (see the R Windows FAQ 7.1). To force immediate printing to the console, you can simply add a call to flush.console() after the print() statement.
x = 0
for (j in 1:15) {
for (i in 1:100000) {
x = x + 1
}
print(j)
flush.console()
}
R output is typically buffered. You can circumvent this in two ways. Either (only on Windows, IIRC) you can go to the menu of the R Gui, and chose Misc -> Buffered Output (or press Ctrl-W) to disable buffering (which typically slows down execution), or you can call flush.console() any time you want to ensure that the output is actually shown (e.g. to show progress).
Not familiar with R but that code looks right for what you are trying to do. May be something to do with output buffering as I've come accross the same issue in PHP where the whole script runs before any output is rendered.