Is it bad practice to have arguments called in main() in Python

Should the function name main() always be empty and have arguments called within the function itself or is it acceptable to have them as inputs to the function e.g main(arg1, arg2, arg3)?

I know it works but I'm wondering if it is poor programming practice. Apologies if this is a duplicate but I couldn't see the question specifically answered for Python.

6

3 Answers

In most other programming languages, you'd either have zero parameters or two parameters:

int main(char *argv[], int argc)

To denote the arguments passed through to the parameter. However, in Python these are accessed through the sys module:

import sys
def main(): print(sys.argv, len(sys.argv))

But then you could extend this so that you pass through argv and argc into your python function, similar to other languages yes:

import sys
def main(argv, arc): print(argv, arc)
if __name__ == '__main__': main(sys.argv, len(sys.argv))

But let's forget about argv/argc for now - why would you want to pass something through to main. You create something outside of main and want to pass it through to main. And this can happen in two instances:

  1. You're calling main multiple times from other functions.
  2. You've created variables outside main that you want to pass through.

Point number 1 is definitely bad practice. main should be unique and called only once at the beginning of your program. If you have the need to call it multiple times, then the code inside main doesn't belong inside main. Split it up.

Point number 2 may seem like it makes sense, but then you do it in practise:

def main(a, b): print(a, b)
if __name__ == '__main__': x = 4 y = 5 main(x, y)

But then aren't x and y global variables? And good practice would assume that these are at the top of your file (and multiple other properties - they're constant, etc), and that you wouldn't need to pass these through as arguments.

3

By following the pattern:

def main(): ...stuff...
if __name__ == '__main__': main()

It allows your script to both to be run directly, and if packaged using setup tools, to have an executable script generated automatically when the package is installed by specifying main as an entry point.

See:

You would add to setup.py something like:

entry_points={ 'console_scripts': [ 'my_script = my_module:main' ]
}

And then when you build a package, people can install it in their virtual environment, and immediately get a script called my_script on their path.

Automatic script creation like this requires a function that takes no required arguments.

It's a good idea to allow you script to be imported and expose it's functionality both for code reuse, and also for testing. I would recommend something line this pattern:

import argparse
def parse_args(): parser = argparse.ArgumentParser() # # ... configure command line arguments ... # return parser.parse_args()
def do_stuff(args): # # ... main functionality goes in here ... #
def main(): args = parse_args() do_stuff(args)
if __name__ == '__main__': main()

This allows you to run your script directly, have an automatically generated script that behaves the same way, and also import the script and call do_stuff to re-use or test the actual functionality.

This blog post was mentioned in the comments: which uses a default argument on main to allow dependency injection for testing, however, this is a very old blog post; the getopt library has been superseded twice since then. This pattern is superior and still allows dependency injection.

5

I would definitely prefer to see main take arguments rather than accessing sys.argv directly.

This makes the reuse of the main function by other Python modules much easier.

import sys
def main(arg): ...
if __name__ == "__main__": main(sys.argv[1])

Now if I want to execute this module as a script from another module I can just write (in my other module).

from main_script import main
main("use this argument")

If main uses sys.argv this is tougher.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like