How do you add mutiple arguments to a subprocess line? - python

I am trying to write a little program to run an executable (delprof2.exe) multiple times in a row against multiple computers. I've created three lists with the PC names in and basically need the executable to run with the switch /c:itroom01 (for example) for each machine in that list, but I don't know how to code the machine name part - you can see from the reply = 1 section how far I've got.
See code:
import os
import subprocess
itroom = ["itroom01", "itroom02", "itroom03"]
second = ["2nditroom01", "2nditroom02", "2nditroom03"]
csupport = ["csupport-m30", "csupport-m31", "csupport-m32"]
print "Which room's PCs do you want to clear out?"
print "\t(1) = ITRoom"
print "\t(2) = 2nd ITRoom"
print "\t(3) = Curriculum Support"
reply = input("Enter 1, 2 or 3: ")
if reply == 1:
for item in itroom:
subprocess.call(['c:\delprof2\DelProf2.exe /l /c:'%itroom])
raw_input("Press return to continue...")
elif reply == 2:
for item in second:
subprocess.call("c:\delprof2\DelProf2.exe /l")
raw_input("Press return to continue...")
elif reply == 3:
for item in csupport:
subprocess.call("c:\delprof2\DelProf2.exe /l")
raw_input("Press return to continue...")
else:
print "invalid response"
raw_input("Press return to continue...")
Any assistance would be most appreciated!
Thanks,
Chris.

Your issue is with string formatting. Read the tutorial to know how to do the basic formatting.
If all items are strings, you could just concatenate the strings (+):
import subprocess
reply = int(raw_input("Enter 1, 2 or 3: "))
for item in [itroom, second, csupport][reply - 1]:
subprocess.check_call([r'c:\delprof2\DelProf2.exe', '/l', '/c:' + item])
Note: if you want all subprocesses to run concurrently then you could use Popen directly:
import subprocess
reply = int(raw_input("Enter 1, 2 or 3: "))
commands = [[r'c:\delprof2\DelProf2.exe', '/l', '/c:' + item]
for item in [itroom, second, csupport][reply - 1]]
# start child processes in parallel
children = map(subprocess.Popen, commands)
# wait for processes to complete, raise an exception if any of subprocesses fail
for process, cmd in zip(children, commands):
if process.wait() != 0: # failed
raise subprocess.CalledProcessError(process.returncode, cmd)

Related

I got 'EOFError: EOF when reading a line' in the execution of my Python code. How do I fix this? [duplicate]

