在Python子进程中使用Vim编辑临时文件在M上没有按预期工作

2024-04-27 04:20:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我最初的目标是通过命令行文本编辑器从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和tempfilePython模块在macOS上的交互方式有关。这是怎么回事?在


Tags: 文件theto方法用户from脚本message
1条回答
网友
1楼 · 发布于 2024-04-27 04:20:56

这是因为您的第二个脚本在调用vim之前关闭了文件句柄,然后在之后打开了一个新的句柄,而第一个脚本没有这样做。此代码按预期工作:

import tempfile, os
from subprocess import call

initial_message = "Hello world!"

tf = tempfile.NamedTemporaryFile(suffix=".tmp", delete=False)
tf.write(initial_message)
tf.close()

call(['vim', tf.name])

tf = open(tf.name, 'r')
edited_message = tf.read()
tf.close()

os.unlink(tf.name)

print(edited_message)

注意对NamedTemporaryFile的调用中的delete=False,它确保在我们第一次关闭文件时不会删除它(稍后我们必须用os.unlink手动删除它)。在

我认为这里发生的是vim没有在适当的地方编辑你的文件,而是在写一个交换文件。当您保存并退出时,vim会将原始文件替换为已编辑的文件,使您的文件句柄指向未经编辑的旧文件。有一些方法可以防止vim使用交换文件(请参见,例如here),但我不推荐它们。只需记住在vim完成任务后更新文件句柄。在

相关问题 更多 >