SSH远程执行Python3 Error: UnicodeEncodeError: 'ascii' codec
2021/12/8 14:18:12
本文主要是介绍SSH远程执行Python3 Error: UnicodeEncodeError: 'ascii' codec,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
最近项目上需要SSH远程到Centos7容器上执行Python代码,Python版本为3.6。在执行打开中文名称的文件时,在Centos7容器上本地执行open('狼来了.txt')
不会有任何问题,但当通过SSH连接过去后发现open()方法报如下错误:
UnicodeEncodeError :'ascii' codec can't encode characters in position 0-2
问题出现在open的时候将 '狼来了.txt'(中文文件名称)作为参数按照ascii编码方式进行encode,而我们知道ascii编码是只有128位包含数字、大小写字母和一些特殊符号,是不包含中文汉字的。【至于为什么会进行encode,本文不做介绍】
所以将代码做如下更改便可以正常运行:
open('狼来了.txt'.encode('utf8'))
因为这里我们指定了了utf-8
的编码格式(当然,需要运行环境支持)。
找到问题的本质,我们就可以接着来看SSH的问题。
语言编码环镜
Python运行容器环境
Python运行环境容器里通过locale
以及locale -a
命令来查看发现语言编码环境如下所示:
[root@pyrun-test-69d4d45d79-mqg6n /]# locale -a C en_US.utf8 POSIX [root@pyrun-test-69d4d45d79-mqg6n /]# locale LANG=en_US.utf8 LC_CTYPE="en_US.utf8" LC_NUMERIC="en_US.utf8" LC_TIME="en_US.utf8" LC_COLLATE="en_US.utf8" LC_MONETARY="en_US.utf8" LC_MESSAGES="en_US.utf8" LC_PAPER="en_US.utf8" LC_NAME="en_US.utf8" LC_ADDRESS="en_US.utf8" LC_TELEPHONE="en_US.utf8" LC_MEASUREMENT="en_US.utf8" LC_IDENTIFICATION="en_US.utf8" LC_ALL=
SSH客户端的语言编码环境
而SSH客户端的语言编码环境如下:
root@coding-editor-test-8c6cdfdd8-9tpcl:/app# locale -a C C.UTF-8 POSIX root@coding-editor-test-8c6cdfdd8-9tpcl:/app# locale LANG=C.UTF-8 LANGUAGE= LC_CTYPE="C.UTF-8" LC_NUMERIC="C.UTF-8" LC_TIME="C.UTF-8" LC_COLLATE="C.UTF-8" LC_MONETARY="C.UTF-8" LC_MESSAGES="C.UTF-8" LC_PAPER="C.UTF-8" LC_NAME="C.UTF-8" LC_ADDRESS="C.UTF-8" LC_TELEPHONE="C.UTF-8" LC_MEASUREMENT="C.UTF-8" LC_IDENTIFICATION="C.UTF-8" LC_ALL=
配置语言编码环境
通过对比发现SSH客户端的编码环境是C.UTF-8
,而Python运行环境为en_US.utf8
(ps : C表示的是ascii编码, en_US.utf8 与 zh_CN.utf8 都是包含汉字的)
首先想到的是可能是SSH客户端影响了Python运行时的默认encode方式,那么我们把SSH客户端的环境设置成和Python运行环境一样的『这里客户端为Ubuntu』:
#!/bin/sh # 1.设置语言为en_US_UTF-8 echo -e 'LANG="en_US_UTF-8"\nLANGUAGE="en_US:en"' >> /etc/default/locale # 生效配置 source /etc/default/locale # 2.如果缺少en_US_UTF-8语言包 安装locales工具并设置en_US_UTF-8 apt-get install --no-install-recommends -y locales locale-gen en_US.UTF-8 localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
设置完成后再尝试SSH到Python运行环境容器,发现open('狼来了.txt')
运行不再报错。
那么问题来了,为什么SSH会用客户端的编码运行环境
SSH ENV机制探究
cat /etc/ssh/ssh_config
在ssh的配置文件中发现如下内容:
上面配置,会将本地的语言环境SendEnv到Python运行环境,那么我们就不需要保证客户端和Python运行环境的语言环境一致了。
只需要将配置修改为:
SendEnv LANG en_US.utf8
Mina SSH 的设置
由于项目是由Java通过Mina SSH 调用Python运行环境终端去执行的代码,而非直接用的SSH,因此对/etc/ssh/ssh_config
的修改并不能解决问题。
通过对Mina的观察发现,再创建ChannelShell的时候可以传递参数,源码接口如下:
/** * Create a channel to start a shell using specific PTY settings and/or environment. * * @param ptyConfig The PTY configuration to use - if {@code null} then internal defaults are used * @param env Extra environment configuration to be transmitted to the server - ignored if * {@code null}/empty. * @return The created {@link ChannelShell} * @throws IOException If failed to create the requested channel */ ChannelShell createShellChannel( PtyChannelConfigurationHolder ptyConfig, Map<String, ?> env) throws IOException;
那么在创建ChannelShell的时候可以这样写,将语言编码配置:
shellChannel = session.createShellChannel(new PtyChannelConfiguration(), Map.of("LANG","en_US.utf8"));
这篇关于SSH远程执行Python3 Error: UnicodeEncodeError: 'ascii' codec的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-21Python编程基础教程
- 2024-11-20Python编程基础与实践
- 2024-11-20Python编程基础与高级应用
- 2024-11-19Python 基础编程教程
- 2024-11-19Python基础入门教程
- 2024-11-17在FastAPI项目中添加一个生产级别的数据库——本地环境搭建指南
- 2024-11-16`PyMuPDF4LLM`:提取PDF数据的神器
- 2024-11-16四种数据科学Web界面框架快速对比:Rio、Reflex、Streamlit和Plotly Dash
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门