Path: csiph.com!eternal-september.org!feeder.eternal-september.org!border1.nntp.ams1.giganews.com!nntp.giganews.com!bcyclone01.am1.xlned.com!bcyclone01.am1.xlned.com!newsfeed.xs4all.nl!newsfeed8.news.xs4all.nl!nzpost1.xs4all.net!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; '"""': 0.05; '(except': 0.05; 'defaults': 0.05; 'none:': 0.05; 'sys': 0.05; '"__main__":': 0.07; '__name__': 0.07; 'exit': 0.07; '``none``.': 0.09; 'block.': 0.09; 'defined.': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'reliably': 0.09; 'python': 0.10; 'output': 0.13; 'def': 0.13; 'explicitly': 0.15; 'variables': 0.15; 'argv:': 0.16; 'describing': 0.16; 'function::': 0.16; 'inputs': 0.16; 'invoking': 0.16; 'outputs': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'resist': 0.16; 'status.': 0.16; 'subject:program': 0.16; 'systemexit': 0.16; 'url:thread': 0.16; 'url:weblogs': 0.16; 'try:': 0.18; 'input': 0.18; 'arguments': 0.22; 'correctly.': 0.22; 'function,': 0.22; 'wrote': 0.23; 'absolute': 0.23; "python's": 0.23; 'slightly': 0.23; 'import': 0.24; 'module': 0.25; 'header:User-Agent:1': 0.26; 'header:X -Complaints-To:1': 0.26; 'rest': 0.26; 'parameters': 0.27; 'module.': 0.27; 'said,': 0.27; 'sequence': 0.27; 'function': 0.28; 'arguments,': 0.29; 'behaving': 0.29; 'command-line': 0.29; 'invoke': 0.29; 'testing.': 0.29; 'ago': 0.29; 'handled': 0.29; 'raise': 0.29; 'allows': 0.30; 'that.': 0.30; 'code': 0.30; 'says': 0.32; 'wrap': 0.33; 'structure': 0.34; 'except': 0.34; 'mine': 0.35; 'unit': 0.35; 'but': 0.36; 'there': 0.36; 'possible': 0.36; 'loaded': 0.36; 'to:addr:python-list': 0.36; 'subject:: ': 0.37; 'received:org': 0.37; 'minimum': 0.38; 'test': 0.39; 'application': 0.39; 'subject:the': 0.39; 'to:addr:python.org': 0.40; 'your': 0.60; 'skip:u 10': 0.61; 'programs': 0.62; 'making': 0.62; 'more': 0.63; 'different': 0.63; 'strictly': 0.64; 'between': 0.65; 'fundamental': 0.66; 'skip:\xe2 10': 0.70; '8bit%:43': 0.72; 'duty': 0.72; 'url:jsp': 0.72; '8bit%:46': 0.76; 'article': 0.77; '1971': 0.84; '_o__)': 0.84; 'keyword)': 0.84; 'received:125': 0.84; 'restrain': 0.84 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Ben Finney Subject: Re: Putting the main program in a main function Date: Mon, 14 Sep 2015 17:32:01 +1000 References: <55f673b3$0$3342$426a74cc@news.free.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Gmane-NNTP-Posting-Host: jigong.madmonks.org X-Public-Key-ID: 0xAC128405 X-Public-Key-Fingerprint: 517C F14B B2F3 98B0 CB35 4855 B8B2 4C06 AC12 8405 X-Public-Key-URL: http://www.benfinney.id.au/contact/bfinney-pubkey.asc X-Post-From: Ben Finney User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux) Cancel-Lock: sha1:N5wyREdNJAyUXKr2HdkrzDpgCKw= X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 74 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1442215949 news.xs4all.nl 23787 [2001:888:2000:d::a6]:48243 X-Complaints-To: abuse@xs4all.nl X-Received-Bytes: 6617 X-Received-Body-CRC: 1471677168 Xref: csiph.com comp.lang.python:96554 "ast" writes: > The author says that with this structure there are no global variables > (except when using "global' keyword) and that the program can be > loaded as a module without be ran to test the function in the python > shell. > > is it advised to always write programs like that ? Writing all the code in functions makes your code more reliably tested: you can write a unit test that exercises the code and know whether it is behaving correctly. Writing all the code in functions makes your code more understandable: the possible interactions between different parts of the program are more explicitly and strictly defined. So yes, it's advisable to write a ‘main’ function for the application and keep to absolute minimum the ‘if __name__ == "__main__"’ block. That said, your ‘main’ function can be slightly more self-contained. The paradigm for invoking a command-line program is that its input parameters are the process's command-line arguments, and its return value is the process's exit status. So you can write a ‘main’ function that explicitly allows those input and output to be handled as for a normal function:: import sys def main(argv=None): """ Mainline code for this module. :param argv: The sequence of command-line arguments used to invoke this program. Defaults to `sys.argv`. :return: ``None``. """ if argv is None: argv = sys.argv try: handle_the_command_line(argv) do_various_things() except SystemExit as exc: exit_status = exc.code else: # No exit requested; return “success” status. exit_status = 0 return exit_status if __name__ == "__main__": exit_status = main(sys.argv) sys.exit(exit_status) That way, the ‘if __name__ == "__main__"’ block will use the conventional input (command-line arguments) and output (process exit status); the rest of the application code may call ‘sys.exit’ or raise ‘SystemExit’ as normal; but your code will wrap it all up as the inputs and outputs of the ‘main’ function, making it much easier to control for testing. Python's BDFL wrote an article many years ago describing this pattern , mine is a small refinement of that. -- \ “It is the fundamental duty of the citizen to resist and to | `\ restrain the violence of the state.” —Noam Chomsky, 1971 | _o__) | Ben Finney