我们可能会在本地主机建立项目和编辑代码,不过一些深度学习任务需要用到 GPU 硬件支持,这时我们需要把代码在 SSH 远程服务器下运行和调试。这种情况下,调试代码,设置断点和监视变量值,就需要用到远程调试。
远程调试是 PyCharm Professional 才支持的功能,Pycharm Community Edtion 并不支持。在这个页面下载 Pycharm Professional。Professional 可以用有效的学生/教师身份申请于在校期间使用。在 Pycharm 界面,如果找不到某些菜单的位置,双击 shift 可以直接进行全局搜索。
配置远程服务器
为了令PyCharm能够连接远程服务器,需要完成配置:1. 服务器地址、端口号、用户名及密码;2. 服务器配置根文件夹和访问它的URL地址;3. 项目的根文件夹、从项目根文件夹拷贝到服务器上的目标文件夹、目标文件夹的URL地址,这三者之间的映射关系。如果以下步骤遇到问题,可以参考官方指引。
1)建立连接
首先,在本地打开项目,配置该项目对应的远程服务器。在主菜单选择 Tools -> Deployment -> Configuration 以打开 Deployment 菜单。菜单左边会显示已保存的一些配置(如果之前没有配置过则没有),点击左上角的 + 以新建一份配置。
先选择文件传输协议(现在连服务器一般用的都是 SSH 协议,所以选择 SFTP,以下流程也是基于 SFTP 协议的,使用其它协议还请参照上面给出的官方指引,而且目前只有 SSH 服务器可以实现远程调试功能)。选择协议后弹出 Create new sever 对话框,为你的服务器起一个名字(不需要和用户名相同),OK 确认。如果取消勾选 visible for only this project,则其之后他项目也可以直接使用这份配置。
配置服务器连接信息
在 SSH configuration 栏输入连接参数,格式为“用户名:密码@地址:端口号”。最新的 PyCahrm 版本没有 SSH configuration 栏,而是把 Host、Port、User Name、Password 这四项分开逐个填写。之后点击 Test Connection 测试连接,如果成功连接,会弹出 “Successfully connected to {address}”。没成功的话,看看是不是连接参数哪里写错了,用 MobaXterm 之类的其它软件测试一下连接。SSH 配置部分如果遇到问题,可进一步参考官方指引。
Root path 为当前用户可见的最底层根目录。如果想访问任何地方,填入“/”。点击后面的 Auto detect 会自动切换到你选择的用户的根目录。
2)建立本地文件到服务器的映射
如果你想建立多个映射关系,可以通过 Add new mapping 实现。更详细的内容参考官方指引。
建立完映射关系后,可以设置文件同步。这会使 PyCharm 在能连接上服务器时,自动同步你的代码等文件到服务器端。设置文件同步的方法如下:
选择 Tools -> Deployment -> Automatic Upload,并在弹出的选框中选择刚才设置的服务器配置。之后再打开 Tools -> Deployment,会看到 Automatic Upload 前面打了个勾,并且后面标注有(Always),再次点击便可取消。实际上,Always 代表,不论是 Pycharm 自动保存还是用户用 Ctrl + S 手动保存,都同时将文件同步到服务器端,如果想切换成 On explicit save action(只在用户手动保存的时候同步),参考官方指引。
Pycharm 只能静默地同步文件内容,不能静默地新建文件,所以在设置好这些之后,会发现服务器上的映射文件夹还是空的。需要先手动上传一次,在 PyCharm 左侧的浏览栏中,右键点击文件或文件夹并选择 Upload to {sever name} 以将其内容上传至服务器对应的文件夹。之后每当编辑本地项目里的文件内容时,服务器上该文件的内容会自动同步。
如果之后新建了文件或者文件夹,发现 PyCharm 没有自动同步,也这样手动同步就好。目前看来可能直接在 PyCharm 的界面里新建的文件会同步,通过 windows 的文件管理系统复制过去的不会同步。如果项目文件夹下有些文件不想同步,再次打开 Tools -> Deployment -> Configuration,在上方选择 Excluded Paths,可以设置不想同步的文件或文件夹。可以通过正则表达式指定这些文件/文件夹,以“;”为分隔符,“*”指代任意数量的字符,“?”指代一个字符。不过只要一开始不上传到服务器,这些文件也不会被同步。
另外,可以在 Pycharm 主界面右侧找到 Remote Host 标签(或Tool -> Deployment -> Browse Remote Host),点击以展开。默认的服务器可能是,点击右边小箭头选择服务器配置以连接刚才设置的服务器,然后就可以在这里浏览服务器上的文件了。
这次配置好,之后就不用重复配置了。新的项目连接到相同的服务器时,只要在 Tools -> Deployment -> Configuration 里选择已有的服务器设置,改一下映射路径即可。
配置远程 Python 解释器
尽管代码在本地主机上,我们需要使用服务器上的 Python 解释器来执行它。如果以下步骤遇到问题,可以参考官方指引。
选择 File -> Settings -> Project:{project name} -> Project Interpreter,以显示本地项目当前应用的解释器,如果未选择,则为。点击右边的设置键(齿轮)选择 Add 以打开 Add Python Interpreter 窗口,选择 SSH Interpreter 并选择 Existing sever configuration,选择刚才设好的服务器设置。
新增远程 SSH 解释器
点击 Next 进入下个界面,现在选择远程 Python 解释器,在 Interpreter 栏内输入解释器的路径。可以勾选 Execute code using this interpreter with root privileges via sudo,这将会让代码以root权限执行,如果勾选了,之后会有一个对话框让你输入 root 密码。在下面的 Sync folders 选择本地项目文件同步的文件夹。选择同步文件夹这一步之前已经为 Deployment 设置过了,这次是为 Debugger 选择,应选择和之前相同的路径。
设置解释器路径
点击 Finish,可以看到现在这个项目的解释器已经被设为了 SSH 远程解释器。正常的话, PyCharm 会识别出这个环境下的所有包,并将它们列出来。
成功设置解释器
如果新的项目需要用到这个解释器,只要在 File -> Settings -> Project: {project name} -> Interpreter 中选择已有的解释器,并更改映射文件夹路径即可。
好耶
现在,项目内的代码已经可以在远程服务器上调试了。可以试着打几个断点,调试一下,监视以下变量,这些都是可以做到的。Pycharm的远程调试配置就完成了。更详细的内容可以参考官方指引。
注意事项
远程调试过程中发现的一些小问题,每次发现就慢慢补充吧。
1. cv2.imshow()报错
由于是远程运行,cv2.imshow() 无法正常工作。报错:qt.qpa.xcb: could not connect to display. qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "{path-to-environment}/lib/python3.8/site-packages/cv2/qt/plugins" even though it was found. This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 目前未解决,只能先不用 imshow 了,想看图的话就 imwrite 保存下来再看吧。
2. 调试时加载不出变量值
如果用到 pytorch,代码在调试时或许会加载不出一些带 tensor 的变量的值,显示 Timeout waiting for response on 113、Loading timeout 或者 Failed collecting data 之类的。虽然不清楚发生这个问题的原理,但是按下面的做应该可以解决:在 File -> Settings -> Build, Excution, Deployment -> Debugger -> Python Debugger 里勾选 Gevent Compatible。我用这个方法能够解决上述问题,具体参考 stackoverflow 上的这个问题的回答。
另外,勾选 Gevent Compatible 可能会导致一些其它问题,所以确保你是仅对这个项目勾选了。如果之后项目改用本地解释器,可能需要取消勾选 Gevent Compatible,否则可能会发生其他文件里的断点失效的问题。
3. matpoltlib.pyplot 创建 figure 报错
这个报错应该是 tkinter.TclError: couldn't connect to display。发生这种错误不是因为远程调试,而是因为一般服务器没有窗口化显示的需求,所以没有 xming 图形化显示模块。matplotlib 默认使用该模块。
解决方法,在程序首部插入以下代码,以切换图形化显示模块:
```
import matplotlib
matplotlib.use("Agg")
```