【已解决】Python的坑:os.system()运行带有空格的长路径和双引号参数有bug_os.system怎么调试-程序员宅基地

技术标签: python  bug  ffmpeg  Python  

在Python代码里运行DOS命令,可以使用os库的os.system()函数。其用法很简单,需要注意的是os.system不会返回输出的结果赋予一个变量。今天我发现了一个bug:当DOS命令行带有双引号路径、双引号参数时,os.system()运行的结果总是显示:“XXX(路径名) 不是内部或外部命令,也不是可运行的程序或批处理文件。”

我写了一个Python批量使用ffmpeg转换视频的代码。首先定义ffmpeg的路径:

ffmpeg_path = r'D:\Program Files\ffmpeg\bin\ffmpeg.exe'

当运行os.system(ffmpeg_path)会报错,这样写是入门时经常遇到的现象。

3961c0b4d3d64ca4845a3e558f3ef3c3.png

很显然路径名称中的Program Files含有空格,DOS要求凡是有空格的路径一定要加双引号,因此代码要这样改才能使os.system()正确执行:

ffmpeg_path = r'"D:\Program Files\ffmpeg\bin\ffmpeg.exe"'

今天我要讲的重点不是这个。

ffmpeg需要添加很多参数来转码,比如把ts格式的m3u8文件转换成mp4文件:ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,https,crypto,tcp" -i "input.m3u8" -c copy "output.mp4"。

import os
inputfile = r'd:\temp\input.m3u8'
outputfile = r'd:\temp\output.mp4'
ffmpeg_path = r'"D:\Program Files\ffmpeg\bin\ffmpeg.exe"'
command = f'{ffmpeg_path} -allowed_extensions ALL -protocol_whitelist "file,http,https,crypto,tcp" -i "{inputfile}" -c copy "{outputfile}"'

'''
print(command)
输出:
"D:\Program Files\ffmpeg\bin\ffmpeg.exe" -allowed_extensions ALL -protocol_whitelist "file,http,https,crypto,tcp" -i "d:\temp\input.m3u8" -c copy "d:\temp\output.mp4"
'''

os.system(command)

这里的command字符串明明没问题,但到了os.system(command)又出同样的错:

 

我意识到又是双引号的问题了。如果去掉ffmpeg后面所有的参数、仅运行主程序呢?试试:os.system(ffmpeg_path)

e23cd73376934d2d942af1007c3752b5.png

结果是可以正常运行。是不是ffmpeg参数带有双引号就运行不了?

可是ffmpeg规定-protocol_whitelist 参数后面的类型 "file,http,https,crypto,tcp" 必须有双引号,改单引号或去掉都非法。-i 后的输入文件路径、以及末尾的输出文件路径如有空格,也必须加双引号。

前后调试了多次,我发现如果ffmpeg不加上完整的路径,os.system(command)可以成功运行。但需要作前提设置:要把ffmpeg的路径添加到系统路径的变量里(具体操作不作赘述)。

按照这个思路顺藤摸瓜,既然参数的双引号一定要加,那么主程序的路径名不加双引号,怎么操作?我突发奇想:ffmpeg的路径使用旧式的8位字符短路径又如何?把长路径中的“Program Files”改为“Progra~1”,代码改成这样:

inputfile = r'd:\temp\input.m3u8'
outputfile = r'd:\temp\output.mp4'
ffmpeg_path = r'D:\Progra~1\ffmpeg\bin\ffmpeg.exe'
command = f'{ffmpeg_path} -allowed_extensions ALL -protocol_whitelist "file,http,https,crypto,tcp" -i "{inputfile}" -c copy "{outputfile}"'

os.system(command)

意想不到的是os.system(command)居然成功运行了。ffmpeg转码的信息在屏幕里不停滚动,像瀑布一样哗哗直流。

b5ff50d5d3d643a395793ac4df875ac9.png

“Progra~1”这种短路径表示方式可以说是Windows系统的绝对路径,能彻底访问含空格、或带奇怪字符的路径,这是多年前Win9x年代的玩法,现在还有多少人记得?方法虽旧,但却很管用。

小结一下:os.system()的bug在于:

条件1:当命令行的主程序路径含有空格时,路径必须有双引号。

