Call a text-editor from within a Python script to get user input Motivation

I'd like to know how integrate the use of text editors (e.g. emacs, vim, etc.) into command-line Python programs.

Features

I'd like to be able to do the following:


Call a text editor from within a program in order to edit a file or buffer
Regain control after the text editor exits
Use temporary files, i.e. don't leave anything lying around after the program exits
Prepopulate the file or buffer with data
Get the edited text back for use in the program


Implementation

I wrote a small module named callvim.py (betraying my preferred choice of text editor) which creates a temporary file, populates it with some text, opens it with a text editor (defaults to vim), and prints the modified text:

#!/usr/bin/env python
# -*- encoding: ascii -*-
"""callvim.py

Demonstrates calling a text-editor (e.g. Vim) from within a Python script,
including passing input to the editor and reading output from the editor.
"""

import tempfile
import os
from subprocess import call

# Get the text editor from the shell, otherwise default to Vim
EDITOR = os.environ.get('EDITOR','vim')

# Set initial input with which to populate the buffer
initial_message = "Hello world!"

# Open a temporary file to communicate through (`tempfile` should avoid any filename conflicts)
#
# NOTE: Don't autodelete the file on close!
#       We want to reopen the file incase the editor uses a swap-file.
#
with tempfile.NamedTemporaryFile(suffix=".tmp", delete=False) as tf:

    # Write the initial content to the file I/O buffer
    tf.write(initial_message)

    # Flush the I/O buffer to make sure the data is written to the file
    tf.flush()

    # Open the file with the text editor
    call([EDITOR, tf.name])

# Reopen the file to read the edited data
with open(tf.name, 'r') as tf:

    # Read the file data into a variable
    edited_message = tf.read()

    # Output the data
    print(edited_message)
click is a great library for command line processing and it has some utilities, click.edit() is portable and uses the EDITOR environment variable.  I typed the line, stuff, into the editor.  Notice it is returned as a string. Nice.

So, rather then write any code, you could consider replacing what your working on with these two lines:

(venv) /tmp/editor $ export EDITOR='=mvim -f'
(venv) /tmp/editor $ python
&gt;&gt;&gt; import click
&gt;&gt;&gt; click.edit()
'stuff\n'


Check out the docs https://click.palletsprojects.com/en/7.x/utils/#launching-editors  My entire experience:

/tmp $ mkdir editor
/tmp $ cd editor
/tmp/editor $ python3 -m venv venv
/tmp/editor $ source venv/bin/activate
(venv) /tmp/editor $ pip install click
Collecting click
  Using cached https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl
Installing collected packages: click
Successfully installed click-7.0
You are using pip version 19.0.3, however version 19.3.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(venv) /tmp/editor $ export EDITOR='=mvim -f'
(venv) /tmp/editor $ python
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import click
&gt;&gt;&gt; click.edit()
'stuff\n'
&gt;&gt;&gt;


I would check out the source code for click.edit() if you want to write your own.