【问题标题】:Execute bash script from Python on Windows在 Windows 上从 Python 执行 bash 脚本
【发布时间】:2017-05-29 11:07:04
【问题描述】:

我正在尝试编写一个 python 脚本来执行我在我的 Windows 机器上的 bash 脚本。到目前为止,我一直在使用 Cygwin 终端,因此执行 bash 脚本 RunModels.scr 就像 ./RunModels.scr 一样简单。现在我希望能够使用 Python 的subprocess,但是因为 Windows 没有内置的功能来处理 bash 我不知道该怎么做。

我正在尝试模仿./RunModels.scr < validationInput > validationOutput

我最初是这样写的:

os.chdir(atm)
vin = open("validationInput", 'r')
vout = open("validationOutput", 'w')
subprocess.call(['./RunModels.scr'], stdin=vin, stdout=vout, shell=True)
vin.close()
vout.close()
os.chdir(home)

但是在花了一段时间试图弄清楚为什么我的访问被拒绝之后,我意识到我的问题不是文件权限,而是我试图在 Windows 上执行一个 bash 文件这一事实。有人可以解释一下如何使用 python 脚本在 Windows 上执行带有定向输入/输出的 bash 脚本吗?

编辑(跟进问题)

感谢您的回复,我需要将 bash.exe 的完整路径作为第一个参数。然而现在,来自 RunModels.scr 的命令行调用在 python 输出中返回为command not found。例如,lscpmake。对此有何建议?

跟进 #2: 我更新了我的电话:

subprocess.call(['C:\\cygwin64\\bin\\bash.exe', '-l', 'RunModels.scr'], stdin=vin, stdout=vout, cwd='C:\\path\\dir_where_RunModels\\')

我现在得到的错误是/usr/bin/bash: RunModels.scr: No such file or directory。 使用 cwd 似乎对此错误没有任何影响,无论子进程在/usr/bin/bash 中查找RunModels.scr

自行回答 我需要在调用中指定 RunModels.scr 的路径以及使用cwd

subprocess.call(['C:\\cygwin64\\bin\\bash.exe', '-l', 'C:\\path\\dir_where_RunModels\\RunModels.scr'], stdin=vin, stdout=vout, cwd='C:\\path\\dir_where_RunModels\\')

但另一个问题...

不管指定cwdRunModels.scr 执行的命令都会抛出错误,就好像RunModels.scr 在错误的目录中一样。脚本执行,但cpcd 抛出错误no such file or directory。如果我通过命令行导航到 RunModels.scr 所在的位置并以老式方式执行它,我不会收到这些错误。

【问题讨论】:

  • 由于是bash脚本,需要显式调用bash命令:全路径使用Windows路径语法。
  • 注意:打开文件时最好使用with语句。这样你就可以防止在引发异常时让它们保持打开状态。

标签: python windows bash


【解决方案1】:

Python 3.4 及以下

只需将bash.exe 放在您的subprocess.call 参数列表的首位即可。您可以删除shell=True,在这种情况下不需要这样做。

subprocess.call(['C:\\cygwin64\\bin\\bash.exe', '-l', 'RunModels.scr'], 
                 stdin=vin, stdout=vout,
                 cwd='C:\\path\\dir_where_RunModels\\')

根据 bash 的安装方式(是否在 PATH 中),您可能必须使用 bash 可执行文件的完整路径。

Python 3.5 及以上版本

subprocess.call() 已被subprocess.run() 有效替换。

subprocess.run(['C:\\cygwin64\\bin\\bash.exe', '-l', 'RunModels.scr'], 
                 stdin=vin, stdout=vout,
                 cwd='C:\\path\\dir_where_RunModels\\')

编辑:

关于第二个问题,您可能需要在 shell 调用中添加-l 选项,以确保它读取所有重启命令文件,如/etc/profile。我认为这些文件包含 bash 中 $PATH 的设置。

编辑 2:

pwd 之类的内容添加到RunModels.scr 的开头,这样您就可以确实在正确的目录中。检查 rc 文件中是否没有 cd 命令!

编辑 3:

如果 bash 找不到脚本中调用的命令之一,也会生成错误 /usr/bin/bash: RunModels.scr: No such file or directory。尝试将 -v 选项添加到 bash 以查看是否提供更多信息。

【讨论】:

  • 您必须提供 bash 的完整路径(例如 c:\\cygwin\\bin\\bash.exe),除非它位于 PATH 环境变量中。
  • 谢谢,我需要完整路径并且执行成功。如果您也可以提供帮助,我已经用后续问题更新了帖子:)
  • 感谢您迄今为止的所有帮助。我又更新了我的帖子。现在所有的命令和脚本都被识别并执行,但表现得好像RunModels.scr 位于错误的目录中。由于某种原因,在通话中使用 cwd 并不能解决我的问题。
  • @RolandSmith 我开始认为我的错误/usr/bin/bash: RunModels.scr: No such file or directory 可能是由 bash 而不是RunModels.scr 引起的。我添加了pwds 并检查了cds 没有运气。我认为这仍然是一个 Windows bash 问题。 RunModels.scr 顶部有 #!/bin/bash,这在使用 ./ 时有效。我尝试将其更改为 #!/usr/bin/bash #!/usr/bin/env bash/ 并且在从 python 脚本运行时没有任何工作。您对这是一个 bash 问题有什么想法吗?
  • @WhS4 #!-line 仅用于类 UNIX 操作系统。而当你直接调用 bash 时,它根本就没有关系。另请参阅编辑 3
猜你喜欢
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 2012-06-24
  • 1970-01-01
  • 2012-05-19
相关资源
最近更新 更多