Python program write to another python program? - python

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

Related

Getting skipped out of the loop without letting me type

So I made a very simple Auto-typer and want to be able to run it again or quit it.
All works perfectly fine but at the end the "ending = input()" doesnt let me type it just exits out of the programm. Any reason why?
import pyautogui
import time
import os
def clearConsole():
command = 'clear'
if os.name in ('nt', 'dos'): # If Machine is running on Windows, use cls
command = 'cls'
os.system(command)
break_loop = 1
while break_loop <= 1:
secs_inbetween_actions = float(input("""
Seconds between actions(should be float but int is also ok): """))
no_of_lines = int(input("""
How many Lines do you want to write?(Only int): """))
time_between_action = int(input("""
How long should the time between enter and writing be?: """))
lines = ""
print("""
Write your Text under this message (You have """ + str(no_of_lines) + """ line(s) to wite)
""")
for i in range(no_of_lines):
lines += input() + "\n"
print("-------------------------------------")
while time_between_action > 0:
time_between_action = time_between_action - 1
print('Time Left until writing -+==> ' + str(time_between_action))
time.sleep(1)
print("-------------------------------------")
pyautogui.typewrite(lines, interval=secs_inbetween_actions)
ending = input("If you want to use this aplication once again type 'y' + 'enter key' ,if not press the 'enter key': ")
if ending == "y":
break_loop = 1
clearConsole()
else:
break_loop += 1
This is a rather fun little problem. It occurs, as #Barmar notes, because pyautogui.typewrite() is writing to the console for you. I incorrectly thought that it was not happening when there was no delay between actions, which was a far more puzzling little problem.
In this case the solution is easy: add after your typewrite():
if lines:
input()
To absorb what has just been typed for you.

how do i interup input in processing in python

I try to make a simple game, give a sum random number and input to answer it, I try to limit the time for input, but I can stop the input processing when timeout.
score=0
from threading import Timer
while score<=3:
import random
a=random.randint(0,100)
b=random.randint(0,100)
sum=a+b
d=str(sum)
while True:
print(a,"+",b,"=")
timeout = 3
t = Timer(timeout, print, ['Sorry, times up'])
t.start()
prompt = "you have %d s to input your answer\n" % timeout
c = input(prompt)
t.cancel()
#i want to stop input c and make other code like 'do you want to play again'
if c.isdigit():
break
else:
print('invalid input')
continue
result=c
if result==d:
score=score+1
print('your score',score)
else:
score=score-1
print('your score',score)
else:
print('you win')
Similar question has been answered before here.
I have tested it before and the following codes work in my Ubuntu. I'm not sure if this works in Windows too.
import sys
from select import select
timeout = 5
print "What is your name?"
# Assignment to three different variables based on select() paramenters
# rlist: wait until ready for reading
# wlist: wait until ready for writing
# xlist: wait for an "exceptional condition"
rlist, _, _ = select([sys.stdin], [], [], timeout)
if rlist:
s = sys.stdin.readline()
print "Your name is: %s" %(s)
else:
print "Timeout!! Try again."
Hope this helps.
This works also for me (Debian)
import sys, termios, signal
from _thread import interrupt_main
while True:
timeout = 3
signal.signal(signal.SIGALRM, lambda x,y: interrupt_main())
signal.alarm(3)
try:
c = input("Number? ")
except:
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
answer = input('\nContinue? ')
if (len(answer) == 0) or (answer.lower()[0] != 'y'):
break
signal.alarm(0)
If you are using Windows you could try using interrupt_main as handler for Timer
t = Timer(timeout, interrupt_main)
This approach does not fully work for me. In my linux box the signal handler is able to interrupt the input() call but the timer handler, however, not. Only if you press Enter, the program flow follows to the "Continue" question

How do you add mutiple arguments to a subprocess line?

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)

Interrupting a timer

I'm creating part of a program right now for a personal project and I need some help on one aspect of it.
Here is how the program works:
User enters the amount of time to run
User enters the text - Files are modified
Timer is started
optional User can enter "password" to interrupt the timer
Actions are reversed
I have all of the steps coded except the Timer because I'm trying to figure out the best way to do this. Ideally, I'd like the timer to be displaying a countdown, and if the user enters a certain "password" the timer is interrupted and it skips to step number 5.
Would the best way to do this be with a thread? I haven't worked much with threads in the past. I just need someway for the timer to be displayed while also giving control back to the user in case they want to enter that password.
Thanks for any help you provide.
Here's the code:
import time
import urllib
import sys
def restore():
backup = open(r'...backupfile.txt','r')
text = open(r'...file.txt', 'w+')
text.seek(0)
for line in backup:
text.write(line)
backup.close()
text.close()
text = open(r'...file.txt', 'a+')
backup = open(r'...backupfile.txt','w+')
text.seek(0)
for line in text:
backup.write(line)
backup.close()
while True:
url = raw_input('Please enter a URL: ')
try:
if url[:7] != 'http://':
urllib.urlopen('http://' + url)
else:
urllib.urlopen(url)
except IOError:
print "Not a real URL"
continue
text.write(url)
while True:
choice = raw_input('Would you like to enter another url? (y/n): ')
try:
if choice == 'y' or choice == 'n':
break
except:
continue
if choice == 'y':
text.seek(2)
continue
elif choice == 'n':
while True:
choice = raw_input('Would you to restore your file to the original backup (y/n): ')
try:
if choice == 'y' or choice == 'n':
break
except:
continue
if choice == 'y':
text.close()
restore()
sys.exit('Your file has been restored')
else:
text.close()
sys.exit('Your file has been modified')
As you can see, I haven't added the timing part yet. It's pretty straight forward, just adding urls to a text file and then closing them. If the user wants the original file, reverse() is called.
Under Windows you can use msvcrt to ask for a key. Asking for a password is actually more complex, because you have to track several keys. This program stops with F1.
import time
import msvcrt
from threading import Thread
import threading
class worker(Thread):
def __init__(self,maxsec):
self._maxsec = maxsec
Thread.__init__(self)
self._stop = threading.Event()
def run(self):
i = 1
start = time.time()
while not self.stopped():
t = time.time()
dif = t-start
time.sleep(1) # you want to take this out later (implement progressbar)
# print something once in a while
if i%2==0: print '.',
#check key pressed
if msvcrt.kbhit():
if ord(msvcrt.getch()) == 59:
self.stop()
#do stuff
# timeout
if dif > self._maxsec:
break
i+=1
def stop(self):
print 'thread stopped'
self._stop.set()
def stopped(self):
return self._stop.isSet()
print 'number of seconds to run '
timeToRun = raw_input()
#input files
#not implemented
#run
w = worker(timeToRun)
w.run()
#reverse actions

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