2011-06-10 77 views
31

我想調用python腳本中的編輯器來請求用戶輸入,就像crontab egit commit一樣。從python腳本中調用EDITOR(vim)

這是我迄今爲止運行的一個片段。 (在將來,我可能會使用$ 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,似乎讓我的I/O與python腳本從進入vim的正在運行的副本,我無法找到一種方法來通過I/O通過vim。我收到以下錯誤。

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

什麼是從python調用CLI程序,手動控制它,然後在完成後將其傳回的最佳方式?

回答

55

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

好事,庫負責創建和刪除臨時文件。

+0

太棒了!我的一個修改是在未設置EDITOR的情況下添加回退:編輯器= os.environ.get('編輯器')如果os.environ.get('編輯器')其他'vim'。如果您希望接受它,我已將此作爲編輯提交給您。 – sam 2011-06-10 19:25:40

+0

感謝@sam和@unutbu的建議。我不知道你可以用一個未設置的'$ EDITOR'逃脫:) – progo 2011-06-10 20:40:11

+0

+1,即使由於某種原因,EDITOR沒有在我的Ubuntu上設置。奇怪的(r)'$ editor'啓動納米,其中'crontab -e'啓動vim ... – FMCorz 2014-04-09 12:34:34

2

PIPE是問題所在。 VIM是一個應用程序,它依賴於stdin/stdout通道是終端而不是文件或管道。刪除標準輸入/標準輸出參數爲我工作。

我會避免使用os.system,因爲它should被子進程模塊取代。

+0

感謝dmeister。但它不適用於我。我有以下代碼。這是你的意思嗎? 'edit_call = [「vim」,tmp_file]; \t edit = subprocess.Popen(edit_call)' – sam 2011-06-10 17:05:14

+0

@sam是的,這就是我的意思 – dmeister 2011-06-10 17:08:49

+0

@Sam發生了什麼? – dmeister 2011-06-10 17:26:57

3

在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 
+0

收到空白字符回來。試着用'print(edited_message)'返回'b''。這是通過OS X終端與Python 3.5.2 – 2016-12-08 17:00:46

0

包裝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