Spyder:如何在本地编辑Python脚本并在远程内核上执行?
我在Windows 7上使用Spyder 2.3.1,并且在树莓派的RASPBIAN Linux操作系统上运行着iPython 2.3内核。
我可以通过一个.json文件连接到外部内核,参考这个教程:远程ipython控制台
但是接下来该怎么办呢?如果我按下“运行”脚本的快捷键(F5),那么内核会尝试像这样执行脚本:
%run "C:\test.py"
错误:文件 u'C:\\test.py'
找不到。
当然会出现这个错误,因为这个脚本在我电脑的C盘上,而不是在远程的树莓派上。我该如何告诉Spyder先把脚本复制到远程机器上,然后在那里执行呢?
如果我勾选了“这是一个远程内核”的复选框,我就无法再连接到现有的内核了。这个选项是什么意思呢?它会在执行之前通过SSH把脚本复制到远程机器上吗?如果我输入SSH登录信息,就会出现“内核似乎意外死亡”的错误。
4 个回答
我想发个帖子,更新一下Roy Cai关于Spyder 4的回答,以防有人需要这个信息。Roy的回答对我来说完全没问题。不过,Spyder 4把相关的代码位置换了地方,跟他写回答时不一样了。现在这个方法在\Lib\site-packages\spyder\plugins\ipythonconsole里,具体的文件是plugin.py。
其他的功能和以前一样,插入修改后的代码的位置也没变,更新的方法还是能解决问题。
(顺便说一句,Spyder 4现在可以保存登录信息,用来登录远程内核,真是太棒了!)
还有一个选择是使用Spyder的单元格功能,把你文件里的所有内容发送到IPython控制台。我觉得这比用Samba或sshfs挂载远程文件系统要简单,特别是当那样做不太可能或者很麻烦的时候。
单元格是通过在文件中添加类似 # %%
的行来定义的。例如,假设你的文件是:
# -*- coding: utf-8 -*-
def f(x):
print(x + x)
f(5)
那么你可以在底部添加一个单元格,像这样:
# -*- coding: utf-8 -*-
def f(x):
print(x + x)
f(5)
# %%
然后只需按 Ctrl + Enter 在单元格行上方,文件的全部内容就会一次性发送到控制台并进行计算。
我在 site-packages\spyderlib
这个文件夹里搜索了关键词 %run
,找到了一个方法(在 site-packages\spyderlib\plugins\ipythonconsole.py
文件里),这个方法是用来构建 %run
命令的:
def run_script_in_current_client(self, filename, wdir, args, debug):
"""Run script in current client, if any"""
norm = lambda text: remove_backslashes(to_text_string(text))
client = self.get_current_client()
if client is not None:
# Internal kernels, use runfile
if client.kernel_widget_id is not None:
line = "%s('%s'" % ('debugfile' if debug else 'runfile',
norm(filename))
if args:
line += ", args='%s'" % norm(args)
if wdir:
line += ", wdir='%s'" % norm(wdir)
line += ")"
else: # External kernels, use %run
line = "%run "
if debug:
line += "-d "
line += "\"%s\"" % to_text_string(filename)
if args:
line += " %s" % norm(args)
self.execute_python_code(line)
self.visibility_changed(True)
self.raise_()
else:
#XXX: not sure it can really happen
QMessageBox.warning(self, _('Warning'),
_("No IPython console is currently available to run <b>%s</b>."
"<br><br>Please open a new one and try again."
) % osp.basename(filename), QMessageBox.Ok)
我在 else: # External kernels, use %run
之后添加了以下代码,用来转换路径:
# ----added to remap local dir to remote dir-------
localpath = "Z:\wk"
remotepath = "/mnt/sdb1/wk"
if localpath in filename:
# convert path to linux path
filename = filename.replace(localpath, remotepath)
filename = filename.replace("\\", "/")
# ----- END mod
现在,当我按下 F5 键时,它会在远程机器上运行这个文件。我使用的是 Spyder 2.3.9
,并且已经把 samba 共享映射到了 z: 盘。
你提到的教程有点过时了,因为现在Spyder可以连接到远程内核了。
当你勾选“这是一个远程内核”这个选项时,会出现一个对话框,你可以在里面输入你的ssh连接信息。
(除非你手动打开了需要的ssh隧道来转发远程内核的进程端口,否则你需要这些信息……)
另外,ipython连接信息(也就是json文件)必须和你在树莓派上运行的远程内核对应。
最后,目前没有办法在你点击运行时把本地电脑上的脚本复制过去。其实更好的方法是反过来:使用像sshfs这样的工具挂载你的树莓派文件系统,然后直接在里面编辑。计划是将来在Spyder中实现一个sftp客户端,这样就不需要手动操作了,你可以直接通过Spyder的文件浏览器查看远程文件系统。
总结一下:
1)假设你已经登录到你的树莓派,启动一个本地的IPython内核,使用命令 ipython kernel。这样会给你一个json文件的名字,你需要把它复制到你的本地电脑上。
2)在你本地电脑上的Spyder中,使用那个json文件和你的ssh凭证连接到远程内核。
我知道这有点麻烦,但这是第一步……