如何从Python脚本启动编辑器(如vim)?

62 投票
6 回答
24668 浏览
提问于 2025-04-16 19:20

我想在一个Python脚本中调用一个编辑器,让用户输入内容,就像crontab e或者git commit那样。

这是我目前运行的一小段代码。(将来,我可能会用$EDITOR代替vim,这样大家可以根据自己的喜好来定制。)

tmp_file = '/tmp/up.'+''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6))
edit_call = [ "vim",tmp_file]
edit = subprocess.Popen(edit_call,stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True )   

我的问题是,使用Popen的时候,似乎无法把Python脚本的输入输出传递到正在运行的vim中,我找不到办法把输入输出直接传给vim。我遇到了以下错误。

Vim: Warning: Output is not to a terminal
Vim: Warning: Input is not from a terminal

从Python调用一个命令行程序,如何把控制权交给它,然后在完成后再把控制权交回来,最好的方法是什么?

6 个回答

8

python-editor

$ pip install python-editor
$ python
>>> import editor
>>> result = editor.edit(contents="text to put in editor\n")

更多详细信息请查看这里: https://github.com/fmoo/python-editor

11

在Python3中,你会看到这样的错误信息:'str' does not support the buffer interface,意思是说字符串不支持缓冲区接口。

$ python3 editor.py
Traceback (most recent call last):
  File "editor.py", line 9, in <module>
    tf.write(initial_message)
  File "/usr/lib/python3.4/tempfile.py", line 399, in func_wrapper
    return func(*args, **kwargs)
TypeError: 'str' does not support the buffer interface

在Python3中,你可以用 initial_message = b"" 来声明一个缓冲字符串。

然后可以使用 edited_message.decode("utf-8") 将这个缓冲区解码成普通字符串。

import sys, tempfile, os
from subprocess import call

EDITOR = os.environ.get('EDITOR','vim') #that easy!

initial_message = b"" # if you want to set up the file somehow

with tempfile.NamedTemporaryFile(suffix=".tmp") as tf:
    tf.write(initial_message)
    tf.flush()
    call([EDITOR, tf.name])

    # do the parsing with `tf` using regular File operations.
    # for instance:
    tf.seek(0)
    edited_message = tf.read()
    print (edited_message.decode("utf-8"))

结果:

$ python3 editor.py
look a string
103

调用 $EDITOR 很简单。我写了这样的代码来打开编辑器:

import sys, tempfile, os
from subprocess import call

EDITOR = os.environ.get('EDITOR', 'vim')  # that easy!

initial_message = ''  # if you want to set up the file somehow

with tempfile.NamedTemporaryFile(suffix=".tmp") as tf:
  tf.write(initial_message)
  tf.flush()
  call([EDITOR, tf.name])

  # do the parsing with `tf` using regular File operations.
  # for instance:
  tf.seek(0)
  edited_message = tf.read()

这里的好处是,这些库会自动处理临时文件的创建和删除。

撰写回答