【问题标题】:Replacing os.popen() with subprocess.Popen()用 subprocess.Popen() 替换 os.popen()
【发布时间】:2013-10-24 19:45:25
【问题描述】:

我目前正在自学 Python,并且正在编写我的第一个 shell 脚本。它是一个 linux 文件搜索 shell 脚本,使用“md5hash”识别重复文件。它仅用于学习目的,而不是用于实际项目。

这是我的代码:

from subprocess import Popen, PIPE
import os
def index(directory):
    stack = [directory]
    files = []
    while stack:
        directory = stack.pop()
        for file in os.listdir(directory):
            fullname = os.path.join(directory, file)
            if search_term in fullname:
                files.append(fullname)
            if os.path.isdir(fullname) and not os.path.islink(fullname):
                stack.append(fullname)
    return files

from collections import defaultdict

def check(directory):
    files = index(directory)
    if len(files) < 1:
        print("No file(s) meets your search criteria")
    else:
        print ("List of files that match your criteria:")
        for x in files:
            print (x)
        print ("-----------------------------------------------------------------")
    values = []
    for x in files:
        cmd = ['md5sum', x]
        proc = Popen(cmd, stdout=PIPE)
        (out, err) = proc.communicate()
        a = out.split(' ', 1)
        values.append(a[0])
    proc.stdout.close()
    stat = os.waitpid(proc.pid, 0)
    D = defaultdict(list)
    for i,item in enumerate(values):
        D[item].append(i)
    D = {k:v for k,v in D.items() if len(v)>1}
    for x in D:
        if len(D[x]) > 1:
            print ("File", files[D[x][0]], "is same file(s) as:")
            for y in range(1, len(D[x])):
                print (files[D[x][y]]) 

search_term = input('Enter a (part of) file name for search:')
a = input('Where to look for a file? (enter full path)')
check(a)

我关于代码的问题:

1.有人建议我用 subprocess.Popen() 替换已弃用的 os.popen()

但我不知道该怎么做。我尝试了几种解决方案,我发现这些解决方案已经存在于 stackoverflow 上,但似乎没有一个适用于我的案例,而且每个解决方案都会产生某种错误。例如,像这样处理它:

from subprocess import Popen, PIPE
...
cmd = ['md5sum', f]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
proc.stdout.close()
stat = os.waitpid(proc.pid, 0)

我收到NameError: global name 'subprocess' is not defined 错误。

我真的迷路了,因此我们非常感谢您提供的任何帮助。

2。如何使这个程序能够从顶部(根)搜索?

如果我输入“/”作为搜索路径,我会得到 PermissionError: [Errno 1] Operation not permitted: '/proc/1871/map_files' 我的脚本是否需要 sudo 权限?

我正在尝试通过互联网为自己学习 Python。感谢您的帮助!

【问题讨论】:

    标签: python shell subprocess popen python-3.3


    【解决方案1】:

    1. 如果你使用from module import variable语法,你可以直接访问variable,在这种情况下:

    from subprocess import Popen, PIPE
    proc = Popen(cmd, stdout=PIPE)
    

    如果您使用import module 语法,则需要添加模块名称(就像您在代码中所做的那样):

    import subprocess
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    

    有关导入的更多信息,我推荐文章Understanding imports and PYTHONPATH

    2. 文件系统上的某些文件只能以root 身份读取,例如/proc/ 目录中的某些文件。要阅读它们,您的 Python 脚本需要 root 访问权限,例如通过 sudo

    【讨论】:

    • 在这种情况下,我需要拆分 readline() 函数的结果,因此我将其存储在变量中:res = proc.stdout.readline() 但是当我尝试 a = res.split(' ', 1) 时,我得到了 TypeError: Type str doesn't support the buffer API 。你能帮我解决这个问题吗?
    • 这个错误的原因比较复杂。我找到了一个适合您的简单解决方案,请参阅:stackoverflow.com/questions/7468668/python-subprocess-readlines。调用(out, err) = proc.communicate()后,应该可以访问out中的命令输出了。
    • 仍然收到相同的错误代码...我一定是做错了什么。我也尝试过您已链接我的问题提供的解决方案,但发生了同样的错误。我已经编辑了原始代码供您查看...
    • 如果在交互式解释器中测试子进程会发生什么?它对我有用:pastebin.com/M0MipK3H
    • 啊,这是 Python 3 特有的行为。我无法解释,但这是因为out 是一个字节串(b'...')。如果将其转换为常规字符串 (str(out)),它应该可以工作。
    猜你喜欢
    • 2013-07-28
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2020-02-09
    相关资源
    最近更新 更多