在从OS X进行SSH时出现UnicodeDecodeError错误

4

我的Django应用程序在启动时加载一些文件(或当我执行管理命令时)。当我从我的Arch或Ubuntu计算机之一通过ssh连接时,所有工作都正常,我可以成功运行任何命令和迁移。

但是当我从OS X(我有El Capital)通过ssh连接并尝试做同样的事情时,我会收到以下错误消息:

UnicodeDecodeError: 'ASCII' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

为了打开我的文件,我使用 with open(path_to_file) as f: ... 当从iterm和terminal进行ssh时,出现了错误。我发现原因是LC_CTYPE环境变量。在我的其他Linux机器上没有设置,但在Mac上它是UTF-8,所以当我ssh到服务器时它被设置成相同的值。取消设置LC_CTYPE后,错误被修复。
实际问题是发生了什么以及如何避免这种情况?我可以在本地机器上取消设置此变量,但会产生负面影响吗?最佳做法是什么?
2个回答

5
您本地机器上的终端使用字符编码。它使用的编码似乎是UTF-8。当您登录到服务器时(顺便问一下,它运行的是什么操作系统?),在那里运行的程序需要知道您的终端支持哪种编码,以便按需要显示内容。他们从LC_CTYPE获取此信息。 ssh正确将其设置为UTF-8,因为这是您的终端支持的内容。
当您取消设置LC_CTYPE时,那么您的程序将使用默认值ASCII。程序现在以ASCII而不是UTF-8显示,这是有效的,因为UTF-8与ASCII向后兼容。但是,如果程序需要显示ASCII中不存在的特殊字符,则无法正常工作。
虽然根据您提供的信息,我不完全清楚系统为什么会表现出这种方式,但我可以告诉您,取消设置LC_CTYPE是一种不好的解决方法。为避免未来出现问题,在所有机器的所有终端中使用UTF-8,并摆脱ASCII将是更好的选择。
当您尝试打开文件时,Python使用终端(即LC_CTYPE)的字符集。我从来没有完全理解为什么要这样做;为什么您的终端的字符集应该指示文件的编码呢?但是,这就是它的制造方式,以及正确修复问题的方法是使用open的encoding参数(如果您正在使用Python 3),或者如果您正在使用Python 2,则使用codecs标准库模块。

4
实际上,我刚刚搜索了一下,发现UTF-8不是有效的LC_CTYPE,所以我在我的.bash_profile文件中加入了export LC_ALL=en_US.UTF-8export LANG=en_US.UTF-8,问题就解决了。顺便说一下,我使用的是Ubuntu 16.04作为服务器。我不知道open使用LC_CTYPE来定义文件编码,这确实很奇怪。谢谢你的帮助。我会接受你的回答。 - valignatev

1
我在更新我的OS-X后遇到了类似的问题,在ssh连接到一个UNIX服务器时,版权符号没有被编码,因为UTF-8语言环境没有正确设置。我通过取消终端偏好设置中的“启动时设置语言环境变量”选项来解决了这个问题。

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