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

9
我正在使用Windows 7下的Spyder 2.3.1,并在Rasperry Pi RASPBIAN Linux OS上运行iPython 2.3内核。我可以使用.json文件和本教程(Remote ipython console)连接到外部内核。但现在怎么办?如果我运行一个脚本(F5),那么内核会尝试像这样执行脚本:
%run "C:\test.py"

错误: 找不到文件u'C:\\test.py'

当然,这会导致一个错误,因为脚本位于我的机器上,而不是远程机器/树莓派的机器上。我该如何告诉Spyder先将脚本复制到远程机器上,然后在那里执行它呢?

如果我选中"这是远程内核"复选框,我就无法再连接到现有的内核。那个框是什么意思?它会在执行之前通过SSH将脚本复制到远程机器吗? 如果我输入了SSH登录信息,就会收到"似乎内核意外死亡"错误。

4个回答

6
您提到的教程有点过时,因为Spyder现在可以连接远程内核。选中“这是一个远程内核”复选框后,您可以输入ssh连接凭据。除非您已手动打开所需的ssh隧道以转发远程内核的进程端口,否则您需要此选项。
另外,ipython连接信息(json文件)必须与运行在您的树莓派上的远程内核相对应。
最后,目前没有办法在点击运行时复制本地计算机上的脚本。更好的方法实际上是反向操作:使用sshfs之类的工具挂载您的树莓派文件系统并直接编辑它们。计划在Spyder中实现sftp客户端,以便您不需要这样做,并且您将能够从Spyder的文件资源管理器中浏览远程文件系统。
总结一下:
1)假设您已登录树莓派,请使用ipython kernel启动本地IPython内核。它应该给出要使用的json文件的名称,您应该将其复制到本地计算机。
2)在本地计算机上的Spyder中,使用json文件和您的ssh凭据连接到远程内核。
我知道这很麻烦,但这是第一步..

假设我通过一个已经存在的json文件连接到远程机器上的iPython内核。这已经可以在没有“这是一个远程内核”复选框的情况下工作了。为什么我需要输入任何SSH凭据呢?那么Spider会登录到我的树莓派上并在那里启动一个ipython内核,然后为我获取json文件吗?我使用samba来加载树莓派主目录中的脚本。然后连接到内核。所以我可以在本地编辑文件,然后切换到ipython控制台,手动“运行xyz.py”(不用F5)。好的,这应该可以工作。谢谢! - venti
如果您正在使用无密码的ssh连接,那么您不需要勾选 这是一个远程内核 的选项。我猜这就是您的设置,否则我不明白您是如何连接到您的树莓派的。无论如何,这个功能可以帮助用户打开ssh隧道,以便他们可以自动连接到其他机器上的内核。但如果您不需要它,那么您不需要担心它。 - Carlos Cordoba

4

site-packages\spyderlib 目录中搜索关键字 %run 后,我发现了构建 %run 命令的方法(在 site-packages\spyderlib\plugins\ipythonconsole.py 中):

    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: 驱动器。


你能提供更多细节吗?当你按下F5时,似乎你的Windows Spyder会尝试从远程机器复制代码并在Windows上执行它?难道你不需要打开SSH连接才能将执行命令发送到远程主机吗? - MichaelSB
我设置了Spyder以使用OP提到的JSON文件连接到远程IPython内核,当按下F5时,Spyder会将%run filepath发送到IPython内核。OP遇到错误是因为远程机器上不存在该文件路径,我将Samba文件共享映射到Z:驱动器,以便远程机器可以访问。 - Roy Cai
第二部分(抱歉,我不小心点击了提交按钮):在命令发送之前,远程机器上有相同的文件(在Spyder还保存了该文件),我答案中的代码将本地文件路径转换为远程文件路径。至于第二个问题,我认为SSH并不是必需的,但我确实在Spyder中使用了SSH选项,但我认为它只做端口转发(因为远程机器上有防火墙)。 - Roy Cai
我明白了,谢谢!我在远程Ubuntu服务器上启动了内核,并将相应的json文件复制到了我的Windows机器上。然后我在“连接到现有内核”对话框中输入了信息,但是当我单击连接时,它显示“无法打开SSH隧道,Paramiko不可用”。下一步该怎么办? - MichaelSB
1
只需要在本地使用 pip install Paramiko 命令进行安装即可,根据你的 Python site-packages 位置不同,你可能需要以管理员身份运行 cmd 命令进行安装。 - Roy Cai
我创建了一个助手,通过重新定义%run来实现这一点,如果有人感兴趣,请访问https://github.com/aulemahal/RunElsewhere。 - Aule Mahal

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,可以将文件的完整内容发送到控制台并一次性进行评估。

太酷了!我不知道那个。它有效。不幸的是,我遇到了一个问题,你不能STRG+C远程内核。在我的应用程序中,我无限期地在一些外部LED条上运行动画。如果你按下STRG+C,spyder会告诉你“---------------------------IPython---------------------------Kernel process is either remote or unspecified. Cannot interrupt---------------------------OK ---------------------------”,所以我将更改程序,在Raspberry的PWM GPIO引脚上写入一些周期后结束循环。 - venti
1
对不起,现在无法中断外部核心。关于此问题,请参阅此IPython问题进行讨论。 - Carlos Cordoba

2
我想发表我的第一篇文章,更新Roy Cai在Spyder 4中的答案,以防有人寻找。对我而言,Roy的答案完美地解决了问题。 Spyder 4将相关代码从他编写答案时的位置移动到\Lib\site-packages\spyder\plugins\ipythonconsole,而python文件则为plugin.py。
除此之外,其他所有操作都与过去相同——插入修改代码的位置相同,并且同样的更新修复了它。
(顺便说一下,在Spyder 4中保存登录远程内核的登录信息的功能真是太棒了!)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接