自动运行Python时出现“读取行时EOF”错误
我在我的 .vimrc 文件里加了一行代码
map <F4> :w !python<cr>
当我打开 gvim 编辑一个没有命名的 Python 文件时,里面只有两行内容
x=input("which one do you like ? ")
print(x)
我按下 F4,结果出现了 EOF when reading a line
的错误,我该怎么解决呢?
当你添加 map <F4> :w<cr>:!python %<cr>
或者 imap <F4> <Esc>:w <cr>:!python %<cr>
这段代码时,它只能让有名字的文件运行,如果是没有名字的文件,这个设置就不管用了,我该怎么让没有名字的文件也能运行呢?
4 个回答
有一种方法可以在不使用临时文件的情况下做到这一点,可以用一个小的辅助函数来实现:
function! GetContentsForPython()
let contents = join(getline(1,'$'), "\n")
let res = ''
for l in split(contents, '\n')
if len(l)
let res = res . l . ';'
endif
endfor
let res = '"' . escape(res, '"') . '"'
return res
endfunction
noremap <f4> :!python -c <c-r>=GetContentsForPython()<cr><cr>
这个方法会获取当前缓冲区的内容,并把换行符替换成分号,这样你就可以用下面的方式执行它:
python -c "print 'hello'"
可能还有更好的方法来实现这个功能,但对我来说,这个方法是有效的。
我觉得问题出在input()
这一行。Python在等待输入,但找不到任何东西。它到处找,结果只发现了一个文件结束符(EOF)。
因为你的设置里有 :w
,我猜你是想要直接在插入模式下运行脚本,或者在运行之前先保存一下。
在 vim 里,多个命令之间需要用分隔符,比如 <bar>
(也就是 |
),或者在命令之间和之后使用 <CR>
(回车键)。
你可以把下面的两个设置放到你的 .vimrc
文件里,这样无论你是在普通模式还是插入模式下,按 F4
都能满足你的需求。
如果你在普通模式下,可以使用 map
:
map <F4> :w<cr>:!python %<cr>
而在插入模式下,你需要用 imap
,并且按一下 Esc
来退出插入模式:
imap <F4> <Esc>:w <cr>:!python %<cr>
@benjifisher的回答是对的。问题出在输入(函数)上。
:w !python
这个命令是把程序通过标准输入(stdin)传给python(基本上和
echo 'input("x")' | python
在命令行中运行是一样的,但也会失败)。但是,input()
试图从标准输入读取数据,而此时python已经从标准输入读取了程序,标准输入还在尝试从管道中读取。然而,管道已经到达末尾,不会再有新数据。所以,input()
只能读取到文件结束符(EOF)。
为了确认python确实在从标准输入读取数据,我们可以查看:h :w_c
,这会显示文件被传递给命令的标准输入,而这个命令在这里是python。
:w_c :write_c
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command :!.
如果缓冲区里有一些不是从标准输入读取的内容,你的映射就能正常工作。
举个例子,如果未命名的缓冲区包含
print(42)
在vim中运行命令:w !python
会打印出42。
所以问题并不是映射失败。问题在于你的程序不知道怎么获取输入。解决办法是使用一个命名文件,或者不要在vim中编写交互式程序。可以使用python解释器来处理这类情况。