|
184 | 184 | $ python3.9 options.py -f '22' |
185 | 185 | usage: options.py [-h] [-f F] [-b] [-o] [-x] [-v] ip_expr |
186 | 186 | options.py: error: the following arguments are required: ip_expr |
187 | | -</code></pre><h3><a class=header href=#accepting-stdin id=accepting-stdin>Accepting stdin</a></h3><p>The final feature to be added is the ability to accept both <code>stdin</code> and argument value as the input expression. The modified script is shown below.<pre><code class=language-python># py_calc.py |
188 | | -import argparse, sys, fileinput |
| 187 | +</code></pre><h3><a class=header href=#accepting-stdin id=accepting-stdin>Accepting stdin</a></h3><p>The final feature to be added is the ability to accept both <code>stdin</code> and argument value as the input expression. The <code>sys.stdin</code> filehandle can be used to read <code>stdin</code> data. The modified script is shown below.<pre><code class=language-python># py_calc.py |
| 188 | +import argparse, sys |
189 | 189 |
|
190 | 190 | parser = argparse.ArgumentParser() |
191 | 191 | parser.add_argument('ip_expr', nargs='?', |
|
203 | 203 | args = parser.parse_args() |
204 | 204 |
|
205 | 205 | if args.ip_expr in (None, '-'): |
206 | | - del sys.argv[1:] |
207 | | - args.ip_expr = fileinput.input().readline().strip() |
| 206 | + args.ip_expr = sys.stdin.readline().strip() |
208 | 207 |
|
209 | 208 | try: |
210 | 209 | result = eval(args.ip_expr) |
|
224 | 223 | print(result) |
225 | 224 | except (NameError, SyntaxError): |
226 | 225 | sys.exit("Error: Not a valid input expression") |
227 | | -</code></pre><p>The <code>nargs</code> parameter allows to specify how many arguments can be accepted with a single action. You can use an integer value to get that many arguments as a list or use specific regular expression like metacharacter to indicate varying number of arguments. The <code>ip_expr</code> argument is made optional here by setting <code>nargs</code> to <code>?</code>. If <code>ip_expr</code> isn't passed as an argument by the user, the attribute will get <code>None</code> as the value. The <code>-</code> character is often used to indicate <code>stdin</code> as the input data. So, if <code>ip_expr</code> is <code>None</code> or <code>-</code>, the code will try to read a line from <code>stdin</code> as the input expression.<p>Quoting from <a href=https://docs.python.org/3/library/fileinput.html>docs.python: fileinput</a>:<blockquote><p>... iterates over the lines of all files listed in <code>sys.argv[1:]</code>, defaulting to <code>sys.stdin</code> if the list is empty.</blockquote><p>To ensure the list is empty and options like <code>-f</code> doesn't get treated as filename, <code>del sys.argv[1:]</code> is used here. Since <code>parse_args()</code> has already processed <code>sys.argv</code> values, this is a safe choice to make. The <code>strip()</code> string method is applied to the <code>stdin</code> data to prevent newlines from messing up the output for <code>-v</code> option. Rest of the code is the same as seen before.<p>The help documentation for this script is shown below. The only difference is that the input expression is now optional as indicated by <code>[ip_expr]</code>.<pre><code class=language-bash>$ python3.9 py_calc.py -h |
| 226 | +</code></pre><p>The <code>nargs</code> parameter allows to specify how many arguments can be accepted with a single action. You can use an integer value to get that many arguments as a list or use specific regular expression like metacharacter to indicate varying number of arguments. The <code>ip_expr</code> argument is made optional here by setting <code>nargs</code> to <code>?</code>.<p>If <code>ip_expr</code> isn't passed as an argument by the user, the attribute will get <code>None</code> as the value. The <code>-</code> character is often used to indicate <code>stdin</code> as the input data. So, if <code>ip_expr</code> is <code>None</code> or <code>-</code>, the code will try to read a line from <code>stdin</code> as the input expression. The <code>strip()</code> string method is applied to the <code>stdin</code> data mainly to prevent newline from messing up the output for <code>-v</code> option. Rest of the code is the same as seen before.<p>The help documentation for this script is shown below. The only difference is that the input expression is now optional as indicated by <code>[ip_expr]</code>.<pre><code class=language-bash>$ python3.9 py_calc.py -h |
228 | 227 | usage: py_calc.py [-h] [-f F] [-b] [-o] [-x] [-v] [ip_expr] |
229 | 228 |
|
230 | 229 | positional arguments: |
|
246 | 245 | 43 / 5 |
247 | 246 | 8.6 |
248 | 247 |
|
249 | | -# expression passed as argument, works the same as seen before |
250 | | -$ python3.9 py_calc.py '5 % 2' |
251 | | -1 |
252 | | -</code></pre><p>Without <code>del sys.argv[1:]</code>, the below examples would have failed as the options would have been treated as filenames by the <code>fileinput</code> module.<pre><code class=language-bash>$ echo '0b101 + 3' | python3.9 py_calc.py -vx |
| 248 | +# strip() will remove whitespace from start/end of string |
| 249 | +$ echo ' 0b101 + 3' | python3.9 py_calc.py -vx |
253 | 250 | 0b101 + 3 = 0x8 |
254 | 251 |
|
255 | 252 | $ echo '0b101 + 3' | python3.9 py_calc.py -vx - |
256 | 253 | 0b101 + 3 = 0x8 |
| 254 | + |
| 255 | +# expression passed as argument, works the same as seen before |
| 256 | +$ python3.9 py_calc.py '5 % 2' |
| 257 | +1 |
257 | 258 | </code></pre><h3><a class=header href=#shortcuts id=shortcuts>Shortcuts</a></h3><p>To simplify calling the Python CLI calculator, you can create an alias or an executable Python script.<p>Use absolute path of the script to create the alias and add it to <code>.bashrc</code>, so that it will work from any working directory. The path used below would differ for you.<pre><code class=language-bash>alias pc='python3.9 /home/learnbyexample/python_projs/py_calc.py' |
258 | 259 | </code></pre><p>To create an executable, you'll have to first add a <a href=https://en.wikipedia.org/wiki/Shebang_(Unix)>shebang</a> as the first line of the Python script. You can use <code>type</code> built-in command to get the path of the Python interpreter.<pre><code class=language-bash>$ type python3.9 |
259 | 260 | python3.9 is /usr/local/bin/python3.9 |
|
0 commit comments