Archives | Categories

Julia Development Workflow with Revise.jl

Table of Contents

<2019-01-08 Tue>

This article shows how to organize the module development process in Julia using the Revise.jl package. A Julia program contains several functions that are normally aggregated into modules. On one hand, the process of module development and testing usually involves experimenting with the code in the Julia command line.

However, every time a change is made in one of the functions within a module, it requires reloading the entire module. This is inconvenient because having to remember to reload the module, you will need to do it after every single change to your code.

Additionally, for large modules, reloading an entire module may take a significant amount of time. A remedy for this problem is the Revise.jl package.

1. Getting ready

Configure your favorite programming environment. Note that you can find the complete code for this article at https://github.com/PacktPublishing/Julia-1.0-Programming-Cookbook/tree/master/Chapter08.

Revise can simply be installed with the Julia package manager. In the Julia command line, press the ] key and run the following command:

(v1.0) pkg> add Revise

This will install the Revise.jl library and all its dependencies. Additionally, use the HTTP.jl library:

(v1.0) pkg> add HTTP

2. How to do it…

A module for collecting data on Bitcoin cryptocurrency prices from coindesk.com will be created. Follow these steps:

  1. Create a file, Module1.jl, with the following content. Note that this code is assembled into a module:

    module Module1
    
    using HTTP
    using JSON
    
    export getcoinprices
    
    function getcoinprices(dateFrom::String, dateTo::String)
        url = string("https://api.coindesk.com/v1/bpi/historical/close.json?currency=USD&start=",
                     dateFrom, "&end=", dateTo)
        res = HTTP.request("GET", url ,verbose=0)
        dat = JSON.parse(join(readlines(IOBuffer(res.body)), " "))
        haskey(dat, "bpi") ? dat["bpi"] : Dict()
    end
    
    end # module
    

    In order to use the preceding module, you need to make sure that the file is located in the same directory as the working directory of the Julia command line.

  2. Use the pwd() command to check the current directory. If you want to switch directories, use the cd("enter_new_directory_here") command. Once you have made sure the directories are correct, run the following commands:

    push!(LOAD_PATH, ".")
    using Revise
    using Module1
    
  3. Now, test the module by running the following code:

    julia> getcoinprices("2018-06-20", "2018-06-22")
    Dict{String,Any} with 3 entries:
      "2018-06-22" => 6053.9
      "2018-06-20" => 6758.38
      "2018-06-21" => 6717.2
    
  4. Add an incorrect date range and observe what happens:

    julia> getcoinprices("2018-06-23", "2018-06-22")
    ERROR: HTTP.ExceptionRequest.StatusError(404, HTTP.Messages.Response:
    """
    HTTP/1.1 404 Not Found
        ...(more errors here)...
    
    

    Update the implementation of the getcoinprices function in order to avoid throwing an error for such date ranges; instead, return an empty Dict object.

  5. Open the Module1.jl file in any text editor and add the following line at the beginning of the getcoinprices(dateFrom::String, dateTo::String) function. Remember to save the file:

    dateFrom > dateTo && return Dict()
    
  6. Now, run the same function again:

    julia> getcoinprices("2018-06-23", "2018-06-22")
    Dict{Any,Any} with 0 entries
    

    Note that the function definition has been automatically updated by Revise.jl; you need not relaunch Julia nor reload the module, Module1.

3. How it works…

Revise.jl works by continuously scanning the source code for changes. Special event handling for command-line Terminals (including the Julia command line and Juno) is added. Whenever a change in function implementation is discovered, this function is automatically passed to the Julia interpreter. Note that Revise.jl does not reload the entire module; only those functions that have changed are reloaded.

Revise.jl is able to track most code changes, with two exceptions. Firstly, when a type definition is changed (for example, a new field is added to struct), the Julia interpreter needs to be reloaded (that is, you need to execute the exit() command and start the Julia interpreter again). Secondly, module or file renaming is not supported; again, if you decide to rename modules or files, you should restart the Julia command line.

Note that Revise.jl only provides automatic tracking out of the box for files that have been included within the namespace, either by executing a using or an import statement. However, it is possible to manually add files to the tracking system by executing the push!(LOAD_PATH, "/path/to/the/file/that/will/be/tracked") command. Files loaded by include can also be tracked by explicitly using Revise.track(filename).

4. There's more…

When working in Juno, makes sure that your Julia is set to CyclerBoot Mode. In this way, when you eventually need to restart the Julia command line due to type definition changes, for instance, you will not be left waiting for a new Julia Terminal to start (there will always be one Julia process waiting in the background for you).

5. Further Reading

Learn about Julia development workflow with Revise.jl in this article by Bogumił Kamiński, an associate professor and head of the Decision Support and Analysis Unit at the SGH Warsaw School of Economics, and Przemysław Szufel, an assistant professor in the Decision Support and Analysis Unit at the SGH Warsaw School of Economics.

If you found this article interesting, you can explore Julia 1.0 Programming Cookbook to discover the new features and widely used packages in Julia to solve complex computational problems in your statistical applications. Julia 1.0 Programming Cookbook will be your solution-based guide as it will take you through different programming aspects with Julia.

Copyright © KDr2, SOME RIGHTS RESERVED UNDER CC BY-NC 4.0.

Built with Emacs 28.2 (Org mode 9.5.5).

Last updated: 2022-01-28 Fri 13:42.