【问题标题】:subprocess.run() fails when using a glob expression as an argument; works fine in shell [duplicate]使用 glob 表达式作为参数时 subprocess.run() 失败;在外壳中工作正常[重复]
【发布时间】:2022-01-27 11:21:43
【问题描述】:

我正在尝试在 Ubuntu 上使用 Python3 运行 bash 命令。这是代码(sc.py)

import subprocess
path = '/home/user2/*'
result = subprocess.run(['ls', path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
print(result.stdout.decode("utf-8"))
print(result.stderr.decode("utf-8"))

python3 sc.pysudo python3 sc.py 都给予

ls: cannot access '/home/u0502210301/*': No such file or directory

但是,直接运行命令 ls /home/user2/* 并按预期输出 bash。

以上所有测试均使用 sudo 帐户 user1 运行。

有人可以给我一个提示吗?

【问题讨论】:

  • 如果ls 是实际的命令,那么有比使用subprocess 更好的选择。如果ls 不是实际的命令,可能会有更好的选择。
  • *ls 本身没有任何意义; ls 依赖于 shell/home/user2/* 替换为 /home/user2/a.txt /home/user2/b.txt 等单个名称的列表。您没有外壳,所以没有任何替换,所以 ls 正在寻找对于名为 * 的文件,该文件不存在,因此您的错误。
  • 通配符扩展(路径末尾的 *)由 shell 完成,但您隐式使用 shell-False 运行命令。您是否正在尝试获取匹配文件的列表?如果是,don't try to parse ls,使用something native to Python like glob.glob
  • @GordonDavisson,...您添加的副本本身就是一个很好的副本,但唯一的答案(在撰写本文时)还有一些不足之处; shell=True 与其说是首选,不如说是最后的选择。
  • @CharlesDuffy 另一方面,我显然启发了您添加更好的答案!

标签: python bash glob


【解决方案1】:

这与glob expansion 有关。您期望 * 在 python 子进程 run 中处理,就像在 bash 中一样,但事实并非如此。要解决“未找到”问题,您只需将/* 删除并替换为/,因此:

import subprocess
path = '/home/user2/'
result = subprocess.run(['ls', path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
print(result.stdout.decode("utf-8"))
print(result.stderr.decode("utf-8"))

这将解决部分问题,但可能不适用于您的用例(如果您想列出 user2 的子目录中的所有文件/div)

我相信这是一个适合您的具体情况的解决方案:

import subprocess
import glob
path = '/home/user2/*'
cmd = ['ls']
cmd.extend(glob.glob(path))
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(result.stdout.decode("utf-8"))
print(result.stderr.decode("utf-8"))

【讨论】:

  • 我正在为他们的问题编写解决方案。此外,他们在原始帖子中要求提示。我们都在尽力而为,伙计。
  • 当然,但这里的目标是创建教学资源。这意味着尽我们最大努力的一部分是提供有用的评论,以便读者可以了解他们给出的每个答案的局限性,或者可以改进或改进这些答案。
  • 在我看来,您在有问题的评论之后改进了答案方面做得非常好(使评论不再必要或相关,因此将其删除)。我仍然更喜欢另一个答案,因为它避免展示一种只对ls 有益的方法,但这是个人偏好(因此在那里赞成),而不是断言这个答案中的任何东西客观上都是坏的。
【解决方案2】:

path 没有扩展通配* 所以这是无效的:

path = '/home/user2/*'

改为将 glob 扩展为 ls 命令的参数条目:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import subprocess
import glob

globPath = '/home/user2/*'
result = subprocess.run(['ls'] + glob.glob(globPath), stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
print(result.stdout.decode("utf-8"))
print(result.stderr.decode("utf-8"))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-17
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多