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

a1o7rhls  于 2022-11-11  发布在  Python
关注(0)|答案(6)|浏览(225)

我想在python脚本中调用一个编辑器来请求用户输入,就像crontab egit 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脚本的i/o进入正在运行的vim副本,而且我无法找到一种方法将i/o传递给vim。

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

从python调用CLI程序,将控制权交给它,然后在完成后将它传递回来的最佳方式是什么?

ne5o7dgx

ne5o7dgx1#

调用$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()

这里的优点是库可以处理临时文件的创建和删除。

3bygqnnd

3bygqnnd2#

在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
nzkunb0c

nzkunb0c3#

Package 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

pes8fvy9

pes8fvy94#

click是一个很好的命令行处理库,它有一些实用工具,click.edit()是可移植的,并且使用EDITOR环境变量。我在编辑器中输入了stuff这一行。注意,它是以字符串的形式返回的。不错。

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

查看文档https://click.palletsprojects.com/en/7.x/utils/#launching-editors我的整个经历:

/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.
>>> import click
>>> click.edit()
'stuff\n'
>>>
f8rj6qna

f8rj6qna5#

PIPE是问题所在。VIM是一个依赖于stdin/stdout通道是终端而不是文件或管道的应用程序。删除stdin/stdout参数对我很有效。
我会避免使用os.system,因为它应该被subprocess模块取代。

uoifb46i

uoifb46i6#

接受的答案对我不起作用。edited_message保持与initial_message相同,正如评论中所解释的,这是由vim保存策略造成的。
有可能的变通方法,但它们不能移植到其他编辑器。相反,我强烈建议使用click.edit函数。使用它,您的代码将看起来像这样:

import click

initial_message = "edit me!"
edited_message = click.edit(initial_message)
print(edited_message)

Click是一个第三方库,但如果您正在编写控制台脚本,则可能无论如何都应该使用它。click to argparserequests to urllib相同。

相关问题