1

I am trying to run a batch command using the subprocess module but it just isn't working. Here is my code:

import subprocess
subprocess.Popen('for /l %i in (5,1,255) do start /B ping -w 1 -n 1 192.168.0.%i | find /i "Reply"', stdout=subprocess.PIPE)
while True:
    line = p.stdout.readline()
    if not line:
        print 'DONE PING'
        break
    print line

But every time I run this code I get "WindowsError: [Error 2] The system cannot find the file specified".
How do I run this batch command using the subprocess module?

yuval
  • 2,848
  • 4
  • 31
  • 51

3 Answers3

2

Since 'for' is a cmd command, and not an executable, except for setting the shell=True param you can just add cmd /C or cmd /K depends on what you want to happen, see 'cmd /?':

C:\Users\equinox93>cmd /?
Starts a new instance of the Windows command interpreter

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
[[/S] [/C | /K] string]

/C      Carries out the command specified by string and then terminates
/K      Carries out the command specified by string but remains
/S      Modifies the treatment of string after /C or /K (see below)
/Q      Turns echo off
/D      Disable execution of AutoRun commands from registry (see below)
/A      Causes the output of internal commands to a pipe or file to be ANSI
/U      Causes the output of internal commands to a pipe or file to be
    Unicode
/T:fg   Sets the foreground/background colors (see COLOR /? for more info)
/E:ON   Enable command extensions (see below)
/E:OFF  Disable command extensions (see below)
/F:ON   Enable file and directory name completion characters (see below)
/F:OFF  Disable file and directory name completion characters (see below)
/V:ON   Enable delayed environment variable expansion using ! as the
    delimiter. For example, /V:ON would allow !var! to expand the
    variable var at execution time.  The var syntax expands variables
    at input time, which is quite a different thing when inside of a FOR
    loop.
/V:OFF  Disable delayed environment expansion.

So for example in your case the fix could be:

subprocess.Popen('cmd /C for /l %i in (5,1,255) do start /B ping -w 1 -n 1 192.168.0.%i | find /i "Reply"', stdout=subprocess.PIPE)
equinox93
  • 133
  • 9
1

You need to set the parameter shell=True so it will allow you to run cmd commands (for is not a program)

This will work :

subprocess.Popen('for /l %i in (5,1,255) do start /B ping -w 1 -n 1 192.168.0.%i | find /i "Reply"', stdout=subprocess.PIPE,  shell=True)

Edit:

Shell=True is not recommended when the command you run uses user Input. From your question it seems like it is not your case. Anyway, if you want to be sure, you can save your command into a bat file and run it with the subprocess.Popen

So you have:

subprocess.Popen('mycommand.bat', stdout=subprocess.PIPE) 

And in the file my command.bat you write:

for /l %i in (5,1,255) do start /B ping -w 1 -n 1 192.168.0.%i | find /i "Reply"
ρss
  • 5,115
  • 8
  • 43
  • 73
DorElias
  • 2,243
  • 15
  • 18
0

You could do the loop in python and call each ping separately. You can also test the exit value of each ping, rather than searching over its output.

import subprocess
import shlex

def do_ping(address):
    cmd = "ping -w 1 -n 1 {}".format(address)
    # ping exits with 0 on success, or 1-255 otherwise
    return not subprocess.call(shlex.split(cmd))

def job():
    for i in range(5, 256):
        result = do_ping("192.168.0.{}".format(i))
        if result:
            print("successful ping")
            break
    else:
        print("ping failed")

Alternatively you can do the entire program in python. By using the ping module (not part of the standard library). You'll need to modify Ping.do to return a truthful value, rather than printing the status of the ping though.

Dunes
  • 37,291
  • 7
  • 81
  • 97
  • Using this ping model requires administrator. Is their another way to do ping without admin? – yuval Sep 03 '15 at 08:08