【问题标题】:How to use subprocess.call to run a Windows program如何使用 subprocess.call 运行 Windows 程序
【发布时间】:2019-08-02 08:54:44
【问题描述】:

我正在尝试使用 subprocess 命令在 Python 脚本中运行 psql 命令。
我使用 Windows 环境,psql 命令旨在恢复位于远程 Linux 服务器中的数据库。

sn-p 就是这个:

import os, sys
import subprocess

subprocess.call('psql -h ip_remote_server -p port -U user-d database -n schema --file="C:\Docs\script.sql"')  

这不起作用,控制台告诉找不到指定的文件。

任何帮助将不胜感激!
谢谢!

【问题讨论】:

  • 是否有不使用 psycopg2 的具体原因?
  • 你能提供完整的回溯吗?我们不知道 Python 是否无法找到 psql"C:\Docs\script.sql"。此外,您可能必须使用双反斜杠,因为 Python 将 "\D" 视为 "D"。所以试试"C:\\Docs\\script.sql"
  • 其实,当我运行一个简单的 subprocess.call('psql') 我有同样的错误信息:WindowsError: [Error 2] specified file can't be found
  • 您需要提供psql的路径。如果您使用反斜杠,则需要转义它们(例如"C:\\Program Files\\psql\\psql.exe")。

标签: python windows subprocess psql


【解决方案1】:

是的,你的问题绝对是你的路径。我经历了在 Windows 10 上安装 Python 的麻烦并创建了这些脚本:

example.bat

@echo off                                                                                                                                                                           
echo This is a stand-in for your program                                                                                                                                            
echo arg1 = %1                                                                                                                                                                      
echo arg2 = %2                                                                                                                                                                      

example.py

import subprocess                                                                                                                                                                   

subprocess.call("C:\\Users\\bogus\\example.bat example arguments")                                                                                                              

控制台

C:\Users\bogus>python example.py
This is a stand-in for your program                                                                                                                                                 
arg1 = example                                                                                                                                                                      
arg2 = arguments                                                                                                                                                                    

如您所见,您无需传递shell=True,或将您的命令拆分为列表。

如果您仔细查看 subprocess.call 的文档,您会看到以下内容(已添加重点):

上面显示的参数只是一些常见的参数。 完整的函数签名与 Popen 构造函数的签名相同 - 此函数将所有提供的参数(除了超时)直接传递到该接口。

如果您仔细查看 subprocess.Popen 的文档,您会看到以下内容(已添加重点):

在 Windows 上,如果 args 是一个序列,它将按照在 Windows 上将参数序列转换为字符串中所述的方式转换为字符串。这是因为底层的 CreateProcess() 对字符串进行操作。

关于将参数拆分为列表或传递 shell=True 的任何建议仅适用于 POSIX,但有一个例外:

您需要在 Windows 上指定 shell=True 的唯一情况是您希望执行的命令内置于 shell 中(例如 dir 或 copy)。您不需要 shell=True 来运行批处理文件或基于控制台的可执行文件。

【讨论】:

  • 请注意,如果shell=True 仍然适用于 Windows,则不传递参数列表的建议。 subprocess.list2cmdline 通常不会为 CMD shell 正确引用和转义命令行。如果不是不可能,那将是困难的。如果我们直接运行 .bat 或 .cmd 脚本也同样适用,因为在这种情况下,CreateProcessW 会重写命令行以运行"%ComSpec%" /c(即"%SystemRoot%\System32\cmd.exe" /c)。
  • 仅供参考,我们可以使用原始字符串作为命令行字符串文字,而不是转义反斜杠。我们还可以对字符串文字使用单引号,这样可以更轻松地在命令行中使用双引号引用路径。例如:r'"C:\Users\bogus\example.bat" example arguments'.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 2011-07-15
相关资源
最近更新 更多