Let's say I want to pipe input to a Python program, and then later get input from the user, on the command line.
echo http://example.com/image.jpg | python solve_captcha.py
and the contents of solve_captcha.py are:
import sys
image_url = sys.stdin.readline()
# Download and open the captcha...
captcha = raw_input("Solve this captcha:")
# do some processing...
The above will trigger a EOFError: EOF when reading a line error.
I also tried adding a sys.stdin.close() line, which prompted a ValueError: I/O operation on closed file.
Can you pipe information to stdin and then later get input from the user?
Note: This is a stripped down, simplified example - please don't respond by saying "why do you want to do that in the first case," it's really frustrating. I just want to know whether you can pipe information to stdin and then later prompt the user for input.
There isn't a general solution to this problem. The best resource seems to be this mailing list thread.
Basically, piping into a program connects the program's stdin to that pipe, rather than to the terminal.
The mailing list thread has a couple of relatively simple solutions for *nix:
Open /dev/tty to replace sys.stdin:
sys.stdin = open('/dev/tty')
a = raw_input('Prompt: ')
Redirect stdin to another file handle when you run your script, and read from that:
sys.stdin = os.fdopen(3)
a = raw_input('Prompt: ')
$ (echo -n test | ./x.py) 3<&0
as well as the suggestion to use curses. Note that the mailing list thread is ancient so you may need to modify the solution you pick.
bash has process substitution, which creates a FIFO, which you can treat like a file, so instead of
echo http://example.com/image.jpg | python solve_captcha.py
you can use
python solve_capcha.py <(echo http://example.com/image.jpg)
You would open first argument to solve_capcha.py as a file, and I think that sys.stdin would still be available to read input from the keyboard.
Edit: if you're not using bash, you can use mkfifo to accomplish the same thing on any POSIX system:
mkfifo my_pipe
echo "http://example.com/image.jpg" > my_pipe
python solve_captcha.py my_pipe
The FIFO will block (wait without closing) for output.
You can close stdin and then reopen it to read user input.
import sys, os
data = sys.stdin.readline()
print 'Input:', data
sys.stdin.close()
sys.stdin = os.fdopen(1)
captcha = raw_input("Solve this captcha:")
print 'Captcha', captcha
Made this up to emulate raw_input(), since I had the same problem as you. The whole stdin and clear ugliness is simply to make it look pretty. So that you can see what you are typing.
def getInputFromKeyPress(promptStr=""):
if(len(promptStr)>0):
print promptStr
"""
Gets input from keypress until enter is pressed
"""
def clear(currStr):
beeString, clr="",""
for i in range(0,len(currStr)):
clr=clr+" "
beeString=beeString+"\b"
stdout.write(beeString)
stdout.write(clr)
stdout.write(beeString)
from msvcrt import kbhit, getch
from sys import stdout
resultString, userInput="", ""
while(userInput!=13):
if (kbhit()):
charG=getch()
userInput= ord(charG)
if(userInput==8):#backspace
resultString=resultString[:-1]
clear(resultString)
elif(userInput!=13):
resultString="".join([resultString,charG])
clear(resultString)
stdout.write(resultString)
if(userInput==13):
clear(resultString)
#print "\nResult:",resultString
return resultString.strip()
I updated #Bob's answer to support delete, ctrl + [left, right, home, end] keypresses and simplified the stdout clearing and rewriting.
def keypress_input(prompt_str=""):
"""
Gets input from keypress using `msvcrt` until enter is pressed.
Tries to emulate raw_input() so that it can be used with piping.
:param prompt_str: optional string to print before getting input
:type prompt_str: str
"""
from re import finditer
from msvcrt import getch
from sys import stdout
# print even if empty to create new line so that previous line won't be overwritten if it exists
print prompt_str
user_input = ""
curr_chars = []
cursor_pos = 0
backspace = 8
enter = 13
escape_code = 224
delete = 83
left = 75
right = 77
home = 71
end = 79
ctrl_left = 115
ctrl_right = 116
ctrl_home = 119
ctrl_end = 117
while user_input != enter:
char_g = getch()
user_input = ord(char_g)
prev_len = len(curr_chars) # track length for clearing stdout since length of curr_chars might change
if user_input == backspace:
if len(curr_chars) > 0 and cursor_pos <= len(curr_chars):
cursor_pos -= 1
curr_chars.pop(cursor_pos)
elif user_input == escape_code:
user_input = ord(getch())
if user_input == delete:
curr_chars.pop(cursor_pos)
elif user_input == left:
cursor_pos -= 1
elif user_input == right:
if cursor_pos < len(curr_chars):
cursor_pos += 1
elif user_input == home:
cursor_pos = 0
elif user_input == end:
cursor_pos = len(curr_chars)
elif user_input == ctrl_home:
curr_chars = curr_chars[cursor_pos:]
cursor_pos = 0
elif user_input == ctrl_end:
curr_chars = curr_chars[:cursor_pos]
cursor_pos = len(curr_chars)
elif user_input == ctrl_left:
try:
chars_left_of_cursor = "".join(curr_chars[:cursor_pos])
left_closest_space_char_index = [m.span()[0] for m in finditer(" \w", chars_left_of_cursor)][-1]
pos_diff = cursor_pos - left_closest_space_char_index - 1
cursor_pos -= pos_diff
except IndexError:
cursor_pos = 0
elif user_input == ctrl_right:
try:
chars_right_of_cursor = "".join(curr_chars[cursor_pos + 1:])
right_closest_space_char_index = [m.span()[0] for m in finditer(" \w", chars_right_of_cursor)][0]
cursor_pos += right_closest_space_char_index + 2
except IndexError:
cursor_pos = len(curr_chars) - 1
elif user_input != enter:
if cursor_pos > len(curr_chars) - 1:
curr_chars.append(char_g)
else:
curr_chars.insert(cursor_pos, char_g)
cursor_pos += 1
# clear entire line, write contents of curr_chars, reposition cursor
stdout.write("\r" + prev_len * " " + "\r")
stdout.write("".join(curr_chars))
pos_diff = len(curr_chars) - cursor_pos
stdout.write("\b" * pos_diff)
stdout.write("\r" + len(curr_chars) * " " + "\r")
stdout.write("".join(curr_chars) + "\n")
return "".join(curr_chars)

Getting my Python program to run Power Shell Script

Hello please forgive me if my question duplicate, I've searched previous questions and nothing seems to be quite the same. I'm working on a program that will scan a specific folder and search for specific file types to create a menu for a user to select. Once the user select the menu option the the corresponding file which is a power shell script. Currently My program does everything but run even a simple power shell script. I've attempted several configuration and it's not working. It would be great if someone can see what I may be doing wrong or provide me with some pointers. Code below.
##Text Menu Dynamic test
##version 1
## Created By Dragonshadow
## Code produce in Notpad++ For python v3.4.4
import os
import subprocess
import time
import pathlib
import logging
import fnmatch
import re
## Directory Enumerator
fileFolderLocationFilter = fnmatch.filter(os.listdir('C:\\Users\\myfolder\\Documents\\Automation_Scripts\\ENScripts\\'),"*.ps1")
selectedFile=""
## Menu defined setting veriables
def ENOC_menu():
files = fileFolderLocationFilter
counter = 1
print (20 * "=" , "Enoc Quick Menu" , 20 * "=")
enumFiles = list(enumerate(files))
for counter, value in enumFiles:
str = repr(counter) + ") " + repr(value);
print(str)
str = repr(counter+1) + ") Exit";
print(str)
print (57 * "_")
str = "Enter your choice [1 - " + repr((counter+1)) + "]:"
choice = int(input("Please Enter a Selection: "))
selectedFiles = enumFiles[choice]
return(selectedFiles[1])
if choice > counter :
choice = -1
elif choice != counter :
print("Please selecte a valid choice")
else:
selectedFiles = enumFiles[choice]
print(selectedFiles[1])
##selectedFiles = selectedFiles[1]
return choice
def you_sure():
opt = input("Are you sure Yes or No: ")
if opt=="Yes":
print("Continuing please wait this may take a moment...")
elif opt=="No":
print("returnig to Enoc Menu")
else: ##Stays in loop
print ("Please choose yes or no")
##count_down
def count_down ():
count_down = 10
while (count_down >= 0):
print(count_down)
count_down -= 1
if count_down == 0:
print("Task will continue")
break
##initiating loop
loop = True
while loop:
choice = ENOC_menu()
print ("\n" +"You selected "+ choice +"\n")
subprocess.call("C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe" + choice, shell=True)
##print ("---" +str(selectedFile))
You have probably already figured this out, but I the problem is in the subprocess.call() line. You are concatenating the powershell.exe path and the target file name together. See here:
>>> scriptToRun = "c:\\users\\Username\\Documents\\WindowsPowerShell\\classtestscript.ps1"
>>> powershellExe = "c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe"
>>> print(powershellExe + scriptToRun)
c:\windows\system32\windowspowershell\v1.0\powershell.exec:\users\Username\Documents\WindowsPowerShell\classtestscript.ps1
Above, the two strings are stuck together without a space between them. Windows can't make sense of what you're trying to execute.
Put a space between the two two and subprocess.call() will understand what you're trying to do:
>>> print(powershellExe + ' ' + scriptToRun)
c:\windows\system32\windowspowershell\v1.0\powershell.exe c:\users\Username\Documents\WindowsPowerShell\classtestscript.ps1

Python program write to another python program?

New to programming and started a hobby project. In Python 3.4 I put together a program to type numbers to another Python program that acts as a combo lock. The combo lock reads 3 digit combos 000-999, unlocking if the user or second Python program types the correct 3 digit combo. I've accomplished the typer program using from win32api import keybd_event and have the functions to support this.
Snippit of typer program:
def main():
os.startfile('lockprogram.py')
for num in range(0,1000):
Write(str(num).zfill(3),speed = 1000)
Press('ENTER')
main()
Here's the lock program:
def main():
start = 'locked'
while start =='locked':
password = str(input('Enter the numbered three digit password: '))
if password == str(671).zfill(3):
start = 'open'
input('You unlocked the program. Enter to continue. ')
else:
print('Incorrect.')
#End program response.
x = True
while x == True:
response = str(input('To end press q: '))
if response == 'q':
x = False
else:
print()
main()
I'd like the typer program to write specifically to the lockprogram.py and not just as keyboard presses typing out in the open. Is there anyway to accomplish this? Like a py_file.write()?
The answer I'm writing below deviates a bit from writing to file. I'm using a multiprocessing.Queue (which internally it uses a Pipe, which uses a file to communicate the processes), but from a programatic point of view, it looks like it doesn't (I don't know if this is what you want or not). If you want to go with this solution, you should take a look to the documentation of the multiprocessing module.
You can certainly implement your own inter-process communication system, if you prefer, but once you start doing multi-threaded stuff, things get ugly. If it's multi-processed, things get... well... much, much uglier, so I'd go with something that exists out there, is well tested... yadda yadda yadda
I'd make this my typer.py:
def main(q):
while True:
print "Yellou. User typed %s" % q.get()
And this my lock.py:
from multiprocessing import Process, Queue
import typer
def main():
start = 'locked'
while start == 'locked':
password = str(
input('Enter the numbered three digit password: ')
).zfill(3)
print "You entered %s" % password
if password == '671':
start = 'open'
input('You unlocked the program. Enter to continue. ')
else:
print('Incorrect.')
# End program response.
# Launch typer.py
q = Queue()
p = Process(target=typer.main, args=(q,))
p.start()
x = True
while x is True:
response = input('To end press q: ')
if response == 'q':
x = False
p.terminate()
else:
q.put(response)
if __name__ == "__main__":
main()
To be able to import typer in lock.py these two scripts musts live in a directory that contains a third python file called __init__.py . This file can be totally empty, but I'll tell python that it's currently in a package (see this and this).
Your directory structure should look something like this:
my_programs/
|> typer.py
|> lock.py
|> __init__.py
If you run your lock.py, this will happen:
Enter the numbered three digit password: 671
You entered 671
You unlocked the program. Enter to continue.
Here
To end press q: helou
To end press q: Yellou. User typed helou
howdy?
To end press q: Yellou. User typed howdy?
q
As I mentioned, I'm not sure if this is what you're looking for exactly.
EDIT (I think the OP was trying to use typer.py to find the number that unlocks "the program")
If what you want is simulate a user interaction with the lock.py, I suggest you look at pexpect. As far as I know, is multiplatform:
This would be your typer.py
import pexpect
def main():
child = pexpect.spawnu('python /path/to/lock.py')
child.expect(u"Enter the numbered three digit password:.*", timeout=1)
pwd = None
for num in range(1000):
if pwd is None:
print "Trying %s" % (num)
child.sendline(unicode(num))
i = child.expect([
u'You entered.*\r\nIncorrect.*',
u'You entered.*\r\nYou unlocked the program.*',
pexpect.EOF])
if i == 0:
print "%s didn't work" % num
elif i == 1:
print "Cracked. Num is %s" % num
pwd = num
child.terminate(force=True)
else:
print "woot?"
return pwd
print "Got %s" % main()
That should find your number:
Trying 669
669 didn't work
Trying 670
670 didn't work
Trying 671
Cracked. Num is 671
Got 671

