{"id":215,"date":"2015-12-09T02:25:54","date_gmt":"2015-12-08T18:25:54","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=215"},"modified":"2026-03-17T01:20:29","modified_gmt":"2026-03-16T17:20:29","slug":"argparse-create-a-command-line-app-with-python","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/argparse-create-a-command-line-app-with-python.html","title":{"rendered":"argparse: Create a Command-line App with Python"},"content":{"rendered":"<p><code>argparse<\/code> is a Python standard library that makes it easy to write a CLI application. You should use this module instead of <code>optparse<\/code> which is deprecated since Python 2.7.<\/p>\n<p>ref:<br \/>\n<a href=\"https:\/\/docs.python.org\/3\/library\/argparse.html\">https:\/\/docs.python.org\/3\/library\/argparse.html<\/a><\/p>\n<h2>Basic example<\/h2>\n<pre class=\"line-numbers\"><code class=\"language-py\">#!\/usr\/bin\/env python\n\nfrom __future__ import print_function\n\nimport argparse\nimport sys\n\nimport jokekappa\n\nclass JokeKappaCLI(object):\n\n    def __init__(self):\n        parser = argparse.ArgumentParser(\n            prog='jokekappa',\n            description='humor is a serious thing, you should take it seriously',\n        )\n        self.parser = parser\n        self.parser.add_argument('-v', '--version', action='version', version=jokekappa.__version__)\n\n        self.subparsers = parser.add_subparsers(title='sub commands')\n        self.subparsers \n            .add_parser('one', help='print one joke randomly') \n            .set_defaults(func=self.tell_joke)\n        self.subparsers \n            .add_parser('all', help='print all jokes') \n            .set_defaults(func=self.tell_jokes)\n        self.subparsers \n            .add_parser('update', help='update jokes from sources') \n            .set_defaults(func=self.update_jokes)\n\n    def parse_args(self):\n        if len(sys.argv) == 1:\n            namespace = self.parser.parse_args(['one', ])\n        else:\n            namespace = self.parser.parse_args()\n        namespace.func()\n\n    def tell_joke(self):\n        joke = jokekappa.get_joke()\n        print(joke['content'])\n\n    def tell_jokes(self):\n        for joke in jokekappa.get_jokes():\n            print(joke['content'])\n\n    def update_jokes(self):\n        jokekappa.update_jokes()\n        print('Done')\n\ndef main():\n    JokeKappaCLI().parse_args()\n\nif __name__ == '__main__':\n    main()<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/github.com\/CodeTengu\/JokeKappa\">https:\/\/github.com\/CodeTengu\/JokeKappa<\/a><br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/5176691\/argparse-how-to-specify-a-default-subcommand\">https:\/\/stackoverflow.com\/questions\/5176691\/argparse-how-to-specify-a-default-subcommand<\/a><\/p>\n<h2>Advanced example<\/h2>\n<p>In the following code, you're able to create a Python module called <code>pangu<\/code> and a command-line tool also called <code>pangu<\/code>, both share the same codebase.<\/p>\n<p>in pangu.py<\/p>\n<pre class=\"line-numbers\"><code class=\"language-py\">from __future__ import print_function\n\nimport argparse\nimport sys\n\n__version__ = '3.3.0'\n__all__ = ['spacing_text', 'PanguCLI']\n\ndef spacing_text(text):\n    \"\"\"\n    You could find real code in https:\/\/github.com\/vinta\/pangu.py\n    \"\"\"\n    return text.upper().strip()\n\nclass PanguCLI(object):\n\n    def __init__(self):\n        parser = argparse.ArgumentParser(\n            prog='pangu',\n            description='paranoid text spacing',\n        )\n        self.parser = parser\n        self.parser.add_argument('-v', '--version', action='version', version=__version__)\n        self.parser.add_argument('text', action='store', type=str)\n\n    def parse(self):\n        if not sys.stdin.isatty():\n            print(spacing_text(sys.stdin.read()))\n        elif len(sys.argv) &gt; 1:\n            namespace = self.parser.parse_args()\n            print(spacing_text(namespace.text))\n        else:\n            self.parser.print_help()\n        sys.exit(0)\n\nif __name__ == '__main__':\n    PanguCLI().parse()<\/code><\/pre>\n<p>in bin\/pangu<\/p>\n<pre class=\"line-numbers\"><code class=\"language-py\">#!\/usr\/bin\/env python\n\nfrom pangu import PanguCLI\n\nif __name__ == '__main__':\n    PanguCLI().parse()<\/code><\/pre>\n<p>in setup.py<\/p>\n<pre class=\"line-numbers\"><code class=\"language-py\">from setuptools import setup\n\nsetup(\n    name='pangu',\n    py_modules=['pangu', ],\n    scripts=['bin\/pangu', ],\n    ...\n)<\/code><\/pre>\n<p>As a result, there're multiple usages:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">$ pangu \"abc\"\n$ python -m pangu \"abc\"\n$ echo \"abc\" | pangu\n$ echo \"abc\" | python -m pangu\nABC<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/github.com\/vinta\/pangu.py\">https:\/\/github.com\/vinta\/pangu.py<\/a><\/p>\n<h2>Accept a list as option<\/h2>\n<pre class=\"line-numbers\"><code class=\"language-py\">parser.add_argument('-u', '--usernames', type=lambda x: x.split(','), dest='usernames', required=True)\n# your_command -u vinta\n# your_command -u vinta,saiday<\/code><\/pre>\n<h2>Accept conditional argument<\/h2>\n<p>ref:<br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/15459997\/passing-integer-lists-to-python\">https:\/\/stackoverflow.com\/questions\/15459997\/passing-integer-lists-to-python<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>argparse is a Python standard library makes it easy to write a CLI application. You should use this module instead of optparse.<\/p>\n","protected":false},"author":1,"featured_media":780,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[101,2],"class_list":["post-215","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-about-python","tag-cli-tool","tag-python"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/215","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=215"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/215\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/780"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=215"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=215"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}