How to exit a Julia program without completely exit REPL or shutting down Julia?

Sorry for another stupid question.
In a Julia program, or a function, if some ‘Oops’ happens, I know that I can put

exit()

somewhere in the code, so that I can automatically and completely shutting down julia and quit.

I mean like, in the windows CMD, doing exit() it will completely quit Julia. In Jupyter Notebook, doing exit() will shutting down the Julia kernel.
Like, once Julia is in the environment variable, in CMD I can type julia and enter REPL,

      C:\Users\Trump>julia
                     _
         _       _ _(_)_     |  Documentation: https://docs.julialang.org
        (_)     | (_) (_)    |
         _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
        | | | | | | |/ _` |  |
        | | |_| | | | (_| |  |  Version 1.5.4 (2021-03-11)
       _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
      |__/                   |

Now if I type, exit(), it just complete quit,

julia> exit()
C:\Users\Trump>

Is there a way to quit however still in the REPL environment? Like

julia>  somecommand()
julia>

I know there are some other guys might have asked similar question, but the answer is not very clear.

  1. I just wonder, in Julia, is there a command such that one can quit, but do not completely shutting down Julia?

Or is it by design that Julia only allow a complete exit?
However, this is also reasonable, because if it is a complete exit, all the workspace will be cleaned, and this is actually reasonable.

  1. Is there a command which can completely clean the workspace (remove all the variables, definitions of functions, just delete everything) without quit the REPL?
    I mean like, just say in Jupyter Notebook, currently if I want to completely clean the workspace, I need to restart the kernal. Although restarting the kernal is fast, I believe there might be smarter ways to clean the workspace.

Thanks in advance!

3 Likes

I believe that running Julia again from the REPL does what you are looking for:

run(`julia.exe`)

Image example aswell:

image

Not sure if it works in jupyter since I don’t have it installed but it works for me in the REPL.

2 Likes

Perhaps Tim Holys Revise.jl can help in your workflow?

3 Likes

That’s typically done by throwing an exception (error("oh no!")).

At the moment no. There used to be a workspace() command that did this but it had some issues so it was removed. However, I think the underlying issues have been fixed so it is possible that could be put back.

11 Likes

I think you refer to pre Julia-1…
Having back a workspace() function would really be useful… I saw this request asked tens of time by users :slight_smile:

4 Likes

Even more powerful than a workspace command would be some kind of “change module” command that would cause subsequent REPL inputs to be evaluated in a module different from Main. Imagine if one could do something like:

julia> module Main2 end; # create a new, empty workspace

julia> change_module(Main2) # Move the REPL to that workspace

julia/Main2> data = Main.data; # Stuff from old workspace is still accessible.
3 Likes

https://gist.github.com/pfitzseb/8fab21f09d6c15246d4a0960af3c65b1

4 Likes

There is PR doing that, but it needs some more work.

3 Likes

Is there an equivalent of the “exec” functions from C? so you could just tell Julia to exec Julia. This is equivalent really to exit() followed by julia except you can do it from entirely within Julia. It has the advantage of not leaving any threads or tasks running in the background, and unlike run() doesn’t leave the original Julia running.

If not, perhaps someone could just create Exec.jl which uses ccall to provide them?

1 Like

this does that. Also C is not interactive, what’s the point

2 Likes

if I understand the help on run(), run("julia.exe") causes the running Julia to run a sub-process and wait for it to exit. This means you’ve now got two processes… suppose the first process has enormous quantities of memory allocated for example, they still are allocated… the new Julia process is clean, but the old one is still hanging out there… If you do run() again you’ll have 3 processes, and then 4, and then 5 etc…

exec causes the current process to be replaced by a process running the new command. So now every time you run exec("julia") you don’t get a new process, you just completely reset the process to be a fresh run of julia.

2 Likes

the idea is that after you Ctrl-C the sub-process, you are still in Julia (although pretty point less)

ah, I see, thanks for the clarification.

1 Like

I mean, it would be pretty trivial to provide this through ccall right? I imagine I could do it this afternoon if I took the time to read up on ccall. But it would be better to be a package kind of maintained by some github organization, like JuliaStrings etc except with a “OS interaction” theme or something.

I just tested this on my computer, and it worked:

julia> ccall(:execvp,Int32,(Cstring,Array{Cstring}),"/home/dlakelan/julia-latest/bin/julia",Cstring[])

Also this:

julia> ccall(:execvp,Int32,(Cstring,Array{Cstring}),"julia",Cstring[])

since execvp searches the path in the same way the shell does and my personal julia install is in my path :wink:

it should also be possible to create a function like this which just re-execs julia with the same arguments (figured out the specific sauce required).

julia> function reexec()
                 cmd = Base.julia_cmd()
                 @ccall execvp(cmd.exec[1]::Cstring,cmd.exec[2:end]::Ptr{Cstring})::Int32
       end
reexec (generic function with 1 method)

julia> reexec()
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.7.0-beta3.0 (2021-07-07)
 _/ |\__'_|_|_|\__'_|  |  release-1.7/e76c9dad42 (fork: 68 commits, 71 days)
|__/                   |



1 Like

Thank you very much!
My another stupid question. So like, if I have a main program called A.jl .
Now, currently if I want to completely clean the workspace and run it again. What I do is type :

exit()

then

 julia 

then

include("A.jl")

Like

julia> exit()

C:\Users\Trump>julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.6.1 (2021-04-23)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> include("A.jl")

Every time I have to loop over these stupid three steps again and again, I am sure what I did is among the most stupid ways.

May I ask, what do you guys do if you want to completely clean the workspace and run the Julia program again?

use DaemonModes maybe? I think it handles that for you by wrapping code inside module.

but why not just return? don’t call exit()

Inside my .julia/config/startup.jl file I have the function

function clean()
   atexit() do
       run(`$(Base.julia_cmd())`)
   end
   exit()
end

so whenever i call clean() inside a julia session the session will exit and automatically restart. I use this for cleaning a workspace.

2 Likes

You are still creating a second Julia process as a child process of the first Julia process, i.e. the memory and other resources of the first Julia process are still allocated until the second Julia process terminates, as you can see with ps uf:

$ ps f
 188560 pts/7    Ss     0:00 bash
 188574 pts/7    Sl+    0:00  \_ julia
 188654 pts/7    Sl+    0:00      \_ julia

Instead of run you want to use the execve function on POSIX systems and the equivatent _wexecve function on Win32 systems. These really replace the first process with the second (while keeping the Process ID), i.e. all the memory of the the first process is deallocated and replaced with memory allocated to the newly started executable. You cannot return from an execve call. I don’t think Julia Base currently has an exec function that works like run without ever returning, so you would have to use equivalent platform-specific ccall invocations.

1 Like

If I regularly need to restart Julia after it has run A.jl, e.g., because of huge or many global variables used in a script, I just invoke it with

julia -i A.jl

and then I press the three/four keys “Ctrl-D” “cursor-up” “enter” to repeat that, which takes me less than 500 ms. (But if you really need to do this regularly, you might consider putting your script into a function or module.)

4 Likes

Thank you Mr. Biggs, that was helpful.

1 Like

Hi Kristoffer,
are there plans to bring it back maybe renamed to e.g. to Clear() as proposed by Stefan K?
The error() command is for me something like a workaround.
Stefan