When to use subprocess.call() or subprocess.Popen(

2019-03-22 06:13发布

问题:

I have this little script that puts your wireless device into monitor mode. It does an airodump scan and then after terminating the scan dumps the output to file.txt or a variable, so then I can scrape the BSSID and whatever other info I may need.

I feel I haven't grasped the concept or difference between subprocess.call() and subprocess.Popen().

This is what I currently have:

def setup_device(): 
    try:
        output = open("file.txt", "w")
        put_device_down = subprocess.call(["ifconfig", "wlan0", "down"])
        put_device_mon = subprocess.call(["iwconfig", "wlan0", "mode", "monitor"]) 
        put_device_up = subprocess.call(["iwconfig", "wlano", "up"])
        start_device = subprocess.call(["airmon-ng", "start", "wlan0"])
        scanned_networks = subprocess.Popen(["airodump-ng", "wlan0"], stdout = output)  
        time.sleep(10)  
        scanned_networks.terminate()

    except Exception, e:
         print "Error:", e

I am still clueless about where and when and in which way to use subprocess.call() and subprocess.Popen()

The thing that I think is confusing me most is the stdout and stderr args. What is PIPE?

Another thing that I could possibly fix myself once I get a better grasp is this:

When running subprocess.Popen() and running airodump, the console window pops up showing the scan. Is there a way to hide this from the user to sort of clean things up?

回答1:

You don't have to use Popen() if you don't want to. The other functions in the module, such as .call() use Popen(), give you a simpler API to do what you want.

All console applications have 3 'file' streams: stdin for input, and stdout and stderr for output. The application decides what to write where; usually error and diagnostic information to stderr, the rest to stdout. If you want to capture the output for either of these outputs in your Python program, you specify the subprocess.PIPE argument so that the 'stream' is redirected into your program. Hence the name.

If you want to capture the output of the airodump-ng wlan0 command, it's easiest to use the subprocess.check_output() function; it takes care of the PIPE argument for you:

scanned_networks = subprocess.check_output(["airodump-ng", "wlan0"])

Now output contains whatever airodump-ng wrote to its stdout stream.

If you need to have more control over the process, then you do need to use the Popen() class:

proc = subprocess.Popen(["airodump-ng", "wlan0"], stdout=subprocess.PIPE)
for line in proc.stdout:
    # do something with line
proc.terminate()