Python调用Antiword运行时报权限拒绝、无法执行二进制文件错误
问题产生原因
- 核心原因是你项目目录里存放的
!Antiword二进制文件和当前Mac系统的架构/格式不匹配。你在命令行能正常运行antiword是调用了系统全局安装的、适配你本机CPU架构(Intel/Apple Silicon)的Mach-O格式可执行文件,而你项目里存的那个文件大概率是其他平台(比如Linux的ELF格式、Windows的PE格式)或者其他架构的版本,系统根本无法识别执行,这才会报cannot execute binary file——这个报错和权限无关,权限不足只会触发Permission denied,你之前反复改权限、加sudo都没用就是因为找错了问题方向。 - 路径包含特殊字符
!,你用shell=True拼接命令字符串时,!在zsh/bash里是历史命令展开的特殊元字符,没有转义的情况下会被shell提前解析,也会触发路径识别错误,是你最开始遇到Permission denied的诱因之一。 - 代码里的subprocess调用逻辑有冲突:你既在命令字符串里写了
>做shell重定向,又指定了stdout=subprocess.PIPE,二者会互相干扰;同时用字符串拼接命令的方式对带空格、特殊字符的文件名兼容性极差,很容易执行失败。 - 硬编码了个人电脑的绝对路径,完全不符合你要做跨平台自包含程序的需求,换个存放目录、换台电脑路径就直接失效。
修复步骤
- 第一步先替换损坏的Antiword二进制
打开终端执行which antiword,找到你系统里能正常运行的antiword可执行文件路径,把这个文件复制到你项目的!Antiword目录下,替换掉原来无法执行的同名文件。替换后先手动在终端切到!Antiword目录,执行./!Antiword 你的测试doc文件路径,确认能正常输出文本内容,再进行后续步骤。
如果要做跨平台自包含,需要提前把对应平台(Windows、Mac Intel、Mac Silicon、Linux)的Antiword二进制都存到目录里,运行时根据系统类型自动选择对应文件。 - 第二步修正subprocess调用逻辑
放弃shell=True+字符串拼接命令的写法,改用列表传参的方式调用命令,从根源上规避特殊字符、文件名空格、shell展开的问题;输出重定向直接通过Python的文件操作完成,不要混用shell重定向和subprocess的PIPE参数。 - 第三步去掉硬编码路径,适配跨平台逻辑
不要写死你个人电脑的绝对路径,通过脚本自身的存放位置动态拼接Antiword的路径,同时针对Windows平台加exe后缀的适配。
修正后的可运行代码
import os import stat import subprocess import sys import platform def convert_file_type(target_dir): # 基于脚本自身位置拼接Antiword路径,适配任意存放位置 script_root = os.path.dirname(os.path.abspath(__file__)) antiword_root = os.path.join(script_root, "!Antiword") # 根据系统和架构选择对应二进制 sys_type = sys.platform cpu_arch = platform.machine() if sys_type == "win32": antiword_path = os.path.join(antiword_root, "antiword.exe") elif sys_type == "darwin": # Mac平台区分Intel和Apple Silicon if cpu_arch == "arm64": antiword_path = os.path.join(antiword_root, "antiword_mac_arm64") else: antiword_path = os.path.join(antiword_root, "antiword_mac_x86_64") else: # Linux平台 antiword_path = os.path.join(antiword_root, "antiword_linux_x86_64") # 类Unix系统下给可执行文件加执行权限 if sys_type != "win32": os.chmod( antiword_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH ) # 遍历目标目录处理doc文件 for file_name in os.listdir(target_dir): full_path = os.path.join(target_dir, file_name) if not os.path.isfile(full_path): continue file_base, file_ext = os.path.splitext(full_path) if file_ext.lower() != ".doc": continue output_path = f"{file_base}.txt" # 直接通过Python写输出文件,不用shell重定向 with open(output_path, "w", encoding="utf-8") as out_file: subprocess.run( [antiword_path, full_path], stdout=out_file, stderr=subprocess.PIPE, check=True ) print(f"转换完成:{full_path} -> {output_path}") if __name__ == "__main__": # 传入要处理的目录路径即可 convert_file_type(target_dir="./")
额外注意事项
- 不要加sudo运行脚本,普通用户权限完全满足读写文件、调用当前目录程序的需求,sudo会改变执行上下文的环境变量、路径权限,反而会引入额外问题。
- 如果后续要适配更多架构,只需要在选择二进制的逻辑里加对应判断,把对应版本的Antiword文件放到目录里即可。
内容的提问来源于stack exchange,提问作者hn6
相关产品推荐
相关产品推荐