条件2:命令行的参数带有双引号。

这两个条件都满足的情况下,运行会报错:“XXX(路径名) 不是内部或外部命令,也不是可运行的程序或批处理文件。”

我当前的Python版本是3.10,也许os.system()函数没有考虑周全像DOS命令行参数带双引号这种情况。

解决办法:

1、主程序的路径改用旧式的8位字符短路径,并且去掉其双引号。后面的参数保留双引号,不用改。

或者

2、把主程序所在的路径添加到Windows系统的环境变量%PATH%,os.system()就可以直接使用程序名称,不需要添加路径名。

以上的小结有点啰嗦,我作个通俗一点的表格归纳一下使用os.system()运行ffmpeg成功与否的组合搭配:

序号 程序名 参数 结果
(1) 带长路径程序名 "参数" 路径缺双引号,报错
(2) "带长路径程序名" "参数" 路径和参数都带双引号却报错。我认为是BUG。
(3) "带长路径程序名" 参数 参数不带双引号,如果程序对某些参数不要求带双引号就能正常运行,否则会报错。
(4) "带长路径程序名" 可以运行,但没有参数,运行程序可能达不到预期的效果。
(5) 程序名 "参数" 程序名前没有路径,程序必须在当前路径或者在系统%PATH%变量中才能成功,否则报错。
(6) 短路径的程序名 "参数" 成功。短路径的程序名不需要加双引号了。

最后再教一招:如何获取短路径?

方法1:在cmd命令提示符下用 dir /x 命令查看。

方法2:Python代码引入win32api的GetShortPathName函数进行获取:

from win32api import GetShortPathName
ffmpeg_path = r'D:\Program Files\ffmpeg\bin\ffmpeg.exe'
ffmpeg_path = GetShortPathName(ffmpeg_path)
'''
print(ffmpeg_path)
输出:
'D:\Progra~1\ffmpeg\bin\ffmpeg.exe'
'''

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Scott0902/article/details/129446831

智能推荐

使用 Docker 和 Traefik v1 搭建轻量代码仓库(Gogs)_gogs sqlite 性能-程序员宅基地

文章浏览阅读710次。本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)本文作者: 苏洋创建时间: 2020年02月04日统计字数: 12336字阅读时间: 25分钟阅读本文链接: https://soulteary.com/2020/02/04/gogs-git-server-with-docker-and-..._gogs sqlite 性能

腾讯云新人专享福利:2024年4核8G12M轻量服务器优惠活动及性能测评_腾讯云 4核 活动-程序员宅基地

文章浏览阅读958次,点赞17次,收藏25次。用户仅需支付646元,便可享受一整年的服务,而且腾讯云还额外赠送3个月的服务时长,意味着用户实际上能享受到长达15个月的超值服务。无论是个人开发者的博客、中小企业的官网,还是云端网站、Web应用、小程序等,这款服务器都能提供强大的支持。这游戏比较吃内存,所以内存尽量在16G以上(Pocketpair官方的推荐配置是4核16G),CPU选4核即可,带宽方面推荐不限流量的固定带宽,延时低,畅玩体验更佳。到这一步的时候,帕鲁的服务端安装程序已经预置在服务的镜像里了,无需手动复制,非常方便。_腾讯云 4核 活动

ValueError: Error when checking target: expected denseclassify to have 3 dimensions, but got array w_error when checking target: expected lstm_4 to hav-程序员宅基地

文章浏览阅读2.2k次。ValueError: Error when checking target: expected denseclassify to have 3 dimensions, but got array with shape (8, 5)。使用keras搭建bilstm+selfattention的模型,进行多文本分类发现出现ValueError的错误,但检查发现denseclassify层的输..._error when checking target: expected lstm_4 to have 3 dimensions, but got ar

Windows使用PHP启动ThinkPHP项目,部署配置-程序员宅基地

文章浏览阅读4.2k次。这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar_启动thinkphp项目

生物科研软件(从科研到发文章)(转自小木虫)-程序员宅基地

