Creating a Terminal Program with Python
Question:
I recently started learning python. I have created some basic webapps with Django and wrote some simple scripts. After using VIM as a Python IDE I really fell I love with “Terminal programs” (is there an official term for this?). Right now I am capable of doing simple things like asking someones age and printing it to the screen. However this comes down to running a .py script and after this script is done the normal bash return. I would like create a program that I can run from the command line and that would allow the same user experience as VIM (one that you open and close). For example I created a simple script to import RSS feeds. It would be cool if I could open my terminal type the name of my program -> program would open -> Then I would like to use commands like :findsomething. Basically have real interaction with my program.
To conclude:
- How would I go about creating such a program?
- What kinds of modules, books or site would you recommend
Answers:
A true command-line program is something in the vein of ls
or grep
; it is started from the command-line, but it’s non-interactive and can be used in pipelines and combined with other programs. A typical command-line program has no interactive user experience, instead relying on shell’s history and init file for customization.
What you want to create is a curses application, that uses the full capabilities of the TTY as an interactive platform, for better or worse. To do that, look up curses.
THe simplest way to do an interactive console application would be:
while True:
command = raw_input('command? ').strip()
if command == 'say_hello':
print('Hello')
elif command == 'other_thing':
print('Doing something else')
elif command == 'quit':
break
else:
print('Invalid Command.')
That’s the basic structure. If you want something more vim-like, you’ll probably need to use the curses library.
You should take a look at the cmd module.
See the Python Cookbook for examples of its use.
On a *nix system (linux/unix),
if you:
$ chmod 0744 your_file.py
-rwxr--r-- your_file.py
and add the path to python as the first line of your_file.py
:
#!/usr/bin/python
or (in my case):
#!/usr/local/bin/python
Once you do that, instead of running it like this:
$ python your_file.py
You can run it like this:
$ ./your_file.py
or even rename it to yourfile
and run it like this:
$ ./yourfile
and if you then copy yourfile
to your bin (i.e. #!/usr/bin/
, or #!/usr/local/bin/
)
you can run it like this:
$ yourfile
Then you can…
Use raw_input()
to solicit and get input from you user.
your_file.py
:
#!/usr/local/bin/python
import os
while(True):
# cntrl-c to quit
input = raw_input('your_prompt$ ')
input = input.split()
if input[0] == 'ls':
dire = '.'
if len(input) > 1:
dire = input[1]
print('n'.join(os.listdir(dire)))
else:
print('error')
your_file.py
use example:
$ chmod 744 your_file.py
$ cp your_file.py /usr/local/bin/your_file
$ your_file
your_prompt$ ls
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ ls .
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ pwd
error
your_prompt$ ^CTraceback (most recent call last):
File "/usr/local/bin/your_file", line 7, in <module>
input = raw_input('your_prompt$ ')
KeyboardInterrupt
$
Grab arguments with sys.argv
from the command line when you run your script:
list_argv.py
:
#!/usr/local/bin/python
import sys
print(sys.argv)
list_argv.py
use example:
$ python list_argv.py
['list_argv.py']
$ python list_argv.py hello
['list_argv.py', 'hello']
$ python list_argv.py hey yo
['list_argv.py', 'hey', 'yo']
$ chmod 744 list_argv.py
$ ./list_argv.py
['./list_argv.py']
$ ./list_argv.py hi
['./list_argv.py', 'hi']
$ ./list_argv.py hey yo
['./list_argv.py', 'hey', 'yo']
$ cp list_argv.py /usr/local/bin/list_argv
$ list_argv hey yo
['/usr/local/bin/list_argv', 'hey', 'yo']
Replace raw_input()
with sys.argv
.
‘your_ls.py’:
#!/usr/local/bin/python
import sys
import os
dire = '.'
if len(sys.argv) > 1:
dire = sys.argv[1]
print('n'.join(os.listdir(dire)))
‘your_ls.py’ use example:
$ chmod 744 your_ls.py
$ cp your_ls.py /usr/local/bin/your_ls
$ your_ls
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
$ your_ls .
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
$ your_ls blah
Traceback (most recent call last):
File "/usr/local/bin/your_ls", line 9, in <module>
print('n'.join(os.listdir(dire)))
OSError: [Errno 2] No such file or directory: 'blah'
Use subprocess.Popen
to access anything you could from the command line.
your_subprocess.py
:
#!/usr/local/bin/python
import os
import subprocess
while(True):
# cntrl-c to quit
input = raw_input('your_prompt$ ')
process = subprocess.Popen(input, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = process.communicate()
print(out)
print(err)
your_subprocess.py
use example:
$ chmod 744 your_subprocess.py
$ cp your_subprocess.py /usr/local/bin/your_subprocess
$ your_subprocess
your_prompt$ ls
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ ls .
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ pwd
/Users/ox/_workspace/cmd_ln
your_prompt$ blah
/bin/sh: blah: command not found
your_prompt$ ^CTraceback (most recent call last):
File "/usr/local/bin/your_subprocess", line 8, in <module>
input = raw_input('your_prompt$ ')
KeyboardInterrupt
$
BREAK STUFF!
😀
HAVE FUN!
-ox
I recently started learning python. I have created some basic webapps with Django and wrote some simple scripts. After using VIM as a Python IDE I really fell I love with “Terminal programs” (is there an official term for this?). Right now I am capable of doing simple things like asking someones age and printing it to the screen. However this comes down to running a .py script and after this script is done the normal bash return. I would like create a program that I can run from the command line and that would allow the same user experience as VIM (one that you open and close). For example I created a simple script to import RSS feeds. It would be cool if I could open my terminal type the name of my program -> program would open -> Then I would like to use commands like :findsomething. Basically have real interaction with my program.
To conclude:
- How would I go about creating such a program?
- What kinds of modules, books or site would you recommend
A true command-line program is something in the vein of ls
or grep
; it is started from the command-line, but it’s non-interactive and can be used in pipelines and combined with other programs. A typical command-line program has no interactive user experience, instead relying on shell’s history and init file for customization.
What you want to create is a curses application, that uses the full capabilities of the TTY as an interactive platform, for better or worse. To do that, look up curses.
THe simplest way to do an interactive console application would be:
while True:
command = raw_input('command? ').strip()
if command == 'say_hello':
print('Hello')
elif command == 'other_thing':
print('Doing something else')
elif command == 'quit':
break
else:
print('Invalid Command.')
That’s the basic structure. If you want something more vim-like, you’ll probably need to use the curses library.
You should take a look at the cmd module.
See the Python Cookbook for examples of its use.
On a *nix system (linux/unix),
if you:
$ chmod 0744 your_file.py
-rwxr--r-- your_file.py
and add the path to python as the first line of your_file.py
:
#!/usr/bin/python
or (in my case):
#!/usr/local/bin/python
Once you do that, instead of running it like this:
$ python your_file.py
You can run it like this:
$ ./your_file.py
or even rename it to yourfile
and run it like this:
$ ./yourfile
and if you then copy yourfile
to your bin (i.e. #!/usr/bin/
, or #!/usr/local/bin/
)
you can run it like this:
$ yourfile
Then you can…
Use raw_input()
to solicit and get input from you user.
your_file.py
:
#!/usr/local/bin/python
import os
while(True):
# cntrl-c to quit
input = raw_input('your_prompt$ ')
input = input.split()
if input[0] == 'ls':
dire = '.'
if len(input) > 1:
dire = input[1]
print('n'.join(os.listdir(dire)))
else:
print('error')
your_file.py
use example:
$ chmod 744 your_file.py
$ cp your_file.py /usr/local/bin/your_file
$ your_file
your_prompt$ ls
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ ls .
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ pwd
error
your_prompt$ ^CTraceback (most recent call last):
File "/usr/local/bin/your_file", line 7, in <module>
input = raw_input('your_prompt$ ')
KeyboardInterrupt
$
Grab arguments with sys.argv
from the command line when you run your script:
list_argv.py
:
#!/usr/local/bin/python
import sys
print(sys.argv)
list_argv.py
use example:
$ python list_argv.py
['list_argv.py']
$ python list_argv.py hello
['list_argv.py', 'hello']
$ python list_argv.py hey yo
['list_argv.py', 'hey', 'yo']
$ chmod 744 list_argv.py
$ ./list_argv.py
['./list_argv.py']
$ ./list_argv.py hi
['./list_argv.py', 'hi']
$ ./list_argv.py hey yo
['./list_argv.py', 'hey', 'yo']
$ cp list_argv.py /usr/local/bin/list_argv
$ list_argv hey yo
['/usr/local/bin/list_argv', 'hey', 'yo']
Replace raw_input()
with sys.argv
.
‘your_ls.py’:
#!/usr/local/bin/python
import sys
import os
dire = '.'
if len(sys.argv) > 1:
dire = sys.argv[1]
print('n'.join(os.listdir(dire)))
‘your_ls.py’ use example:
$ chmod 744 your_ls.py
$ cp your_ls.py /usr/local/bin/your_ls
$ your_ls
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
$ your_ls .
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
$ your_ls blah
Traceback (most recent call last):
File "/usr/local/bin/your_ls", line 9, in <module>
print('n'.join(os.listdir(dire)))
OSError: [Errno 2] No such file or directory: 'blah'
Use subprocess.Popen
to access anything you could from the command line.
your_subprocess.py
:
#!/usr/local/bin/python
import os
import subprocess
while(True):
# cntrl-c to quit
input = raw_input('your_prompt$ ')
process = subprocess.Popen(input, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = process.communicate()
print(out)
print(err)
your_subprocess.py
use example:
$ chmod 744 your_subprocess.py
$ cp your_subprocess.py /usr/local/bin/your_subprocess
$ your_subprocess
your_prompt$ ls
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ ls .
list_argv.py
your_file.py
your_ls.py
your_subprocess.py
your_prompt$ pwd
/Users/ox/_workspace/cmd_ln
your_prompt$ blah
/bin/sh: blah: command not found
your_prompt$ ^CTraceback (most recent call last):
File "/usr/local/bin/your_subprocess", line 8, in <module>
input = raw_input('your_prompt$ ')
KeyboardInterrupt
$
BREAK STUFF!
😀
HAVE FUN!
-ox