PYTHONIOENCODING 信用评分 2016.06.28回顾

本文首先探讨了Python日志文件编码问题,从gbk到utf-8的转换过程中出现的乱码现象及其解决办法;接着介绍了系统配置参数对中文显示的影响;随后分享了一种提高效率的前端修改方案;并对业务系统中征信上传错误及消息接收异常等问题进行了修复;最后通过变量检查发现了一些反直觉的数据结果。

1、开始用的PYTHONIOENCODING=gbk生成的日志文件,这样日志文件就是gbk编码,再用PYTHONIOENCODING=utf-8,确实是按照utf-8写入,但是“翻译”成了gbk,所以是乱码,最后删除掉旧的日志文件,重新生成一个,就是按utf-8编码,解决中文乱码问题
2、en_US是系统所在地区,可能是涉及一些任务栏,菜单栏语言,不会影响中文的显示
3、我想写成一种队列的形式,但是研究了下有点麻烦,所以当前最效率的解决方案,就是叫前端做出修改
4、解决了同时上传征信出错异常,解决了业务系统不能收到第二次正确消息异常
5、研究了下几个变量,并且认真检查了几个变量的正确性,发现了一些和直觉相反的结果,那些历史上有90天以上逾期的居然和整体的逾期率是一样的,2年内90天以上逾期率居然比整体还低,冻结的太少了,找到了有效的三个,三个都履约情况很差!
6、这个手工的分析过程也是对抓数据sql的检查,大多数还是对的,逻辑上可能还需要检查一遍!