文章浏览阅读537次。 生物科研软件(从科研到发文章)(转自小木虫) 1.文献管理与分析:EndNote X1,文献管理软件,平时方便论文管理,写文章的时候插入文献也是相当的方便;RefViz 2.1,文献分析软件,与EndNote结合使用,分析文献,可以省掉大把自己看自己归纳的时间;ReferenceManager似乎很久没有更新了,Thomoson看来以后可能只管EndNote了。2.分子生物学综合软件:..._oligoanalyzer 小木虫

QVector_qt vector 与list区别-程序员宅基地

文章浏览阅读742次。QList 和QVector的区别QList不同于List,QList 是基于数组+链表,即各个节点的 指针不是通过Next来指向,而是通过将各节点的指针存放在一个数组中,遍历通过找到数组中的指向该节点的指针,在通过指针将节点找到,所以QList的效率应该是同QVector差不多,只是多了一个通过指针查找节点的过程。QVector同vector一样是一段连续的内存。QVector 的优缺点..._qt vector 与list区别

随便推点

Unity Shader 之 简单滚动(uv)动画的效果实现_球化uv滚动-程序员宅基地

文章浏览阅读6.4k次。Unity Shader 之 简单滚动(uv)动画的效果实现目录Unity Shader 之 简单滚动(uv)动画的效果实现一、简单介绍二、实现原理三、注意事项四、效果预览五、实现步骤六、代码一、简单介绍Shader Language的发展方向是设计出在便携性方面可以和C++、Java等相比的高级语言,“赋予程序员灵活而方便的编程方式”,并..._球化uv滚动

神经架构搜索:实现高效的图像分割模型-程序员宅基地

文章浏览阅读734次,点赞22次,收藏13次。1.背景介绍图像分割是计算机视觉领域中的一个重要任务,它的目标是将图像划分为多个区域,每个区域代表不同的物体或场景。随着深度学习技术的发展,卷积神经网络(CNN)已经成为图像分割任务的主要解决方案。然而,在实际应用中,我们需要找到一个高效且准确的神经网络架构来实现高质量的图像分割。神经架构搜索(Neural Architecture Search,NAS)是一种自动发现神经网络架构的方法,...

homework-09-程序员宅基地

文章浏览阅读56次。0 需求这次作业需要实现一个动态求解过程展示,在homework2里我们已经实现了对一维/二维矩阵的最大子矩阵和求解,并且能支持-h和-v(本次作业中没要求-a吧?)。程序需要再支持单步执行和自动执行,并且要有随机生成测试数据的功能。对于求解的每一步都用直观的图形展示。1 分析由于网页展示有加分,所以选择在网页上实现。稍微分析了一下,觉得网页实现大概有这三种形式:..._编写程序,程序名称命名为 homework4-1.c,程序要实现如下功自 编

OSWorkFlow 学习-程序员宅基地

文章浏览阅读137次。1.OSWorkFlow基本概念 在商用和开源世界里,OSWorkflow都不同于这些已有的工作流系统。最大不同在于OSWorkflow有着非常优秀的灵活性。在开始 接触OSWorkflow时可能较难掌握(有人说不适合工作流新手入门),比如,OSWorkflow不要求图形化工具来开发工作流,而推荐手工编 写xml格式的工作流程描述符。它能为应用程序开发者提供集成,也...

自动更改Iexplore的Active x设置,添加可信站点,允许弹窗,自动清理-程序员宅基地

文章浏览阅读159次。判断项有Active x,可信站点,阻止弹窗,每次退出清理实现登录系统时进行判断,不满足时自动运行批处理文件修改IE设置,重启浏览器并返回登录页———————————— //获取注册表数值数据 判断注册表Range100项是否存在 private bool IsRegeditItemExist() { string[] subkeyN..._批处理修改注册表ie浏览器允许弹窗

前台和后台互相传递数组_后台怎么传输array数组-程序员宅基地

文章浏览阅读8.6k次。前台和后台互相传递数组  最近做项目要用到将多个字符串通过jq的ajax传递给后台的功能,刚开始是想将字符串以某个分隔符的形式拼接起来再进行传递,如:$.ajax{ url:"xxxx", data:{ array: "Jason,Sean,Danny" }}  然后后台获取参数后再分隔,这种做法有很不好,如果你需要的参数里面包含分隔符..._后台怎么传输array数组

推荐文章

热门文章

相关标签