我最初的目标是通过命令行文本编辑器从Python脚本中获取用户输入。更具体地说,我的计划是创建一个临时文件并用一些预先编写的文本填充它,用文本编辑器打开文件并允许用户修改文件内容,在用户退出编辑器后从文件中读取数据,最后在文件结束后删除该文件。在
我似乎找到了一种对我有用的方法,但在这一过程中,我尝试了几种方法,但都没有奏效,我想确切地了解原因。在
考虑下面的Python脚本(取自this post的稍微修改的脚本版本):
#!/usr/bin/env python2
# -*- 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
with tempfile.NamedTemporaryFile(suffix=".tmp") 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])
# Rewind the file offset to the beginning of the file
tf.seek(0)
# Read the file data into a variable
edited_message = tf.read()
# Output the data
print(edited_message)
到目前为止,我已经尝试在两种不同的环境中运行这个脚本:在macOS计算机上(运行macos10.12)和在Debian计算机上(运行Debian 8.8)。两台计算机都安装了相同(次要)版本的Vim(Vim 7.4)。在
当我用EDITOR=vim
在我的debian8(Jessie)机器上运行这个脚本时,它会按预期工作。系统会提示我使用Vim和一个包含字符串“helloworld!”的缓冲区。在编辑缓冲区以包含字符串“再见,世界!”,保存文件,退出Vim,我看到字符串“再见,世界!”打印到控制台。在
当我在我的macos10.12(Sierra)机器上运行相同的脚本时,它似乎不起作用。同样的程序会产生“Hello world!”在屏幕上显示-就好像文件在被编辑之前被读取一样。在
但是,如果用EDITOR=nano
在我的Mac上运行脚本,那么一切似乎又像预期的那样正常工作。在
我使用tempfile
模块中的不同方法(例如使用tempfile.TemporaryFile()
和{
现在考虑以下替代脚本:
^{pr2}$这个脚本避免使用tempfile
模块,似乎在两个平台上都是一致的。在
因此,由于某种原因,这个脚本可能会失败,这与Vim和tempfile
Python模块在macOS上的交互方式有关。这是怎么回事?在
这是因为您的第二个脚本在调用
vim
之前关闭了文件句柄,然后在之后打开了一个新的句柄,而第一个脚本没有这样做。此代码按预期工作:注意对
NamedTemporaryFile
的调用中的delete=False
,它确保在我们第一次关闭文件时不会删除它(稍后我们必须用os.unlink
手动删除它)。在我认为这里发生的是
vim
没有在适当的地方编辑你的文件,而是在写一个交换文件。当您保存并退出时,vim
会将原始文件替换为已编辑的文件,使您的文件句柄指向未经编辑的旧文件。有一些方法可以防止vim
使用交换文件(请参见,例如here),但我不推荐它们。只需记住在vim
完成任务后更新文件句柄。在相关问题 更多 >
编程相关推荐