2019年8月1日 20:03 by scott
python调试(1)编写Python程序:使用pandas读取excel数据,分析处理后把结果以邮件形式发送。
(2)编写Dockerfile文件,在Docker中部署程序
(3)在Docker中启动定时任务,每天的9点发送邮件
(4)通过定时任务跑出程序时,老是报错:
File "t.py", line 8, in <module>
df = pd.read_excel(fn)
File "/usr/local/lib/python3.6/site-packages/pandas/util/_decorators.py", line 178, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/pandas/util/_decorators.py", line 178, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/pandas/io/excel.py", line 307, in read_excel
io = ExcelFile(io, engine=engine)
File "/usr/local/lib/python3.6/site-packages/pandas/io/excel.py", line 394, in __init__
self.book = xlrd.open_workbook(self._io)
File "/usr/local/lib/python3.6/site-packages/xlrd/__init__.py", line 116, in open_workbook
with open(filename, "rb") as f:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-16: ordinal not in range(128)
猜测原因:sheet name出现了中文,或者sheet 内容中出现了中文,事实上都出现了。
但是进入Docker中手动运行是没有问题的。原因出现在了哪儿呢?
肯定是定时任务运行时的环境和手动执行时环境不一致导致的
可是究竟该怎么把环境配一致呢,尝试了以下方法:
(1)由于是编码导致的,那么就解决编码问题,在定时任务中加上编码方式(PYTHONIOENCODING=utf-8),如下(未凑效):
1 09 * * * cd /code && PYTHONIOENCODING=utf-8 /usr/local/bin/python send_email.py >> /var/log/cron.log 2>&1
(2)既然是shell环境导致,那么把运行命令放入shell脚本中运行(同时把脚本配到crontab中,此处略),shell脚本内容如下(为凑效):
#!/bin/sh
# 为了使python版本一致,这里用的是python3
. /etc/profile
echo "good"
echo `python --version`
python send_email.py
这里先列出解决方案(最终的shell脚本):
#!/bin/sh
. /etc/profile
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
echo "good"
echo `python --version`
python send_email.py
感兴趣的可以继续往下看解决问题的思路。
(1)既然是编码导致的问题,手动可运行,定时任务中不行,那么我把编码打出来看看是啥。
在Python脚本中加入以下行来打印编码内容(系统默认编码、文件转换编码):
import sys
print("system coding:",sys.getdefaultencoding())
print("file coding:",sys.getfilesystemencoding())
(2)再次手动执行,再次定时任务中执行,输出分别如下:
# 手动运行时的输出
system coding: utf-8
file coding: utf-8
# 定时任务中的输出
system coding: utf-8
file coding: ascii
(3) 为什么不一样呢,最后到网上查询,决定 sys.getfilesystemencoding() 值的shell变量是 LANG,LC_* , 原文描述如下:
Terminals usually spawns a new shell and setting LANG or LC_* environment variables will affect only programs that will run withing this shell.
于是在shell脚本中添加如下行:
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
(4)再次在定时任务中执行shell脚本,最终成功运行!激动。。。成就感。。。。
(1)要善于从案发一线找线索,就像警察破案:光知道大致方向,找不到线索也是白搭。
(2)关于Linux的知识,知道的越多越好。比如这里的shell环境中的编码怎么设置,以及有哪些影响。
(3)python中有些工具包、工具函数能帮助我们查找问题。
(4)善于使用Google(百度)搜索引擎。
(1)如有其他问题,欢迎留言。
(2)如果想知道怎么在Docker中配置定时任务,欢迎留言。
(3)想知道怎么发邮件、怎么用Docker部署程序,欢迎留言。
ps. 也许这个问题对你来说不算什么,能把解决过程整理出来,是不是也值得鼓励呢?