Python Exit The loop and start the whole process from start once again

I am new to Python Scripting. I have written a code in python. it works pretty fine till now. What I need to know is how can I run it multiple times, I want to start the whole script from start if the condition fails. The sample code is below. This script is saved in file called adhocTest.py so I run the script like below in python shell
while 1 ==1:
execfile('adhocTest.py')
The function main() runs properly till the time txt1 == 2 which is received from the user input. Now when the input of txt1 changes to other than 2 it exits the script because I have given sys.exit() what I need to know is how can I start the the script adhocTest.py once again without exiting if the input of tx1 is not equal to 2. I tried to find the answer but somehow I am not getting the answer I want.
import time
import sys
import os
txt = input("please enter value \n")
def main():
txt1 = input("Please enter value only 2 \n")
if txt1 == 2:
print txt
print txt1
time.sleep(3)
else:
sys.exit()
if __name__ == '__main__':
while 1 == 1:
main()
You are only re-calling main in your else. You could re-factor as follows:
def main():
txt1 = input("Please enter value only 2 \n")
if txt1 == 2:
print txt
print txt1
time.sleep(3)
main()
Alternatively, just call main() (rather than wrapping it in a while loop) and move the loop inside. I would also pass txt explicitly rather than rely on scoping:
def main(txt):
while True:
txt1 = input("Please enter value only 2 \n")
if txt1 == 2:
print txt
print txt1
time.sleep(3)
The latter avoids issues with recursion.
I think this is what you want:
import time
import sys
import os
def main():
while True:
txt = input("please enter value \n")
txt1 = input("Please enter value only 2 \n")
if txt1 == 2:
print txt
print txt1
time.sleep(3)
if __name__ == '__main__':
sys.exit(main())

