2

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()?

David
  • 35
  • 1
  • 1
  • 5
  • At a first glance, this looks like something doable with a Queue (https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes) but I just took a quick, quick peek a the question. Maybe the link will give you some ideas, though. **:-)** – Savir Dec 03 '14 at 18:29
  • I cannot answer as I do not have a definitive solution. But I had a similar problem where I wanted to send a message to a server (client/server). This was in Python 2.7 I believe, and I used the ftp module if I recall correctly. Edit: https://docs.python.org/2/library/ftplib.html –  Dec 03 '14 at 19:08
  • Wait... you wanna do this to generate numbers in your `typer` to try to unlock the password? – Savir Dec 03 '14 at 20:16
  • If the goal isn't primarily to synthesize keyboard events, but to have pieces of Python code talk to each other, you should consider refactoring the combo lock into a module you can `import` from the guesser. – tripleee Dec 03 '14 at 20:27
  • I've updated my answer to simulate a user interaction, but without further clarification, I still don't know if that's what you ( @David) wanted. – Savir Dec 03 '14 at 21:15
  • @BorrajaX Thanks for writing out this answer. Your output was what I was envisioning. However I can't get Pexpect to install correctly- actually trying Winpexpect for windows. Hopefully I'll figure it out. Thanks again! – David Dec 04 '14 at 00:54

1 Answers1

1

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
Community
  • 1
  • 1
Savir
  • 17,568
  • 15
  • 82
  • 136