Spyder:如何在本地编辑Python脚本并在远程内核上执行?

9 投票
4 回答
21315 浏览
提问于 2025-05-01 03:35

我在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 个回答

2

我想发个帖子,更新一下Roy Cai关于Spyder 4的回答,以防有人需要这个信息。Roy的回答对我来说完全没问题。不过,Spyder 4把相关的代码位置换了地方,跟他写回答时不一样了。现在这个方法在\Lib\site-packages\spyder\plugins\ipythonconsole里,具体的文件是plugin.py。

其他的功能和以前一样,插入修改后的代码的位置也没变,更新的方法还是能解决问题。

(顺便说一句,Spyder 4现在可以保存登录信息,用来登录远程内核,真是太棒了!)

2

还有一个选择是使用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 在单元格行上方,文件的全部内容就会一次性发送到控制台并进行计算。

4

我在 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: 盘。

6

你提到的教程有点过时了,因为现在Spyder可以连接到远程内核了。

当你勾选“这是一个远程内核”这个选项时,会出现一个对话框,你可以在里面输入你的ssh连接信息。
(除非你手动打开了需要的ssh隧道来转发远程内核的进程端口,否则你需要这些信息……)

另外,ipython连接信息(也就是json文件)必须和你在树莓派上运行的远程内核对应。

最后,目前没有办法在你点击运行时把本地电脑上的脚本复制过去。其实更好的方法是反过来:使用像sshfs这样的工具挂载你的树莓派文件系统,然后直接在里面编辑。计划是将来在Spyder中实现一个sftp客户端,这样就不需要手动操作了,你可以直接通过Spyder的文件浏览器查看远程文件系统。

总结一下:

1)假设你已经登录到你的树莓派,启动一个本地的IPython内核,使用命令 ipython kernel。这样会给你一个json文件的名字,你需要把它复制到你的本地电脑上。

2)在你本地电脑上的Spyder中,使用那个json文件和你的ssh凭证连接到远程内核。

我知道这有点麻烦,但这是第一步……

撰写回答