Win7下通过批处理获取含变音符号的命令行文件路径问题
解决Windows批处理传递含变音符号路径给Python的编码问题
这个问题的核心是Windows控制台/批处理的编码和Python 2的sys.argv编码不匹配导致的:
- 手动在控制台输入命令时,控制台使用当前默认代码页(通常是CP936,即GBK),输入的变音符号会被正确编码后传递给Python,所以
os.path.exists能正常识别路径。 - 但如果把批处理保存为UTF-8编码,cmd会默认用ANSI(CP936)解析批处理内容,UTF-8格式的变音符号被错误解析成乱码(比如你看到的
t+±ter+±ta),传递给Python后自然无法匹配真实路径。
下面是几种可行的解决方案,按推荐程度排序:
1. 将批处理文件保存为ANSI编码
这是最简单最可靠的方法,完全符合Windows cmd的默认行为:
- 用记事本打开你的
run_script.bat - 点击「文件」→「另存为」,在编码下拉框选择「ANSI」,保存覆盖原文件
- 再次运行批处理,路径参数就能被正确传递给Python了
2. 在批处理开头切换代码页为UTF-8
如果必须使用UTF-8编码的批处理,可以先把控制台代码页切换为UTF-8(代码页编号65001),确保cmd能正确解析批处理里的UTF-8字符:
@echo off chcp 65001 >nul c:\python27\python.exe c:\path\to\parsepath.py "c:\täterätä"
注意:切换到65001后,部分cmd命令的输出格式可能会有变化,同时要确保你的控制台字体支持UTF-8字符(比如Consolas、Lucida Console),否则变音符号可能显示为方块。
3. 在Python脚本中修复编码转换
如果无法修改批处理的编码,可以在Python里把乱码的参数反向转换为正确的UTF-8:
因为批处理是UTF-8保存的,cmd把它当成CP936解析,所以sys.argv[1]是UTF-8字节被错误解码为CP936的字符串,我们需要反向转换:
import os import sys def main(): # 把错误解码的字符串转回UTF-8字节,再正确解码 fn = sys.argv[1].encode('cp936').decode('utf-8') if os.path.exists(fn): print os.path.basename(fn) # 文件存在 else: print 'Could not read path {}'.format(fn) if __name__ == '__main__': print 'starting' main()
这个方法依赖批处理的编码,如果后续批处理编码变化,代码也要跟着调整,通用性稍差。
4. 使用Windows API直接获取Unicode参数
Python 2的sys.argv在Windows下对Unicode参数的处理有缺陷,我们可以用pywin32库调用Windows API直接获取原始的Unicode命令行参数:
首先需要安装pywin32:pip install pywin32
然后修改脚本:
import os import win32api def main(): # 获取完整命令行,再分割为参数列表 cmd_line = win32api.GetCommandLine() args = win32api.CommandLineToArgv(cmd_line) fn = args[1] # 第一个参数是脚本路径,第二个是传入的目标路径 if os.path.exists(fn): print os.path.basename(fn) else: print 'Could not read path {}'.format(fn) if __name__ == '__main__': print 'starting' main()
这个方法能彻底绕过sys.argv的编码问题,直接拿到正确的Unicode路径,适合复杂的Unicode场景。
内容的提问来源于stack exchange,提问作者thopy




