Recipe 10.6. Spawning an Editor from a Script
Credit: Larry Price, Peter Cogolo
Problem
You want users to work
with their favorite text-editing programs to edit text files, to
provide input to your script.
Solution
Module
tempfile lets you create temporary files, and
module os has many tools to check the environment
and to work with files and external programs, such as text editors. A
couple of functions can wrap this functionality into an easy-to-use
form:
import sys, os, tempfile
def what_editor( ):
editor = os.getenv('VISUAL') or os.getenv('EDITOR')
if not editor:
if sys.platform == 'windows':
editor = 'Notepad.Exe'
else:
editor = 'vi'
return editor
def edited_text(starting_text=''):
temp_fd, temp_filename = tempfile.mkstemp(text=True)
os.write(temp_fd, starting_text)
os.close(temp_fd)
editor = what_editor( )
x = os.spawnlp(os.P_WAIT, editor, editor, temp_filename)
if x:
raise RuntimeError, "Can't run %s %s (%s)" % (editor, temp_filename, x)
result = open(temp_filename).read( )
os.unlink(temp_filename)
return result
if _ _name_ _=='_ _main_ _':
text = edited_text('''Edit this text a little,
go ahead,
it's just a demonstration, after all...!
''')
print 'Edited text is:', text
Discussion
Your scripts may often need a substantial amount of textual input
from the user. Letting users edit the text with their favorite text
editor is an excellent feature for your script to have, and this
recipe shows how you can obtain it. I have used variants of this
approach for such purposes as adjusting configuration files, writing
blog posts, and sending emails.If your scripts do not need to run on Windows, a more secure and
slightly simpler way to code function edited_text is
available:
def edited_text(starting_text=''):Unfortunately, this alternative relies on the editor
temp_file = tempfile.NamedTemporaryFile( )
temp_file.write(starting_text)
temp_file.seek(0)
editor = what_editor( )
x = os.spawnlp(os.P_WAIT, editor, editor, temp_file.name)
if x:
raise RuntimeError, "Can't run %s %s (%s)" % (editor, temp_file.name, x)
return temp_file.read( )
we're spawning being able to open and modify the
temporary file while we are holding that file open, and this
capability is not supported on most versions of Windows. The version
of edited_text given in the recipe is more portable.When you're using this recipe to edit text files
that must respect some kind of syntax or other constraints, such as a
configuration file, you can make your script simpler and more
effective by using a cycle of "input/parse/re-edit
in case of errors," providing immediate feedback to
users when you can diagnose they've made a mistake
in editing the file. Ideally, in such cases, you should reopen the
editor already pointing at the line in error, which is possible with
most Unix editors by passing them a first argument such as
'+23', specifying that they start editing at line
23, before the filename argument. Unfortunately, such an argument
would confuse many Windows editors, so you have to make some hard
decisions here (if you do need to support Windows).
See Also
Documentation for modules tempfile and
os in the Library Reference
and Python in a Nutshell.