0

Having recently discovered python, I attempted to write a simple logger. Data is read from a device, processes, displayed and stored on disc. Those different tasks belong to different modules, of course.

What appeared to be cool at the time, was to provide command-line interface to each module, as explained here: https://docs.python.org/2/tutorial/modules.html#executing-modules-as-scripts

The result is tat although the program as a whole uses import x and the uses the classes in the modules, the modules can be used form the command line as well. For example, invoking hw_comm.py would open the default device with default options and stream to stdout. Also plot.py expects data form stdin and draws a plot.

I can see a ton of advantages to this design, such as

  • easy to debug
  • easy to adapt for different use cases
  • easy to test
  • provides immediate value to the end user, long before the project is finished.

I have read only a few thousand lines of python yet, but haven't seen this approach (modules as both importable classes and stand-alone scripts) elsewhere. Why would be that? Is the extra work to support this format too much for an enterprise project? Or maybe, unlike my tiny project, business scale projects can not easily support this behavior, with hundreds of modules doing different things just to accomplish one complex goal together?

  • Python has an interactive interpreter. If I need to use a module interactively I can just use the interpreter. You're not going to get anything remotely complicated done from the command line, where you'll either perform a simple sequence of statements or invent a new language just to do what you can already do from Python. – Doval Sep 19 '14 at 11:57
  • @Doval, my impression is that by in/outputting data in form of text tables, other utilities can be used to process the data, e.g. cut to get only one column. Source. Doing so from the python interpreter would require typing the code that invokes the class, each time. – Vorac Sep 19 '14 at 12:27
  • Doing so from the python interpreter would require typing the code invoking the class, each time. I'm not sure I see the problem. – Doval Sep 19 '14 at 12:31
  • @Doval, let's say the module contains a single fascade class. Let's say that after if __name__ == "__main__": there are 10 lines, that use this class in a default way. Now using the module can be as simple as python hw_comm.py. If those lines weren't there, one would need to invoke the python interpreter and type those 10 lines. Furthermore, invoking other commands would be more cumbersome than in Bash. – Vorac Sep 19 '14 at 12:50
  • I still don't see the issue. You could just as easily put those 10 lines in a function. I don't see how you can possibly argue that doing things from inside the same language your code is written in is going to be more cumbersome than using Bash to invoke a script that parses strings that eventually leads to some code being run. – Doval Sep 19 '14 at 13:07
2

The benefits of being able to execute a module from the command line are clear, as you outline.

However, what are the benefits of this functionality lying in the module itself? That is not so clear. You could easily accomplish the same thing with a simple wrapper script that called the module. This would be no more work to code and just as convenient to use.

And, in my mind, it is better to logically separate the module from code that uses the module.

0

Using an if __name__ == "__main__" block to run a few quick tests is not unusual - you can even find it in the standard library.

However, if you intend to distribute your package as a command-line app, users generally expect there to be one entry point to the executable. (Imagine how hard rm would be to use if, instead of adding a -r flag to recurse directories, you had to type rmdir, a completely different command).

In Python-land we generally achieve this using a single main script which imports the package's internal modules and calls different functions as required.

0

The reason you don't see this more often is that having a file be both a module and a script doesn't work well except in simple cases. The primary reason is that as a system get more complex you end up with more modules, and at some point the __main__ script will get imported, and at that point you then have two copies of that module in memory -- once as sys.modules['__main__'] and once as sys.modules[actual_name]. At that point weird errors start happening and if you don't know what's going on you can lose hours figuring it out.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.