Python: Closing a for loop by reading stdout

回眸只為那壹抹淺笑 提交于 2019-12-14 02:43:22

问题


import os

dictionaryfile = "/root/john.txt"
pgpencryptedfile = "helloworld.txt.gpg"

array = open(dictionaryfile).readlines()


for x in array:
    x = x.rstrip('\n')
    newstring = "echo " + x + " | gpg --passphrase-fd 0 " + pgpencryptedfile
    os.popen(newstring)

I need to create something inside the for loop that will read gpg's output. When gpg outputs this string gpg: WARNING: message was not integrity protected, I need the loop to close and print Success!

How can I do this, and what is the reasoning behind it?

Thanks Everyone!


回答1:


import subprocess


def check_file(dictfile, pgpfile):
    # Command to run, constructed as a list to prevent shell-escaping accidents
    cmd = ["gpg", "--passphrase-fd", "0", pgpfile]

    # Launch process, with stdin/stdout wired up to `p.stdout` and `p.stdin`
    p = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE)

    # Read dictfile, and send contents to stdin
    passphrase = open(dictfile).read()
    p.stdin.write(passphrase)

    # Read stdout and check for message
    stdout, stderr = p.communicate()
    for line in stdout.splitlines():
        if line.strip() == "gpg: WARNING: message was not integrity protected":
            # Relevant line was found
            return True

    # Line not found
    return False

Then to use:

not_integrity_protected = check_file("/root/john.txt", "helloworld.txt.gpg")
if not_integrity_protected:
    print "Success!"

If the "gpg: WARNING:" message is actually on stderr (which I would suspect it is), change the subprocess.Popen line to this:

p = subprocess.Popen(cmd, stdin = subprocess.PIPE, stderr = subprocess.PIPE)

..and the for loop from stdout to stderr, like this:

for line in stderr.splitlines():



回答2:


Use subprocess.check_output to call gpg and break the loop based on its output.

Something like this (untested since I don't know anything about gpg):

import subprocess

dictionaryfile = "/root/john.txt"
pgpencryptedfile = "helloworld.txt.gpg"

with open(dictionaryfile, 'r') as f:
    for line in f:
        x = line.rstrip('\n')
        cmd = ["echo " + x + " | gpg --passphrase-fd 0 " + pgpencryptedfile]
        output = subprocess.check_output(cmd, shell=True)
        if 'gpg: WARNING: message was not integrity protected' in output:
            break



回答3:


You could use the subprocess module which allows you to use:

subprocess.call(args, *, stdin, stdout, stderr, shell)

(See the Python Documentation for how to use the parameters.)

This is good because you can easily read in the exit code of whatever program you call.

For example if you change 'newstring' to:

"echo " + x + " | gpg --passphrase-fd 0 " + pgpencryptedfile | grep 'gpg: WARNING: message was not integrity protected'

grep will then return 0 if there is a match and a 1 if not matches are found. (Source)

This exit code from grep will be returned from the subprocess.call() function and you can easily store it in a variable and use an if statement.

Edit: As Matthew Adams mentions below, you could also read the exit code of gpg itself.



来源:https://stackoverflow.com/questions/12811374/python-closing-a-for-loop-by-reading-stdout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!