Import only when code used?

Is there a way to import a module only if certain code is used?

I ideally I would put it in a function, but it’s not allowed:

function initialize()
    using A
    # create objects using functionality from A
    # to be used throughout the rest of the program
end

Background:
My program initializes some data structures and then runs an algorithm on the data. I have a file holding all the initialize functions of various kinds. One of them sets up a ROS interface through RobotOS.jl for the needed data. If python + rospy isn’t installed on the system, just importing this will error out the whole program. In other cases it still adds to the startup time even when its functionality is never used.

Any good ideas on keeping the extra package from being imported without resorting to commenting out the code?

Could you use package extensions for this? I’m not sure it fits your application, since it allows conditional code loading based on whether or not a package is present in the environment

https://pkgdocs.julialang.org/dev/creating-packages/#Conditional-loading-of-code-in-packages-(Extensions)

if we’re talking about loading python pkg on the fly specifically, what I like to do is something like

function initialize()
    rospy = pyimport("rospy")
end

otherwise you just have to do it in __init__() of your package

You can do:

function initialize()
    @eval begin
       using A
       # create objects using functionality from A
       # to be used throughout the rest of the program
    end
end

Code inside an @eval will run in the global scope, so any objects that you create will end up there (and not local to the initialize function).

3 Likes

What do you mean by “when code used”, what are the conditions for something like initialize to run, and what sort of things does initialize do? Things that only need to be done once and can’t be undone, like a system-conditional import, aren’t usually put in functions that can be called repeatedly. Best practice really depends on what you need to do, and there’s no shortage of ways to conditionally evaluate code in the global scope: @eval expressions, include files, even a simple if statement.

For example, the initialize-@eval function would only evaluate the expression in the module that initialize belongs to. If you want to evaluate that expression in specified modules, you would need to add an argument to provide the module that you import initialize into. If conditional code is in separate files, include is nice because you specify what module to run by simply running it in that module’s scope.

Thanks for all the responses :slight_smile:. They gave me some good options to try out.

@eval within the function worked and was the simplest fix for the time being. I feel like creating a package extension may eventually be the better solution if I can re-organize my code.

Further clarifications: My initialization file holds all the functions I use to initialize various data for the main algorithm. Only one of them is run and only once at the start of the program. Every function returns the same data structures, just with different values.