input("Press Enter to continue..."): SyntaxError: unexpected EOF while parsing [duplicate] - python
How do I make my python script wait until the user presses any key?
In Python 3, use input():
input("Press Enter to continue...")
In Python 2, use raw_input():
raw_input("Press Enter to continue...")
This only waits for the user to press enter though.
On Windows/DOS, one might want to use msvcrt. The msvcrt module gives you access to a number of functions in the Microsoft Visual C/C++ Runtime Library (MSVCRT):
import msvcrt as m
def wait():
m.getch()
This should wait for a key press.
Notes:
In Python 3, raw_input() does not exist.
In Python 2, input(prompt) is equivalent to eval(raw_input(prompt)).
In Python 3, use input():
input("Press Enter to continue...")
In Python 2, use raw_input():
raw_input("Press Enter to continue...")
On my linux box, I use the following code. This is similar to code I've seen elsewhere (in the old python FAQs for instance) but that code spins in a tight loop where this code doesn't and there are lots of odd corner cases that code doesn't account for that this code does.
def read_single_keypress():
"""Waits for a single keypress on stdin.
This is a silly function to call if you need to do it a lot because it has
to store stdin's current setup, setup stdin for reading single keystrokes
then read the single keystroke then revert stdin back after reading the
keystroke.
Returns a tuple of characters of the key that was pressed - on Linux,
pressing keys like up arrow results in a sequence of characters. Returns
('\x03',) on KeyboardInterrupt which can happen when a signal gets
handled.
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
| termios.ISTRIP | termios.INLCR | termios. IGNCR
| termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
| termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
ret = []
try:
ret.append(sys.stdin.read(1)) # returns a single character
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save | os.O_NONBLOCK)
c = sys.stdin.read(1) # returns a single character
while len(c) > 0:
ret.append(c)
c = sys.stdin.read(1)
except KeyboardInterrupt:
ret.append('\x03')
finally:
# restore old state
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return tuple(ret)
If you are ok with depending on system commands you can use:
from __future__ import print_function
import os
import platform
if platform.system() == "Windows":
os.system("pause")
else:
os.system("/bin/bash -c 'read -s -n 1 -p \"Press any key to continue...\"'")
print()
It has been verified to work with Python 2 and 3 on Windows, Linux and Mac OS X.
Simply using
input("Press Enter to continue...")
will cause the following error when using Python 2:
SyntaxError: expected EOF while parsing.
Simple fix for the code to work on both Python 2 and Python 3 is to use:
try:
input("Press enter to continue")
except SyntaxError:
pass
Cross Platform, Python 2/3 code:
# import sys, os
def wait_key():
''' Wait for a key press on the console and return it. '''
result = None
if os.name == 'nt':
import msvcrt
result = msvcrt.getwch()
else:
import termios
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
try:
result = sys.stdin.read(1)
except IOError:
pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
return result
I removed the fctl/non-blocking stuff because it was giving IOErrors and I didn't need it. I'm using this code specifically because I want it to block. ;)
Addendum:
I implemented this in a package on PyPI with a lot of other goodies called console:
>>> from console.utils import wait_key
>>> wait_key()
'h'
The python manual provides the following:
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
while 1:
try:
c = sys.stdin.read(1)
print "Got character", repr(c)
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
which can be rolled into your use case.
I don't know of a platform independent way of doing it, but under Windows, if you use the msvcrt module, you can use its getch function:
import msvcrt
c = msvcrt.getch()
print 'you entered', c
mscvcrt also includes the non-blocking kbhit() function to see if a key was pressed without waiting (not sure if there's a corresponding curses function). Under UNIX, there is the curses package, but not sure if you can use it without using it for all of the screen output. This code works under UNIX:
import curses
stdscr = curses.initscr()
c = stdscr.getch()
print 'you entered', chr(c)
curses.endwin()
Note that curses.getch() returns the ordinal of the key pressed so to make it have the same output I had to cast it.
I am new to python and I was already thinking I am too stupid to reproduce the simplest suggestions made here.
It turns out, there's a pitfall one should know:
When a python-script is executed from IDLE, some IO-commands seem to behave completely different (as there is actually no terminal window).
Eg. msvcrt.getch is non-blocking and always returns $ff.
This has already been reported long ago (see e.g. https://bugs.python.org/issue9290 ) - and it's marked as fixed, somehow the problem seems to persist in current versions of python/IDLE.
So if any of the code posted above doesn't work for you, try running the script manually, and NOT from IDLE.
If you want to wait for enter (so the user knocking the keyboard does not cause something un-intended to happen) use
sys.stdin.readline()
You could use the keyboard library:
import keyboard
keyboard.wait('space')
print('space was pressed, continuing...')
os.system seems to always invoke sh, which does not recognize the s and n options for read. However the read command can be passed to bash:
os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")
If you want to see if they pressed a exact key (like say 'b') Do this:
while True:
choice = raw_input("> ")
if choice == 'b' :
print "You win"
input("yay")
break
Related
Is there a sort of "when input received" command? [duplicate]
How do I make my python script wait until the user presses any key?
In Python 3, use input(): input("Press Enter to continue...") In Python 2, use raw_input(): raw_input("Press Enter to continue...") This only waits for the user to press enter though. On Windows/DOS, one might want to use msvcrt. The msvcrt module gives you access to a number of functions in the Microsoft Visual C/C++ Runtime Library (MSVCRT): import msvcrt as m def wait(): m.getch() This should wait for a key press. Notes: In Python 3, raw_input() does not exist. In Python 2, input(prompt) is equivalent to eval(raw_input(prompt)).
In Python 3, use input(): input("Press Enter to continue...") In Python 2, use raw_input(): raw_input("Press Enter to continue...")
On my linux box, I use the following code. This is similar to code I've seen elsewhere (in the old python FAQs for instance) but that code spins in a tight loop where this code doesn't and there are lots of odd corner cases that code doesn't account for that this code does. def read_single_keypress(): """Waits for a single keypress on stdin. This is a silly function to call if you need to do it a lot because it has to store stdin's current setup, setup stdin for reading single keystrokes then read the single keystroke then revert stdin back after reading the keystroke. Returns a tuple of characters of the key that was pressed - on Linux, pressing keys like up arrow results in a sequence of characters. Returns ('\x03',) on KeyboardInterrupt which can happen when a signal gets handled. """ import termios, fcntl, sys, os fd = sys.stdin.fileno() # save old state flags_save = fcntl.fcntl(fd, fcntl.F_GETFL) attrs_save = termios.tcgetattr(fd) # make raw - the way to do this comes from the termios(3) man page. attrs = list(attrs_save) # copy the stored version to update # iflag attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK | termios.ISTRIP | termios.INLCR | termios. IGNCR | termios.ICRNL | termios.IXON ) # oflag attrs[1] &= ~termios.OPOST # cflag attrs[2] &= ~(termios.CSIZE | termios. PARENB) attrs[2] |= termios.CS8 # lflag attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON | termios.ISIG | termios.IEXTEN) termios.tcsetattr(fd, termios.TCSANOW, attrs) # turn off non-blocking fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK) # read a single keystroke ret = [] try: ret.append(sys.stdin.read(1)) # returns a single character fcntl.fcntl(fd, fcntl.F_SETFL, flags_save | os.O_NONBLOCK) c = sys.stdin.read(1) # returns a single character while len(c) > 0: ret.append(c) c = sys.stdin.read(1) except KeyboardInterrupt: ret.append('\x03') finally: # restore old state termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save) fcntl.fcntl(fd, fcntl.F_SETFL, flags_save) return tuple(ret)
If you are ok with depending on system commands you can use: from __future__ import print_function import os import platform if platform.system() == "Windows": os.system("pause") else: os.system("/bin/bash -c 'read -s -n 1 -p \"Press any key to continue...\"'") print() It has been verified to work with Python 2 and 3 on Windows, Linux and Mac OS X.
Simply using input("Press Enter to continue...") will cause the following error when using Python 2: SyntaxError: expected EOF while parsing. Simple fix for the code to work on both Python 2 and Python 3 is to use: try: input("Press enter to continue") except SyntaxError: pass
Cross Platform, Python 2/3 code: # import sys, os def wait_key(): ''' Wait for a key press on the console and return it. ''' result = None if os.name == 'nt': import msvcrt result = msvcrt.getwch() else: import termios fd = sys.stdin.fileno() oldterm = termios.tcgetattr(fd) newattr = termios.tcgetattr(fd) newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO termios.tcsetattr(fd, termios.TCSANOW, newattr) try: result = sys.stdin.read(1) except IOError: pass finally: termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) return result I removed the fctl/non-blocking stuff because it was giving IOErrors and I didn't need it. I'm using this code specifically because I want it to block. ;) Addendum: I implemented this in a package on PyPI with a lot of other goodies called console: >>> from console.utils import wait_key >>> wait_key() 'h'
The python manual provides the following: import termios, fcntl, sys, os fd = sys.stdin.fileno() oldterm = termios.tcgetattr(fd) newattr = termios.tcgetattr(fd) newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO termios.tcsetattr(fd, termios.TCSANOW, newattr) oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) try: while 1: try: c = sys.stdin.read(1) print "Got character", repr(c) except IOError: pass finally: termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags) which can be rolled into your use case.
I don't know of a platform independent way of doing it, but under Windows, if you use the msvcrt module, you can use its getch function: import msvcrt c = msvcrt.getch() print 'you entered', c mscvcrt also includes the non-blocking kbhit() function to see if a key was pressed without waiting (not sure if there's a corresponding curses function). Under UNIX, there is the curses package, but not sure if you can use it without using it for all of the screen output. This code works under UNIX: import curses stdscr = curses.initscr() c = stdscr.getch() print 'you entered', chr(c) curses.endwin() Note that curses.getch() returns the ordinal of the key pressed so to make it have the same output I had to cast it.
I am new to python and I was already thinking I am too stupid to reproduce the simplest suggestions made here. It turns out, there's a pitfall one should know: When a python-script is executed from IDLE, some IO-commands seem to behave completely different (as there is actually no terminal window). Eg. msvcrt.getch is non-blocking and always returns $ff. This has already been reported long ago (see e.g. https://bugs.python.org/issue9290 ) - and it's marked as fixed, somehow the problem seems to persist in current versions of python/IDLE. So if any of the code posted above doesn't work for you, try running the script manually, and NOT from IDLE.
If you want to wait for enter (so the user knocking the keyboard does not cause something un-intended to happen) use sys.stdin.readline()
You could use the keyboard library: import keyboard keyboard.wait('space') print('space was pressed, continuing...')
os.system seems to always invoke sh, which does not recognize the s and n options for read. However the read command can be passed to bash: os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")
If you want to see if they pressed a exact key (like say 'b') Do this: while True: choice = raw_input("> ") if choice == 'b' : print "You win" input("yay") break
Python 3.8.0 Weird printing bug
I have a very weird print() bug while using Threads and Termios. I have a repeating Thread catching a key via Termios while printing some stuff. But always it prints a new line it doesn't start at the beginning of the line but where the last line ended. This is my code: def func1(): while True: try: var = int(inputChar()) except ValueError: var = 0 Thread(target=func1).start() while True: print("stuff") time.sleep(2) This is my inputChar() function: import sys, tty, termios fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch This ist the expected output: stuff stuff stuff stuff stuff This is the output: stuff stuff stuff stuff stuff
I have no idea why this is happening but you can fix it by replacing the print command with print("stuff\r") or sys.stdout.write("stuff\n\r") the \r at the end is known as a cartridge return. It's useful when sys.stdout.write() is not a viable option
Python disable console in program?
I made a console game in python, and I would like to disable the console when it prints the story. It looks like this: print("First line of story") time.sleep(2) print("Second line of story") time.sleep(2) And so on... So my problem is that the player can type and mess up with the console while it's writing the story. Can I disable the typing somehow?
If you are on Unix, you can disable echoing like this: import sys import termios import time fd = sys.stdin.fileno() old = termios.tcgetattr(fd) new = termios.tcgetattr(fd) new[3] &= ~termios.ECHO termios.tcsetattr(fd, termios.TCSADRAIN, new) print("First line of story") time.sleep(2) print("Second line of story") time.sleep(2) termios.tcsetattr(fd, termios.TCSADRAIN, old) If you don't want the suppressed input to be echoed after the last tcsetattr call, you can substitute the last TCSADRAIN with TCSAFLUSH. Documentation for the termios module can be found here, which is also where the example is taken from.
Can I use Python to capture keyboard and mouse events in OSX?
I'm trying to write a simple macro recorder in Python for OSX - something which can capture mouse and key events as the script runs in the background and replay them. I can use autopy for the latter, is there a similarly simple library for the former?
I ran across a few solutions to this problem today and figured I'd circle back around and share here so others could save the search time. A nifty cross platform solution for simulating keyboard and mouse input: http://www.autopy.org/ I also found a brief but working (As of Mountain Lion) example of how to globally log key strokes. The only caveat is that you have to use Python2.6 as 2.7 doesn't seem to have the objc modules available. #!/usr/bin/python2.6 """PyObjC keylogger for Python by ljos https://github.com/ljos """ from Cocoa import * import time from Foundation import * from PyObjCTools import AppHelper class AppDelegate(NSObject): def applicationDidFinishLaunching_(self, aNotification): NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, handler) def handler(event): NSLog(u"%#", event) def main(): app = NSApplication.sharedApplication() delegate = AppDelegate.alloc().init() NSApp().setDelegate_(delegate) AppHelper.runEventLoop() if __name__ == '__main__': main() For mouse input, simply replace NSKeyDownMask with the relevant mask from the list available here: http://developer.apple.com/library/mac/#documentation/cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/Reference/Reference.html#//apple_ref/occ/clm/NSEvent/addGlobalMonitorForEventsMatchingMask:handler: For example, NSMouseMovedMask works for tracking mouse movements. From there, you can access event.locationInWindow() or other attributes.
Here's a solution without using curses: http://docs.python.org/faq/library.html#how-do-i-get-a-single-keypress-at-a-time This question was asked some time back here - Python cross-platform listening for keypresses? You might find the sample code there helpful!
I know that you can use curses for capturing key input, but im not sure about mouse input. Not only that but if im not mistaken it is included in the std library with 2.7.2.
There doesn't seem to be a way of doing this in Python on OSX.
Calvin Cheng, Thank you. your suggestion works on OS X 10.8.5. Code from http://docs.python.org/faq/library.html#how-do-i-get-a-single-keypress-at-a-time #!/usr/bin/python import termios, fcntl, sys, os fd = sys.stdin.fileno() oldterm = termios.tcgetattr(fd) newattr = termios.tcgetattr(fd) newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO termios.tcsetattr(fd, termios.TCSANOW, newattr) oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) try: while 1: try: c = sys.stdin.read(1) print "Got character", repr(c) except IOError: pass finally: termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags) One more solution Key Listeners in python?
Reading a single character (getch style) in Python is not working in Unix
Any time I use the recipe at http://code.activestate.com/recipes/134892/ I can't seem to get it working. It always throws the following error: Traceback (most recent call last): ... old_settings = termios.tcgetattr(fd) termios.error: (22, 'Invalid argument) My best thought is that it is because I'm running it in Eclipse so termios is throwing a fit about the file descriptor.
This is working on Ubuntu 8.04.1 , Python 2.5.2, i get no such error. May be you should try it from command line, eclipse may be using its own stdin, i get exact same error if I run it from Wing IDE, but from command line it works great. Reason is that IDE e.g Wing is using there own class netserver.CDbgInputStream as sys.stdin so sys.stdin.fileno is zero, thats why the error. Basically IDE stdin is not a tty (print sys.stdin.isatty() is False) class _GetchUnix: def __init__(self): import tty, sys def __call__(self): import sys, tty, termios fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch getch = _GetchUnix() print getch()
Putting terminal into raw mode isn't always a good idea. Actually it's enough to clear ICANON bit. Here is another version of getch() with timeout support: import tty, sys, termios import select def setup_term(fd, when=termios.TCSAFLUSH): mode = termios.tcgetattr(fd) mode[tty.LFLAG] = mode[tty.LFLAG] & ~(termios.ECHO | termios.ICANON) termios.tcsetattr(fd, when, mode) def getch(timeout=None): fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: setup_term(fd) try: rw, wl, xl = select.select([fd], [], [], timeout) except select.error: return if rw: return sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) if __name__ == "__main__": print getch()