Я пишу программу PyQt, в которой я хотел бы позволить пользователю запускать предпочитаемый им редактор для заполнения поля TextEdit.
Таким образом, цель состоит в том, чтобы запустить редактор (скажем, vim) извне для файла tmp, а после закрытия редактора получить его контексты в переменную python.
Я нашел несколько похожих вопросов, таких как Открытие vi из Python , вызов EDITOR (vim) из скрипта python , вызов редактора (vim) в питоне . Но все они в «блокирующей» манере, которая работает как команда git commit
. Что мне нужно, так это «неблокирующая» манера (потому что это GUI), что-то вроде функции «Редактировать источник» в zimwiki .
Моя текущая попытка:
import os
import tempfile
import threading
import subprocess
def popenAndCall(onExit, popenArgs):
def runInThread(onExit, popenArgs):
tmppath=popenArgs[-1]
proc = subprocess.Popen(popenArgs)
# this immediately finishes OPENING vim.
rec=proc.wait()
print('# <runInThread>: rec=', rec)
onExit(tmppath)
os.remove(tmppath)
return
thread = threading.Thread(target=runInThread, args=(onExit, popenArgs))
thread.start()
return thread
def openEditor():
fd, filepath=tempfile.mkstemp()
print('filepath=',filepath)
def cb(tmppath):
print('# <cb>: cb tmppath=',tmppath)
with open(tmppath, 'r') as tmp:
lines=tmp.readlines()
for ii in lines:
print('# <cb>: ii',ii)
return
with os.fdopen(fd, 'w') as tmp:
cmdflag='--'
editor_cmd='vim'
cmd=[os.environ['TERMCMD'], cmdflag, editor_cmd, filepath]
print('#cmd = ',cmd)
popenAndCall(cb, cmd)
print('done')
return
if __name__=='__main__':
openEditor()
Я думаю, что это не удалось, потому что Popen.wait()
ждет только до тех пор, пока редактор не откроется, а не до его закрытия. Так что он ничего не захватывает из редактора.
Есть идеи, как это решить? Спасибо!
EDIT:
Я нашел этот ответ , который, я думаю, связан. Я бездельничаю, пытаясь позволить os
ждать process group
, но он все еще не работает. Код ниже:
def popenAndCall(onExit, popenArgs):
def runInThread(onExit, popenArgs):
tmppath=popenArgs[-1]
proc = subprocess.Popen(popenArgs, preexec_fn=os.setsid)
pid=proc.pid
gid=os.getpgid(pid)
#rec=proc.wait()
rec=os.waitid(os.P_PGID, gid, os.WEXITED | os.WSTOPPED)
print('# <runInThread>: rec=', rec, 'pid=',pid, 'gid=',gid)
onExit(tmppath)
os.remove(tmppath)
return
thread = threading.Thread(target=runInThread, args=(onExit, popenArgs))
thread.start()
return thread
Я предполагаю, что gid=os.getpgid(pid)
дает мне идентификатор группы, а os.waitid()
ждет группу. Я тоже попробовал os.waitpid(gid, 0)
, тоже не сработало.
Я на правильном пути?
UPDATE
Кажется, что для некоторых редакторов это работает, например xed
. vim
и gvim
оба не пройдены.