【问题标题】:Tilde (~) isn't working in subprocess.Popen()波浪号 (~) 在 subprocess.Popen() 中不起作用
【发布时间】:2016-11-17 18:51:25
【问题描述】:

当我在我的 Ubuntu 终端中运行时:

sudo dd if=/dev/sda of=~/file bs=8k count=200k; rm -f ~/file

效果很好。

如果我通过 Python 运行它subprocess.Popen():

output, err = subprocess.Popen(['sudo', 'dd', 'if=/dev/' + disk, 'of=~/disk_benchmark_file', 'bs=8k', 'count=200k'], stderr=subprocess.PIPE).communicate()
print err

它不起作用。我得到的错误是:

dd: 无法打开 '~/disk_benchmark_file': 没有这样的文件或目录

如果我将Popen() 中的波浪号~ 更改为/home/user,那么它可以工作!

为什么会这样? 对我来说更重要的是:我怎样才能让它发挥作用? 我不知道生产中的用户名是什么。

【问题讨论】:

  • 你试过$HOME吗?

标签: python subprocess popen dd


【解决方案1】:

您需要用os.path.expanduser() 包装这些路径名:

>>> import os
>>> os.path.expanduser('~/disk_benchmark_file')
'/home/dan/disk_benchmark_file'

在您的代码中出现:

['sudo', 'dd', 'if=/dev/' + disk, 'of=~/disk_benchmark_file', 'bs=8k', 'count=200k']

应替换为:

['sudo', 'dd', 'if=/dev/' + disk, 'of=' + os.path.expanduser('~/disk_benchmark_file'), 'bs=8k', 'count=200k']

【讨论】:

    【解决方案2】:
    import os
    import shlex
    
    outfile = os.path.expanduser('~/file')
    cmd_string = 'sudo dd if=/dev/sda of=%s bs=8k count=200k; rm -f %s' % (outfile, outfile)
    cmd_list = shlex.split(cmd_string)
    
    # Then use cmd_list as argument for Popen
    

    shlex.split 是生成必须在子进程中用作command 的列表的标准且最安全的方法。它能够处理所有异常并使您的代码更易于阅读

    您可以使用os.path.expanduser('~') 找到home

    【讨论】:

    • os.path 没有 expand 方法。
    • 感谢您的回答。这个 shlex 好东西。
    【解决方案3】:

    ~ 是 shell 中用于 home 的快捷方式。为了让 shell 解释您的命令,您需要在 Popen 中设置 shell=True

    shell 参数(默认为 False)指定是否使用 shell 作为程序来执行。如果 shell 为 True,建议将 args 作为字符串而不是序列传递

    https://docs.python.org/2/library/subprocess.html

    请注意,虽然这样做有一些警告。

    【讨论】:

    • 从不推荐使用shell=True
    • 很好的解释 :-) 由于不鼓励shell=True,我想解决方案将是 os.path.expand
    • 感谢@RichArt,谨慎使用,但大多数不鼓励使用它的原因是基于清理安全问题。如果这不是生产代码并且您控制输入应该没问题。除非你只处理像 Dan D 这样的绝对值。
    猜你喜欢
    • 1970-01-01
    • 2016-03-27
    • 2017-06-15
    • 2014-04-22
    • 2012-06-20
    • 2023-03-28
    • 2013-10-13
    • 1970-01-01
    • 2018-12-03
    相关资源
    最近更新 更多