Constantly looking for user input in Python

How would I write a Python program that would always be looking for user input. I think I would want to have a variable equal to the input and then something different would happen based on what that variable equaled. So if the variable were "w" then it would execute a certain command and keep doing that until it received another input like "d" Then something different would happen but it wouldn't stop until you hit enter.
If you want to constantly look for an user input you'll need multithreading.
Example:
import threading
import queue
def console(q):
while 1:
cmd = input('> ')
q.put(cmd)
if cmd == 'quit':
break
def action_foo():
print('--> action foo')
def action_bar():
print('--> action bar')
def invalid_input():
print('---> Unknown command')
def main():
cmd_actions = {'foo': action_foo, 'bar': action_bar}
cmd_queue = queue.Queue()
dj = threading.Thread(target=console, args=(cmd_queue,))
dj.start()
while 1:
cmd = cmd_queue.get()
if cmd == 'quit':
break
action = cmd_actions.get(cmd, invalid_input)
action()
main()
As you'll see this, will get your messages a little mixed up, something like:
> foo
> --> action foo
bar
> --> action bar
cat
> --> Unknown command
quit
That's beacuse there are two threads writing to stdoutput at the same time. To sync them there's going to be need of lock:
import threading
import queue
def console(q, lock):
while 1:
input() # Afther pressing Enter you'll be in "input mode"
with lock:
cmd = input('> ')
q.put(cmd)
if cmd == 'quit':
break
def action_foo(lock):
with lock:
print('--> action foo')
# other actions
def action_bar(lock):
with lock:
print('--> action bar')
def invalid_input(lock):
with lock:
print('--> Unknown command')
def main():
cmd_actions = {'foo': action_foo, 'bar': action_bar}
cmd_queue = queue.Queue()
stdout_lock = threading.Lock()
dj = threading.Thread(target=console, args=(cmd_queue, stdout_lock))
dj.start()
while 1:
cmd = cmd_queue.get()
if cmd == 'quit':
break
action = cmd_actions.get(cmd, invalid_input)
action(stdout_lock)
main()
Ok, now it's better:
# press Enter
> foo
--> action foo
# press Enter
> bar
--> action bar
# press Enter
> cat
--> Unknown command
# press Enter
> quit
Notice that you'll need to press Enter before typing a command to enter in "input mode".
from http://www.swaroopch.com/notes/Python_en:Control_Flow
#!/usr/bin/python
# Filename: while.py
number = 23
running = True
while running:
guess = int(input('Enter an integer : '))
if guess == number:
print('Congratulations, you guessed it.')
running = False # this causes the while loop to stop
elif guess < number:
print('No, it is a little higher than that.')
else:
print('No, it is a little lower than that.')
else:
print('The while loop is over.')
# Do anything else you want to do here
print('Done')
Maybe select.select is what you are looking for, it checks if there's data ready to be read in a file descriptor so you can only read where it avoiding the need to interrupt the processing (well, in the example it waits one second but replace that 1 with 0 and it'll work perfectly):
import select
import sys
def times(f): # f: file descriptor
after = 0
while True:
changes = select.select([f], [], [], 1)
if f in changes[0]:
data = f.readline().strip()
if data == "q":
break
else:
print "After", after, "seconds you pressed", data
after += 1
times(sys.stdin)
if you want to get input repeatedly from user;
x=1
while x==1:
inp = input('get me an input:')
and based on inp you can perform any condition.
You can also use definitions, say, something like this:
def main():
(your main code)
main()
main()
though generally while loops are much cleaner and don't require global variables :)

Categories

Resources