Turn shutil into a runnable module

I’d be at least somewhat open to a runpy patch that defined a new runpy.run_resolved_name function that used importlib.util.resolve_name to resolve dotted.module:dotted.name references and run the referenced callable [1].

Given that to build on, python -m runpy could be enhanced to accept names containing “:” and call them using run_resolved_name, with all the remaining command line options passed in as positional arguments.

Since many shutil functions can do useful things with only positional strings as arguments, that would actually cover quite a bit of ground. For example:

py -m runpy shutil:copy2 ~/my/src.txt .

By default, the return value from the called function would be ignored, but --str, --repr, and --ascii options could be added to request printing the result to stdout instead.

However, you wouldn’t be able to pass anything other than strings (no booleans for example), and you wouldn’t be able to pass keyword arguments.

The only generalised solution that has occurred to me for the “keywords and non-string types” part of the problem is to define a mechanism for accepting JSON inputs and emitting JSON outputs.

Something like:

py -m runpy --json shutil:copy2 \
    '["~/my/src.txt", "."]' \
    '{"follow_symlinks": true}'

In JSON mode, if the called function produces a non-None result, that would be dumped to stdout as JSON (with a --no-output option to suppress that behaviour, and --str and --repr also overriding it).

The “somewhat open” hesitance comes from the fact that I’m not sure the simpler version is worth adding on its own (since “only strings, and no keyword arguments” is a pretty massive restriction in applicability), and the JSON-based enhancement feels like a significant enough UX addition to the standard library that it should probably be a PEP (I’d be willing to sponsor such a PEP, though).


  1. To allow additional keyword arguments that affect how the target callable is invoked, the module function would accept args and kwds as positional-or-keyword arguments, rather than accepting arbitrary args and keywords and forwarding them on. ↩︎

3 Likes