<think> 我们正在分析subprocess.run失败的原因及解决方法。根据引用内容,我们可以总结出几个常见的失败原因以及相应的解决方案。 ### 常见失败原因及解决方法 1. **命令执行失败(非零退出码)** 当子进程返回非零退出码时,表示命令执行失败。如果设置了`check=True`,则会抛出`CalledProcessError`异常。 **解决方法**:使用`try-except`捕获异常,并检查返回码和输出信息。 ```python try: result = subprocess.run(['ls', '/nonexistent'], check=True, text=True, capture_output=True) except subprocess.CalledProcessError as e: print(f"命令执行失败,退出码:{e.returncode}") print(f"标准错误输出:{e.stderr}") ``` 2. **命令超时** 如果命令执行时间超过设定的`timeout`,会抛出`TimeoutExpired`异常。 **解决方法**:捕获超时异常,并考虑是否重试或终止。 ```python try: result = subprocess.run(['sleep', '10'], timeout=5, text=True, capture_output=True) except subprocess.TimeoutExpired as e: print(f"命令执行超时:{e}") ``` 3. **命令不存在** 如果尝试执行一个不存在的命令,会抛出`FileNotFoundError`异常。 **解决方法**:确保命令路径正确,或使用绝对路径。 ```python try: result = subprocess.run(['non_existent_command'], text=True, capture_output=True) except FileNotFoundError as e: print(f"命令不存在:{e}") ``` 4. **输出捕获问题** 如果没有正确捕获输出(例如,忘记设置`stdout=subprocess.PIPE`),则无法获取命令的输出。 **解决方法**:使用`capture_output=True`(Python 3.7+)或显式设置`stdout`和`stderr`。 ```python # 正确捕获输出 result = subprocess.run(['ls', '-l'], capture_output=True, text=True) print(result.stdout) ``` 5. **shell注入风险** 当使用`shell=True`时,如果命令字符串来自用户输入,可能存在安全风险。 **解决方法**:尽量避免使用`shell=True`,或严格校验用户输入。 ```python # 不安全的做法(用户输入可能包含恶意命令) user_input = "some; rm -rf /" subprocess.run(f"echo {user_input}", shell=True) # 更安全的做法:使用列表形式并避免shell=True subprocess.run(['echo', user_input]) ``` 6. **编码问题** 如果命令输出包含非UTF-8字符,且未正确处理编码,可能导致解码错误。 **解决方法**:指定正确的编码,或使用`bytes`输出后再解码。 ```python result = subprocess.run(['ls', '-l'], capture_output=True) # 手动解码,忽略错误 output = result.stdout.decode('utf-8', errors='ignore') ``` ### 总结 使用`subprocess.run`时,应始终考虑错误处理。通过捕获异常、检查返回码和正确处理输出,可以更稳健地运行子进程。对于关键任务,建议结合日志记录,以便于故障排查。 §§相关问题§§ 1. 如何安全地执行用户提供的命令? 2. 如何同时捕获标准输出和标准错误? 3. 如何设置子进程的环境变量? 4. 如何在Windows系统中正确使用subprocess.run? </think> ### `subprocess.run` 失败原因及解决方法 当 `subprocess.run()` 执行失败时,常见原因和解决方案如下: #### 1. **命令不存在或路径错误**(引发 `FileNotFoundError`) ```python try: result = subprocess.run(["non_existent_cmd"], check=True) except FileNotFoundError as e: print(f"命令不存在: {e}") # 输出具体错误信息[^1] ``` **解决方法**: - 使用绝对路径:`subprocess.run(["/usr/bin/ls"])` - 添加环境变量: ```python env = {**os.environ, "PATH": "/custom/bin:" + os.environ["PATH"]} subprocess.run(["custom_cmd"], env=env) ``` #### 2. **非零退出码**(引发 `CalledProcessError`) ```python try: # grep 在未找到匹配时返回1 result = subprocess.run(["grep", "pattern", "file"], check=True) except subprocess.CalledProcessError as e: print(f"命令失败(退出码 {e.returncode}): {e.stderr.decode()}") # [^1][^2] ``` **解决方法**: - 移除 `check=True` 捕获退出码: ```python result = subprocess.run(["cmd"], capture_output=True) if result.returncode != 0: print(f"错误输出: {result.stderr.decode()}") ``` #### 3. **超时问题**(引发 `TimeoutExpired`) ```python try: result = subprocess.run(["sleep", "10"], timeout=5) except subprocess.TimeoutExpired as e: print(f"命令超时: {e}") # [^1] e.stdout # 获取已捕获的输出 ``` **解决方法**: - 增加超时时间:`timeout=30` - 使用异步执行: ```python with subprocess.Popen(["long_running_cmd"]) as proc: try: proc.communicate(timeout=30) except TimeoutExpired: proc.kill() ``` #### 4. **权限不足** ```python try: subprocess.run(["sudo", "apt", "update"]) except PermissionError as e: print(f"权限不足: {e}") ``` **解决方法**: - 添加执行权限:`os.chmod("script.sh", 0o755)` - 使用权限提升: ```python subprocess.run(["pkexec", "privileged_cmd"]) ``` #### 5. **输出编码问题** ```python result = subprocess.run(["cmd"], capture_output=True, text=True, # 自动解码 encoding="utf-8", # 指定编码 errors="ignore") # 忽略解码错误[^1] ``` **解决方法**: - 使用原始字节后处理:`output = result.stdout.decode("utf-8", errors="replace")` - 设置环境变量:`env={"PYTHONIOENCODING": "utf-8"}` #### 6. **资源限制导致失败** ```python try: # 限制子进程资源 result = subprocess.run(["mem_hungry_cmd"], rlimits={ resource.RLIMIT_AS: 500 * 1024 * 1024 # 500MB内存限制 }) except OSError as e: print(f"资源不足: {e}") ``` ### 最佳实践总结 1. **始终处理异常**:使用 `try-except` 捕获 `CalledProcessError`, `TimeoutExpired` 等 2. **明确指定路径**:避免依赖 `$PATH` 环境变量 3. **安全使用 `shell=True`**: ```python # 避免! 可能引发注入攻击 subprocess.run(f"rm -rf {user_input}", shell=True) # 推荐做法 subprocess.run(["rm", "-rf", sanitized_path]) ``` 4. **及时清理资源**: ```python with subprocess.Popen(...) as proc: # 自动清理 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值