A better approach is to install your script using a setuptools entry_point and let the argparse handle the parameter parsing. Your project would look something like:
.
├── myproject
│ ├── __init__.py
│ └── cli.py
└── setup.py
Your setup.py would look like:
import setuptools
import myproject
setuptools.setup(
name='myproject',
version=myproject.version,
description='Does stuff',
url='https://github.com/me/myproject',
packages=['myproject'],
entry_points={
'console_scripts': ['my-script = myproject.cli:entry_point'],
},
)
When you install your package using pip, it will install a command line script named my-script somewhere like /usr/local/bin. The command line script will load your package and any requirements, then run the entry_point
function in your cli module. So let's look at that module:
import argparse
import logging
from . import version
def entry_point():
parser = argparse.ArgumentParser(
description='Something ... something short',
epilog='''Bacon ipsum dolor amet occaecat labore qui, ad
veniam boudin capicola flank. Dolore rump jerky magna
sirloin pancetta. Voluptate anim non minim nostrud ham.
Excepteur kevin turkey officia kielbasa pastrami ad ham
nostrud meatball tongue magna t-bone. Chuck salami mollit,
fatback pig velit officia ut. Cupidatat nulla jowl, tail
chicken occaecat excepteur pig beef salami non. Kevin
cupim bresaola filet mignon enim.''')
parser.add_argument('--verbose', '-v', action='count',
help='increase verbosity. Specify multiple times '
'for increased diagnostic output')
parser.add_argument('--version', action='version',
version='%(prog)s {}'.format(version),
help='show the version number and exit')
args = parser.parse_args()
# do stuff here
if __name__ == '__main__':
entry_point()
The argparse module handles the --version
and --help
arguments for you. Since your code is installed and loaded as a proper package, you can use relative imports. Of course, you are free to use import myproject
as well.
I usually do my __init__.py file a little differently. I follow the what the standard sys module does:
version_info = (0, 0, 0)
version = '.'.join(str(c) for c in version_info)
This makes it possible to use version_info
to compare against the numeric version like version_info > (1, 0)
which has some nice benefits.
Here's an example of the package in action:
$ python3.4 -mvenv env
$ env/bin/python setup.py install
$ env/bin/my-script --help
usage: my-script [-h] [--verbose] [--version]
Something ... something short
optional arguments:
-h, --help show this help message and exit
--verbose, -v increase verbosity. Specify multiple times for increased
diagnostic output
--version show the version number and exit
Bacon ipsum dolor amet occaecat labore qui, ad veniam boudin capicola flank.
Dolore rump jerky magna sirloin pancetta. Voluptate anim non minim nostrud
ham. Excepteur kevin turkey officia kielbasa pastrami ad ham nostrud meatball
tongue magna t-bone. Chuck salami mollit, fatback pig velit officia ut.
Cupidatat nulla jowl, tail chicken occaecat excepteur pig beef salami non.
Kevin cupim bresaola filet mignon enim. Kielbasa non occaecat flank t-bone ad,
sunt in tail esse deserunt id duis. Ut boudin turducken, pariatur labore
veniam lorem proident culpa laborum. Hamburger swine sunt aliqua, et bacon
shoulder jerky cillum. Meatloaf sed pork belly, dolore corned beef in
consectetur enim ball tip. Fugiat ribeye eiusmod sirloin ground round boudin
shoulder voluptate, reprehenderit tongue landjaeger hamburger. Fatback nisi
occaecat, bacon brisket consequat filet mignon fugiat laboris turducken eu. Ad
tempor frankfurter reprehenderit est corned beef voluptate.
$
$ env/bin/my-script --version
my-script 0.0.0
Then to run myproject/cli.py
as a standalone script:
$ python -m myproject.cli --version
cli.py 0.0.0
from . import __version__
\$\endgroup\$