Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sendline('') fails sometimes, but using interact and pressing enter works #13

Closed
nmz787 opened this issue Oct 31, 2019 · 7 comments
Closed

Comments

@nmz787
Copy link

nmz787 commented Oct 31, 2019

My expected string is found (something like press enter to continue), but using sendline('') leaves the program hanging. Trying to use import pdb; pdb.set_trace() and manually re-sending the newline fails too (still hangs). If I use p.interact() instead of breaking with pdb.set_trace(), I get a new console/terminal popping up, showing the whole previous console output log, I see a lot of weird characters like ���������

If I press enter in the popped-up console, then my program continues running (but I don't know how to return control to Python).

How do I get sendline working properly?

(Sorry this is a work project which I can't post code of... I'll try to replicate with something I can share)

@nmz787
Copy link
Author

nmz787 commented Oct 31, 2019

I wonder if it is some colored characters or something in the earlier console output... I'm finding that newlines just seem to fail after some point in my series of command executions

@nmz787
Copy link
Author

nmz787 commented Nov 1, 2019

Ok, here's a testcase. It wasn't caused by colored output.
I am running with py -3 testcase_main.py

When you comment out the first line of testcase.py then things work. Unfortunately I can't remove this import in my real-world usage.

You can uncomment the shell.interact() and get the popup shell, and then press enter and the script will continue.

testcase.py

import readline  # pip install pyreadline
# comment out the above import and all will be OK!!!
# unfortunately my real-world use-case is requiring that module, and removing it is out of my control
print("Your text")
print('back to normal now') 
input("Run SVN Update?([yes]/no) : (assuming 'yes' in 1s-Press key to change.)")

print('WARNING!  There are local changes un-committed:')
print(r'    C:\Users\someone\git\test\blah\SOME_thing is missing!')
input('^^^ Press enter to acknowledge the above ^^^')

print('done!')

testcase_main.py

print("Your text")
import time
from wexpect import spawn
from wexpect import TIMEOUT, EOF
unique_prompt = '123123expect123123'
shell = spawn('cmd.exe')
time.sleep(1)
shell.sendline('PROMPT {}'.format(unique_prompt))
shell.expect(unique_prompt)
print('*** got cmd prompt')
shell.sendline('py -3 testcase.py')
DEBUG=False
i=0
always_break = False
while i!=1:
    i = shell.expect([TIMEOUT,
                  unique_prompt,
                  u'Press ENTER to continue',
                  u"Run SVN Update\?\(\[yes\]\/no\)\s*: \(assuming 'yes' in 1s",
                  u'Run SVN Update\?\(\[yes\]\/no\)',
                  u'User for SVN:',
                  u'Password:',
                  u'Username:',
                  u'\^\^\^ Press enter to acknowledge the above \^\^\^'
                  ], timeout=4)
    print('expect gave I is : {}'.format(i))
    if i == 2:
        shell.sendline('\n')
    elif (i == 4 or i==3):
        shell.sendline(' yes') #note the leading space is required!!!
        # shell.interact()   # if you uncomment this line, you can press enter in the popup and it will continue
    elif (i == 5 or i == 7):
        shell.sendline(USERNAME)
    elif i == 6:
        shell.logfile_read = None # so we don't print the password during debug
        shell.sendline(PASSWORD)
        if DEBUG:
            shell.logfile_read=log
    elif i==8:
        numbytes = shell.sendline()
        print('numbytes from sendline was: {}'.format(numbytes))
    elif i==9:
        shell.sendline('\r\n')
print('*** finished expecting')

@nmz787
Copy link
Author

nmz787 commented Nov 4, 2019

I'm not much of a Windows API expert, where should I start debugging this?

@nmz787
Copy link
Author

nmz787 commented Nov 5, 2019

I have talked with some other people who work on the tools I am using wexpect to automate, and they said pyreadline should not be required, so I think I am able to have a function which attempts to delete the installed module/package so it doesn't interfere with wexpect.

I am sure it would be good to figure out how to fix this properly though, as I guess other programs might cause a similar problem.

@nmz787
Copy link
Author

nmz787 commented Mar 3, 2020

I found if you replace the import readline code in testcase.py with this:

import sys
import mock
sys.modules['readline'] = mock.Mock()

then you I think you can get around later sub-module imports inside the same process.

@raczben
Copy link
Owner

raczben commented Mar 6, 2020

Sorry, for my passive behavior.

I've tried, and I could reproduce your issue.

I've added an interact() call to see what happening in the console window. (Please add it for following tests)

...
shell = spawn('cmd.exe')
shell.interact()                        # <<<
time.sleep(1)
...

And, here is the wondow. (Using Python 3.7.5, virtualenv, wexpect<=3.0.0)
image

BUT

I've upgraded wexpect to 3.1.0
And, here is the wondow:
image

And the program finished succesfully.

(virt_i13) C:\Users\usr>python testcase_main.py
Your text
*** got cmd prompt
expect gave I is : 1
*** finished expecting

Please upgrade wexpect to 3.1.0, or higher. Note, that wexpect is not a one-file module anymore. You need to install it.

@raczben
Copy link
Owner

raczben commented Apr 8, 2020

Are your issue solved? If not please feel free to reopen this thread.

@raczben raczben closed this as completed Apr 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants