[Resuelto] Pit de Python: os.system() ejecuta rutas largas con espacios y los parámetros de comillas dobles tienen errores

Para ejecutar comandos de DOS en código Python, puede usar la función os.system() de la biblioteca os. Su uso es muy simple Cabe señalar que os.system no devolverá el resultado de salida a una variable. Hoy encontré un error: cuando la línea de comandos de DOS tiene una ruta de comillas dobles y un parámetro de comillas dobles, el resultado de la operación os.system() siempre muestra: "XXX (nombre de ruta) no es un comando interno o externo, ni es un programa ejecutable o un archivo por lotes".

Escribí un código por lotes de Python para convertir videos usando ffmpeg. Primero defina la ruta de ffmpeg:

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

Al ejecutar os.system(ffmpeg_path), se informará un error, que es un fenómeno que se encuentra a menudo al comenzar.

3961c0b4d3d64ca4845a3e558f3ef3c3.png

Obviamente, los archivos de programa en el nombre de la ruta contienen espacios, y DOS requiere comillas dobles para las rutas con espacios, por lo que el código debe cambiarse de esta manera para que os.system() se ejecute correctamente:

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

Este no es el punto del que quiero hablar hoy.

ffmpeg necesita agregar muchos parámetros para transcodificar, como convertir archivos m3u8 en formato ts a archivos mp4: ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,https,crypto,tcp" -i "input.m3u8" -c copy "salida .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)

La cadena de comando aquí obviamente está bien, pero el mismo error ocurre nuevamente cuando se trata de os.system (comando):

 

Me di cuenta de que era un problema con las comillas dobles nuevamente. ¿Qué sucede si elimina todos los parámetros detrás de ffmpeg y solo ejecuta el programa principal? Prueba: os.system(ffmpeg_path)

e23cd73376934d2d942af1007c3752b5.png

El resultado es que funciona bien. ¿Es porque los parámetros ffmpeg no pueden ejecutarse con comillas dobles?

Sin embargo, ffmpeg estipula que el tipo "archivo, http, https, crypto, tcp" detrás del parámetro -protocol_whitelist debe tener comillas dobles, y es ilegal cambiar o eliminar comillas simples. Si hay espacios en la ruta del archivo de entrada después de -i y la ruta del archivo de salida al final, también se deben agregar comillas dobles.

Después de depurar muchas veces, descubrí que si ffmpeg no agrega la ruta completa, os.system (comando) puede ejecutarse correctamente. Pero debe realizar la configuración de requisitos previos: debe agregar la ruta de ffmpeg a la variable de la ruta del sistema (la operación específica no se describirá en detalle).

De acuerdo con esta línea de pensamiento, dado que se deben agregar las comillas dobles de los parámetros, ¿cómo hacerlo sin comillas dobles en el nombre de la ruta del programa principal? Tuve un capricho: ¿qué pasa si la ruta de ffmpeg usa la ruta corta de caracteres de 8 bits de estilo antiguo? Cambie "Archivos de programa" en la ruta larga a "Progra ~ 1", y cambie el código a esto:

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)

Inesperadamente, os.system(command) se ejecutó correctamente. La información de transcodificación de ffmpeg sigue desplazándose por la pantalla, corriendo como una cascada.

b5ff50d5d3d643a395793ac4df875ac9.png

Se puede decir que la representación de la ruta corta "Progra~1" es la ruta absoluta del sistema Windows, que puede acceder completamente a la ruta que contiene espacios o caracteres extraños. Esta es la forma de jugar en la era Win9x hace muchos años. ¿Cuántos la gente todavía lo recuerda ahora? El método es antiguo, pero funciona.

Para resumir: el error de os.system() radica en:

Condición 1: cuando la ruta del programa principal de la línea de comando contiene espacios, la ruta debe tener comillas dobles.

Condición 2: Los parámetros de la línea de comando tienen comillas dobles.

Cuando se cumplen estas dos condiciones, la operación informará un error: "XXX (nombre de ruta) no es un comando interno o externo, ni es un programa o archivo por lotes operable".

Mi versión actual de Python es 3.10, tal vez la función os.system() no ha considerado la situación como los parámetros de línea de comandos de DOS con comillas dobles.

Solución:

1. La ruta del programa principal se cambia a la ruta corta de estilo antiguo de 8 caracteres y se eliminan las comillas dobles. Los siguientes parámetros conservan las comillas dobles y no es necesario cambiarlos.

o

2. Agregue la ruta del programa principal a la variable de entorno %PATH% del sistema Windows, y os.system() puede usar directamente el nombre del programa sin agregar el nombre de la ruta.

El resumen anterior es un poco extenso. Permítanme hacer una tabla más popular para resumir la combinación y coincidencia del uso de os.system() para ejecutar ffmpeg con éxito o no:

número de serie nombre del programa parámetro resultado
(1) nombre del programa con ruta larga " parámetros " Si la ruta no tiene comillas dobles, se informará de un error .
(2) " nombre del programa con ruta larga " " parámetros " Tanto la ruta como el parámetro tienen comillas dobles, pero se notifica un error. Creo que es un error.
(3) " nombre del programa con ruta larga " parámetro Los parámetros no tienen comillas dobles, si el programa no requiere comillas dobles para algunos parámetros, puede ejecutarse normalmente, de lo contrario se informará un error.
(4) " nombre del programa con ruta larga " Se puede ejecutar, pero sin parámetros, es posible que al ejecutar el programa no se obtengan los resultados esperados.
(5) nombre del programa " parámetros " No hay una ruta antes del nombre del programa, el programa debe estar en la ruta actual o en la variable %PATH% del sistema para tener éxito; de lo contrario, se informará un error.
(6) nombre del programa con ruta corta "parámetro" éxito. El nombre del programa de la ruta corta no necesita estar entre comillas dobles.

Un último truco: ¿cómo conseguir el camino corto?

Método 1: use el comando dir /x para ver en el símbolo del sistema cmd .

Método 2: el código Python importa la función GetShortPathName de win32api para obtener:

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'
'''

Supongo que te gusta

Origin blog.csdn.net/Scott0902/article/details/129446831
Recomendado
Clasificación