[Python-ideas] making a module callable

Andrew Barnert abarnert at yahoo.com
Sun Nov 24 23:35:55 CET 2013


From: Ben Finney <ben+python at benfinney.id.au>


>Greg Ewing <greg.ewing at canterbury.ac.nz> writes:
>
>> Ben Finney wrote:
>> > So, definitely ‘sys.argv’ needs to continue having all command-line
>> > arguments, including the command name used to invoke the program.
>>
>> That doesn't necessarily mean it has to be passed along with the
>> arguments to a __main__() function, though. You can always extract it
>> from sys.argv if you need it.
>
>Yet the ‘__main__’ function needs to get the arguments as a parameter::
>
>    def __main__(argv):
>
>(or at least, that's how I've seen it done most commonly, and I agree
>that it makes a good intreface for ‘__main__’ functions).

Or to get the arguments as separate parameters:

    def __main__(*argv):

… or, more realistically:

    def __main__(inpath, outpath):

Then:

    if __name__ == '__main__':
        __main__(*sys.argv[1:])

The benefit is that the names document what the arguments mean, and also give you better error messages if the script is called wrong. Obviously any serious script is going to have a real usage error, etc., but then any serious script is going to use argparse anyway. For quick & dirty scripts, the first error below is obviously nicer than the second, and no more work.

    $ ./script.py

    TypeError: main() missing 2 required positional arguments: 'inpath' and 'outpath'

    $ ./script.py

    IndexError: list index out of range


There's no reason you _couldn't_ write the idiom with main(argv0, inpath, outpath); I just haven't seen it that way. Scripts that explode argv always seem to do *argv[1:], while those that use it as a list usually seem to do all of argv.


More information about the Python-ideas mailing list