簡體   English   中英

使用Python子進程中的Vim編輯臨時文件在Mac OS上無法正常工作

[英]Editing temporary file with Vim in Python subprocess not working as expected on Mac OS

我最初的目標是通過Python腳本中的命令行文本編輯器獲取用戶輸入。 更具體地說,我的計划是創建一個臨時文件並用一些預先寫好的文本填充它,用文本編輯器打開文件並允許用戶修改文件內容,在用戶退出后從文件中讀取數據編輯器,然后最后刪除文件后全部刪除。

我似乎已經找到了一種方法來做到這一點,這對我有用,但一路上我嘗試了幾種不起作用的方法,我想知道究竟為什么。

考慮以下Python腳本(從這篇文章中略微修改的腳本版本):

#!/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計算機(運行macOS 10.12)和Debian計算機(運行Debian 8.8)上運行。 兩台計算機都安裝了相同(次要)的Vim版本(Vim 7.4)。

當我在Debian 8(Jessie)機器上使用EDITOR=vim運行此腳本時,它按預期工作。 我被Vim和一個包含字符串“Hello world!”的緩沖區提示。 在編輯緩沖區以包含字符串“Goodbye world!”,保存文件並退出Vim之后,我看到字符串“Goodbye world!” 打印到控制台。

當我在我的macOS 10.12(Sierra)機器上運行相同的腳本時,它似乎不起作用。 同樣的程序導致“Hello world!” 在屏幕上顯示 - 就像在編輯文件之前正在讀取文件一樣。

但是如果在我的Mac上使用EDITOR=nano運行腳本,那么一切似乎都按預期工作。

我嘗試使用tempfile模塊中的不同方法(例如使用tempfile.TemporaryFile()tempfile.mkstemp() )對此腳本進行了一些變化,結果相同。

現在考慮以下替代腳本:

#!/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 subprocess
import os

# Create a temporary file and write some default text
file_path = "tempfile"
file_handle = open(file_path, "w")
file_handle.write("Hello world!")
file_handle.close()

# Open the file with Vim
subprocess.call(["vim", file_path])

# Rewind to the beginning of the file
file_handle = open(file_path, 'r')

# Read the data from the file
data = file_handle.read()

# Close the temporary file
file_handle.close()

# Delete the temporary file
os.remove(file_path)

# Print the data
print(data)

這個避免使用tempfile模塊的腳本似乎在兩個平台上都能保持一致。

因此,由於某些原因,這個腳本可能因為Vim和tempfile Python模塊在macOS上的交互方式而失敗。 這里發生了什么?

發生這種情況是因為你的第二個腳本在調用vim之前關閉文件句柄,然后在之后打開一個新腳本,而第一個腳本則沒有。 它與tempfile模塊本身無關。 此代碼按預期工作:

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使用交換文件(參見例如此處 ),但我不推薦它們。 只需記住在vim完成業務后更新文件句柄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM