Search code examples
juliaargparse.jl

Parameter file in ArgParse.jl?


Python's argparse has a simple way to read parameters from a file:

https://docs.python.org/2/library/argparse.html#fromfile-prefix-chars

Instead of passing your arguments one by one:

python script.py --arg1 val1 --arg2 val2 ...

You can say:

python script.py @args.txt

and then the arguments are read from args.txt.

Is there a way to do this in ArgParse.jl?

P.S.: If there is no "default" way of doing this, maybe I can do it by hand, by calling parse_args on a list of arguments read from a file. I know how to do this in a dirty way, but it gets messy if I want to replicate the behavior of argparse in Python, where I can pass multiple files with @, as well as arguments in the command line, and then the value of a parameter is simply the last value passed to this parameter. What's the best way of doing this?


Solution

  • This feature is not currently present in ArgParse.jl, although it would not be difficult to add. I have prepared a pull request.

    In the interim, the following code suffices for what you need:

    # faithful reproduction of Python 3.5.1 argparse.py
    # partial copyright Python Software Foundation
    function read_args_from_files(arg_strings, prefixes)
        new_arg_strings = AbstractString[]
    
        for arg_string in arg_strings
            if isempty(arg_string) || arg_string[1] ∉ prefixes
                # for regular arguments, just add them back into the list
                push!(new_arg_strings, arg_string)
            else
                # replace arguments referencing files with the file content
                open(arg_string[2:end]) do args_file
                    arg_strings = AbstractString[]
                    for arg_line in readlines(args_file)
                        push!(arg_strings, rstrip(arg_line, '\n'))
                    end
                    arg_strings = read_args_from_files(arg_strings, prefixes)
                    append!(new_arg_strings, arg_strings)
                end
            end
        end
    
        # return the modified argument list
        return new_arg_strings
    end
    
    # preprocess args, then parse as usual
    ARGS = read_args_from_files(ARGS, ['@'])
    args = parse_args(ARGS, s)