Some terminals will send ^? as backspace, some other terminals will send ^H.
Most of the terminals can be configured to change their behavior.
I do not want to deal with all the possible combinations but I would like to accept both ^? and ^H as a backspace from python.
doing this
os.system("stty erase '^?'")
I will accept the first option and with
os.system("stty erase '^H'")
I will accept the second one but the first will be no longer available.
I would like to use
raw_input("userinput>>")
to grab the input.
The only way I was able to figure out is implementing my own shell which works not on "raw based input" but on "char based input".
Any better (and quicker) idea?
The built-in function raw_input() (or input() in Python 3) will automatically use the readline library after importing it. This gives you a nice and full-feautured line editor, and it is probably your best bet on platforms where it is available, as long as you don't mind Readline having a contagious licence (GPL).
I don't know your question exactly. IMO, you need a method to read some line-based text(including some special character) from console to program.
No matter what method you use, if read this character have special mean in different console, you should confront a console(not only system-specific, but also console-specific) question, all text in console will be store in buffer first, and then show in screen, finally processed and send in to your program. Another way to surround this problem is to use a raw line-obtaining console environment.
You can add a special method(a decorator) to decorate the raw_input() or somewhat input method to process special word.
After solved that question
using this snippet can deal with input,:
def pre():
textline=raw_input()
# ^? should replace to the specific value.
textline.replace("^?","^H")
return textline
To be faster, maybe invoke some system function depend on OS is an idea. But in fact, IO in python is faster enough for common jobs.
To fix ^? on erase do stty erase ^H
Related
Is there a way, I can change the default encoding in python only for printing?
Can the behaviour of the print statement be changed in general?
I don't want to do it with sys.setdefaultencoding(), because this would change it for the whole script, but I don't know if every module I use supports unicode...
I know I could do it with print u'äöü'.encode('utf-8') but it would be awful to use it everytime...
Any suggestions?
While I don't think you can do it just for printing (using print explicitly), you probably can accomplish what you want using
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
This changes the encoding for all "normal" program output. If you're not familiar with them, you may want to read this article on standard streams
I am working with pythons pexpect module to automate tasks, I need help in figuring out key characters to use with sendcontrol. how could one send the controlkey ENTER ? and for future reference how can we find the key characters?
here is the code i am working on.
#!/usr/bin/env python
import pexpect
id = pexpect.spawn ('ftp 192.168.3.140')
id.expect_exact('Name')
id.sendline ('anonymous')
id.expect_exact ('Password')
*# Not sure how to send the enter control key
id.sendcontrol ('???')*
id.expect_exact ('ftp')
id.sendline ('dir')
id.expect_exact ('ftp')
lines = id.before.split ('\n')
for line in lines :
print line
pexpect has no sendcontrol() method. In your example you appear to be trying to send an empty line. To do that, use:
id.sendline('')
If you need to send real control characters then you can send() a string that contains the appropriate character value. For instance, to send a control-C you would:
id.send('\003')
or:
id.send(chr(3))
Responses to comment #2:
Sorry, I typo'ed the module name -- now fixed. More importantly, I was looking at old documentation on noah.org instead of the latest documentation at SourceForge. The newer documentation does show a sendcontrol() method. It takes an argument that is either a letter (for instance, sendcontrol('c') sends a control-C) or one of a variety of punctuation characters representing the control characters that don't correspond to letters. But really sendcontrol() is just a convenient wrapper around the send() method, which is what sendcontrol() calls after after it has calculated the actual value that you want to send. You can read the source for yourself at line 973 of this file.
I don't understand why id.sendline('') does not work, especially given that it apparently works for sending the user name to the spawned ftp program. If you want to try using sendcontrol() instead then that would be either:
id.sendcontrol('j')
to send a Linefeed character (which is control-j, or decimal 10) or:
id.sendcontrol('m')
to send a Carriage Return (which is control-m, or decimal 13).
If those don't work then please explain exactly what does happen, and how that differs from what you wanted or expected to happen.
If you're just looking to "press enter", you can send a newline:
id.send("\n")
As for other characters that you might want to use sendcontrol() with, I found this useful: https://condor.depaul.edu/sjost/lsp121/documents/ascii-npr.htm
For instance, I was interested in Ctrl+v. Looking it up in the table shows this line:
control character
python & java
decimal
description
^v
\x16
22
synchronous idle
So if I want to send that character, I can do any of these:
id.send('\x16')
id.send(chr(22))
id.sendcontrol('v')
sendcontrol() just looks up the correct character to send and then sends it like any other text
For keys not listed in that table, you can run this script: https://github.com/pexpect/pexpect/blob/master/tests/getch.py (ctrl space to exit)
For instance, ran that script and pressed F4 and it said:
27<STOP>
79<STOP>
83<STOP>
So then to press F4 via pexpect:
id.send(chr(27) + chr(79) + chr(83))
I'm trying to write a python script to access several Cisco network devices. Sadly the devices are not set up the same, some have banners up that appear at weird places. These banners might have the patterns that have some of the same stuff a prompt might have.
For example, once I log in I expect a prompt of 'hostname#', so I basically use a pexpect('#') I might have to handle certain other prompts such as 'hostname>' as well so pexpect('>') works. I'll really have a list of possible prompts, plus a timeout and act accordingly.
This is fine unless a banner shows up in the middle somewhere. For example, after logging in a banner might show up that says ## Welcome ## and be there right before the prompt. I believe if I could tell pexpect to ignore the regular expression #.*\r I'd be fine, but I'm not sure this is possible. Is it possible to have pexpect ignore a string, or is there a better way to go about this?
A solution I used to use back in the BBS days was to look for a prompt, and then immediately after I got one, look for a line break or a space with a timeout of a second or two. If the second wait timed out, that meant I was really waiting at a prompt. Since pexpect uses regular expressions, you can actually check to see if you receive any character within a second after a prompt.
def wait_for_prompt(session, prompt, timeout=1):
gotprompt = 0
while not gotprompt:
session.expect(prompt, timeout=None)
gotprompt = session.expect([".", pexpect.TIMEOUT], timeout=timeout)
child = pexpect.spawn("ssh ...")
wait_for_prompt(child, "[#>] ?")
I've never actually used this library before so this may need some tweaking, but it's an approach I used successfully in the '80s. :-)
The Python pexpect module waits for matching input. You can't actually ignore input, except by creating regular expressions that will not match ambiguous or undesirable input. Instead of creating one really complex regex, though, pexpect can also handle lists of regular expressions. You then anchor those regular expressions to reduce ambiguity.
For example, you can easily differentiate between a command prompt and a banner by anchoring the match to the start or end of the line, and making the match as exact as possible:
users = ['fred', 'ginger']
user_prompt = '^(?:%s)#.*?\$ $' % '|'.join(users)
child.expect (['hostname# $', 'hostname> $', user_prompt])
They key is to understand what input you want to match, build an unambiguous regular expression with anchors, and then update your expressions whenever you find a mismatch--which hopefully won't be too often because you didn't create overly-greedy patterns in the first place.
Once expect has found a match it sets the 'before', 'after', and 'match' attributes on the process instance. You could use these to write some logic.
Alternatively you could just craft a better regex that only matches the prompt that you want. Even r'>$|#$' would probably do what you want since it is only going to match those characters at the end of a line.
What (if any) are the differences between the following two methods of reading a line from standard input: raw_input() and sys.stdin.readline() ? And in which cases one of these methods is preferable over the other ?
raw_input() takes an optional prompt argument. It also strips the trailing newline character from the string it returns, and supports history features if the readline module is loaded.
readline() takes an optional size argument, does not strip the trailing newline character and does not support history whatsoever.
Since they don't do the same thing, they're not really interchangeable. I personally prefer using raw_input() to fetch user input, and readline() to read lines out of a file.
"However, from the point of view of many Python beginners and educators, the use of sys.stdin.readline() presents the following problems:
Compared to the name "raw_input", the name "sys.stdin.readline()" is clunky and inelegant.
The names "sys" and "stdin" have no meaning for most beginners, who are mainly interested in what the function does, and not where in the package structure it is located. The lack of meaning also makes it difficult to remember: is it "sys.stdin.readline()", or " stdin.sys.readline()"? To a programming novice, there is not any obvious reason to prefer one over the other. In contrast, functions simple and direct names like print, input, and raw_input, and open are easier to remember." from here: http://www.python.org/dev/peps/pep-3111/
Am I correct in thinking that that Python doesn't have a direct equivalent for Perl's __END__?
print "Perl...\n";
__END__
End of code. I can put anything I want here.
One thought that occurred to me was to use a triple-quoted string. Is there a better way to achieve this in Python?
print "Python..."
"""
End of code. I can put anything I want here.
"""
The __END__ block in perl dates from a time when programmers had to work with data from the outside world and liked to keep examples of it in the program itself.
Hard to imagine I know.
It was useful for example if you had a moving target like a hardware log file with mutating messages due to firmware updates where you wanted to compare old and new versions of the line or keep notes not strictly related to the programs operations ("Code seems slow on day x of month every month") or as mentioned above a reference set of data to run the program against. Telcos are an example of an industry where this was a frequent requirement.
Lastly Python's cult like restrictiveness seems to have a real and tiresome effect on the mindset of its advocates, if your only response to a question is "Why would you want to that when you could do X?" when X is not as useful please keep quiet++.
The triple-quote form you suggested will still create a python string, whereas Perl's parser simply ignores anything after __END__. You can't write:
"""
I can put anything in here...
Anything!
"""
import os
os.system("rm -rf /")
Comments are more suitable in my opinion.
#__END__
#Whatever I write here will be ignored
#Woohoo !
What you're asking for does not exist.
Proof: http://www.mail-archive.com/python-list#python.org/msg156396.html
A simple solution is to escape any " as \" and do a normal multi line string -- see official docs: http://docs.python.org/tutorial/introduction.html#strings
( Also, atexit doesn't work: http://www.mail-archive.com/python-list#python.org/msg156364.html )
Hm, what about sys.exit(0) ? (assuming you do import sys above it, of course)
As to why it would useful, sometimes I sit down to do a substantial rewrite of something and want to mark my "good up to this point" place.
By using sys.exit(0) in a temporary manner, I know nothing below that point will get executed, therefore if there's a problem (e.g., server error) I know it had to be above that point.
I like it slightly better than commenting out the rest of the file, just because there are more chances to make a mistake and uncomment something (stray key press at beginning of line), and also because it seems better to insert 1 line (which will later be removed), than to modify X-many lines which will then have to be un-modified later.
But yeah, this is splitting hairs; commenting works great too... assuming your editor supports easily commenting out a region, of course; if not, sys.exit(0) all the way!
I use __END__ all the time for multiples of the reasons given. I've been doing it for so long now that I put it (usually preceded by an exit('0');), along with BEGIN {} / END{} routines, in by force-of-habit. It is a shame that Python doesn't have an equivalent, but I just comment-out the lines at the bottom: extraneous, but that's about what you get with one way to rule them all languages.
Python does not have a direct equivalent to this.
Why do you want it? It doesn't sound like a really great thing to have when there are more consistent ways like putting the text at the end as comments (that's how we include arbitrary text in Python source files. Triple quoted strings are for making multi-line strings, not for non-code-related text.)
Your editor should be able to make using many lines of comments easy for you.