urwid
Console user interface library for Python (official repo)
Overview — Urwid 1.3.0
I'm currently rewriting a perl console application that was using curses, and planning to implement it in Python. So far I've narrowed my library options to straight curses, urwid, and dialog.
The application is basically an installer for an appliance that will accommodate basic configuration (network options, hostname, etc). Are there any suggestions or advocates for one of these over the other? Any serious limitations with urwid or dialog?
Source: (StackOverflow)
While Python's standard library has a module for curses, that seems to require a lot of fairly low-level handling.
Is there a simpler way to get started with writing a basic curses UI which includes standard elements like checkboxes, input fields etc.?
I've found urwid, but not sure whether that's the state of the art.
Source: (StackOverflow)
What's the difference between these 3? As far as I understand it they both provide binding to curses which is the C library for terminal text-based UI.
I currently have no knowledge of any of the 3 and I've never used curses. Which one would you recommend? I've heard of ncurses many times but only once or twice about CDK (through research) and never heard of urwid (I think).
Source: (StackOverflow)
I wrote the following code that creates a layout and displays some text in the layout. Next the layout is displayed on the console screen using raw display module from urwid library.
However running the code fails as it doesn't find the function main that I wrote separately in a class.
Error code on running is :
Traceback (most recent call last):
File "./yamlUrwidUIPhase5.py", line 89, in <module>
main()
File "./yamlUrwidUIPhase5.py", line 83, in main
FormDisplay().main()
AttributeError: 'NoneType' object has no attribute 'main'
The code :
import sys
sys.path.append('./lib')
import os
from pprint import pprint
import random
import urwid
def formLayout():
text1 = urwid.Text("Urwid 3DS Application program - F8 exits.")
text2 = urwid.Text("One mission accomplished")
textH = urwid.Text("topmost Pile text")
cols = urwid.Columns([text1,text2])
pile = urwid.Pile([textH,cols])
fill = urwid.Filler(pile)
textT = urwid.Text("Display")
textSH = urwid.Text("Pile text in Frame")
textF = urwid.Text("Good progress !")
frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
dim = ui.get_cols_rows()
ui.draw_screen(dim, frame.render(dim, True))
def RandomColor():
'''Pick a random color for the main menu text'''
listOfColors = ['dark red', 'dark green', 'brown', 'dark blue',
'dark magenta', 'dark cyan', 'light gray',
'dark gray', 'light red', 'light green', 'yellow',
'light blue', 'light magenta', 'light cyan', 'default']
color = listOfColors[random.randint(0, 14)]
return color
def FormDisplay():
import urwid.raw_display
ui = urwid.raw_display.Screen()
palette = ui.register_palette([
('Field', 'dark green, bold', 'black'), # information fields, Search: etc.
('Info', 'dark green', 'black'), # information in fields
('Bg', 'black', 'black'), # screen background
('InfoFooterText', 'white', 'dark blue'), # footer text
('InfoFooterHotkey', 'dark cyan, bold', 'dark blue'), # hotkeys in footer text
('InfoFooter', 'black', 'dark blue'), # footer background
('InfoHeaderText', 'white, bold', 'dark blue'), # header text
('InfoHeader', 'black', 'dark blue'), # header background
('BigText', RandomColor(), 'black'), # main menu banner text
('GeneralInfo', 'brown', 'black'), # main menu text
('LastModifiedField', 'dark cyan, bold', 'black'), # Last modified:
('LastModifiedDate', 'dark cyan', 'black'), # info in Last modified:
('PopupMessageText', 'black', 'dark cyan'), # popup message text
('PopupMessageBg', 'black', 'dark cyan'), # popup message background
('SearchBoxHeaderText', 'light gray, bold', 'dark cyan'), # field names in the search box
('SearchBoxHeaderBg', 'black', 'dark cyan'), # field name background in the search box
('OnFocusBg', 'white', 'dark magenta') # background when a widget is focused
])
urwid.set_encoding('utf8')
def main(self):
#self.view = ui.run_wrapper(formLayout)
self.view = formLayout()
ui.start()
self.loop = urwid.MainLoop(self.view, self.palette, unhandled_input=self.unhandled_input)
self.loop.run()
def unhandled_input(self, key):
if key == 'f8':
quit()
return
def main():
global ui
FormDisplay().main()
########################################
##### MAIN ENTRY POINT
########################################
if __name__ == '__main__':
main()
Source: (StackOverflow)
I'm looking at urwid to develop a console app. As a starting point I'm looking for a simple example of a listbox that displays a few rows that can be scrolled using up/down keys.
Can anyone provide a simple example of how this can be done or point me to a link? I saw the examples on urwid site but I'm looking for something more basic.
Edit
@Adam: I found this example online. I'm having difficulties with the commented out part as I'm not familiar with the API and I'm a python newbie.
Edit2
I figured it out and updated the example.
One more question - can I get the item count directly from the ListBox?
import urwid
palette = [('header', 'white', 'black'),
('reveal focus', 'black', 'dark cyan', 'standout')]
items = [urwid.Text("foo"),
urwid.Text("bar"),
urwid.Text("baz")]
content = urwid.SimpleListWalker([
urwid.AttrMap(w, None, 'reveal focus') for w in items])
listbox = urwid.ListBox(content)
show_key = urwid.Text("Press any key", wrap='clip')
head = urwid.AttrMap(show_key, 'header')
top = urwid.Frame(listbox, head)
def show_all_input(input, raw):
show_key.set_text("Pressed: " + " ".join([
unicode(i) for i in input]))
return input
def exit_on_cr(input):
if input in ('q', 'Q'):
raise urwid.ExitMainLoop()
elif input == 'up':
focus_widget, idx = listbox.get_focus()
if idx > 0:
idx = idx-1
listbox.set_focus(idx)
elif input == 'down':
focus_widget, idx = listbox.get_focus()
idx = idx+1
listbox.set_focus(idx)
def out(s):
show_key.set_text(str(s))
loop = urwid.MainLoop(top, palette,
input_filter=show_all_input, unhandled_input=exit_on_cr)
loop.run()
Source: (StackOverflow)
i was looking at a file wicd-curses.py from the wicd application available with urwid. there is a function named as wrap_exceptions and then at several other places in the file i find some code like this @wrap_exceptions which occurs just before several other functions. What does it mean ?
Source: (StackOverflow)
I am creating a small urwid
app for my use, the structure is a Filler
which has a Pile
composed of several Text
filed, followed by a Divider
, an Edit
, another Divier
and finally a Text
:
Text1
Text2
Text3
Divide
>> Edit
Divide
Textout
Now, I want to replace Text1 .. Text3
with other Text
field, the exact number of those varies. I figure I should redraw the entire UI, but I got no response on draw_screen()
My class:
class main_ui(urwid.Filler):
def __init__(self):
self.body = welcom()
self.options = self.body.options
self.replay = self.body.replay
self.ask = self.body.ask
super(main_ui,self).__init__(self.body.pile,valign='top')
def paint(self):
super(main_ii,self).__init__(urwid.pile[urwid.Text('test')])
The welcom()
function generates the above fields, and options
is dict
that holds information I need
I run the loop like this
def refresh(_loop,_data):
m.new_point()
_loop.draw_screen()
_loop.set_alarm_in(2,refresh)
m = main_ui()
loop = urwid.MainLoop(m)
loop.set_alarm_in(2,refresh)
loop.run()
How can I update my ui?
Source: (StackOverflow)
I am quite new to python an urwid. I found a seemingly OS X specific problem with urwid 1.3.0:
I run Mac OS X 10.9.5 an have the by default installed python 2.7.5 and a manually installed python 3.4.2.
I have made no changes to the original code an tried the following:
I copied as instructed (https://github.com/wardi/urwid/wiki/Installation-instructions) the urwid folder from the package (urwid-1.3.0.tar.gz) into its examples folder to make urwid available for python and being able to test the examples. I got always the same error when executing e.g:
python bigtext.py
python3 bigtext.py
I also tried this with the very first tutorial from the urwid site
# hellotest.py
import urwid
txt = urwid.Text(u"Hello World")
fill = urwid.Filler(txt, 'top')
loop = urwid.MainLoop(fill)
loop.run()
All examples, just like the short one above, produce the following Error:
mymac:examples me$ python3 hellotest.py
Traceback (most recent call last):
File "hellotest.py", line 1, in <module>
import urwid
File "myfolder/urwid-1.3.0/examples/urwid/__init__.py", line 36, in <module>
from urwid.wimp import (SelectableIcon, CheckBoxError, CheckBox, RadioButton,
File "myfolder/urwid-1.3.0/examples/urwid/wimp.py", line 99, in <module>
class CheckBox(WidgetWrap):
File "myfolder/urwid-1.3.0/examples/urwid/wimp.py", line 104, in CheckBox
True: SelectableIcon("[X]"),
File "myfolder/urwid-1.3.0/examples/urwid/wimp.py", line 47, in __init__
self.__super.__init__(text)
AttributeError: 'SelectableIcon' object has no attribute '_SelectableIcon__super'
This Error does not occur when i try this on a fresh Raspbian (Debian) on a Raspberry Pi.
So it seems to me this is a OS specific problem.
Can someone find why this behaviour occurs on OS X, or does it even happen on other systems too? And does someone have an idea on how to fix this?
Thanks in advance
Source: (StackOverflow)
code below creates a layout and displays some text in the layout. Next the layout is displayed on the console screen using raw display module from urwid library. (More info on my complete project can be gleaned from questions at widget advice for a console project and urwid for a console project. My skype help request being here.) However running the code fails as an Assertion Error is raised as described below :
Error on running code is :
Traceback (most recent call last):
File "./yamlUrwidUIPhase6.py", line 98, in <module>
main()
File "./yamlUrwidUIPhase6.py", line 92, in main
form.main()
File "./yamlUrwidUIPhase6.py", line 48, in main
self.view = formLayout()
File "./yamlUrwidUIPhase6.py", line 77, in formLayout
ui.draw_screen(dim, frame.render(dim, True))
File "/usr/lib64/python2.7/site-packages/urwid/raw_display.py", line 535, in draw_screen
assert self._started
AssertionError
The code :
import sys
sys.path.append('./lib')
import os
from pprint import pprint
import random
import urwid
ui=urwid.raw_display.Screen()
class FormDisplay(object):
def __init__(self):
global ui
self.ui = ui
palette = ui.register_palette([
('Field', 'dark green, bold', 'black'), # information fields, Search: etc.
('Info', 'dark green', 'black'), # information in fields
('Bg', 'black', 'black'), # screen background
('InfoFooterText', 'white', 'dark blue'), # footer text
('InfoFooterHotkey', 'dark cyan, bold', 'dark blue'), # hotkeys in footer text
('InfoFooter', 'black', 'dark blue'), # footer background
('InfoHeaderText', 'white, bold', 'dark blue'), # header text
('InfoHeader', 'black', 'dark blue'), # header background
('BigText', RandomColor(), 'black'), # main menu banner text
('GeneralInfo', 'brown', 'black'), # main menu text
('LastModifiedField', 'dark cyan, bold', 'black'), # Last modified:
('LastModifiedDate', 'dark cyan', 'black'), # info in Last modified:
('PopupMessageText', 'black', 'dark cyan'), # popup message text
('PopupMessageBg', 'black', 'dark cyan'), # popup message background
('SearchBoxHeaderText', 'light gray, bold', 'dark cyan'), # field names in the search box
('SearchBoxHeaderBg', 'black', 'dark cyan'), # field name background in the search box
('OnFocusBg', 'white', 'dark magenta') # background when a widget is focused
])
urwid.set_encoding('utf8')
def main(self):
global ui
#self.view = ui.run_wrapper(formLayout)
self.view = formLayout()
self.ui.start()
self.loop = urwid.MainLoop(self.view, self.palette, unhandled_input=self.unhandled_input)
self.loop.run()
def unhandled_input(self, key):
if key == 'f8':
quit()
return
def formLayout():
global ui
text1 = urwid.Text("Urwid 3DS Application program - F8 exits.")
text2 = urwid.Text("One mission accomplished")
textH = urwid.Text("topmost Pile text")
cols = urwid.Columns([text1,text2])
pile = urwid.Pile([textH,cols])
fill = urwid.Filler(pile)
textT = urwid.Text("Display")
textSH = urwid.Text("Pile text in Frame")
textF = urwid.Text("Good progress !")
frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
dim = ui.get_cols_rows()
ui.draw_screen(dim, frame.render(dim, True))
return
def RandomColor():
'''Pick a random color for the main menu text'''
listOfColors = ['dark red', 'dark green', 'brown', 'dark blue',
'dark magenta', 'dark cyan', 'light gray',
'dark gray', 'light red', 'light green', 'yellow',
'light blue', 'light magenta', 'light cyan', 'default']
color = listOfColors[random.randint(0, 14)]
return color
def main():
form = FormDisplay()
form.main()
########################################
##### MAIN ENTRY POINT
########################################
if __name__ == '__main__':
main()
I don't want to change the function formLayout as I intend to add more to this basic code framework, where in another function will be added that repeatedly calls formLayout to keep updating the screen based on reading values from a yml file. I already have a separate code that deals with reading the yaml file and extracting ordered dictionaries out it. After figuring out how to get basic urwid console working, I can move on to integrating both to create my final application.
Source: (StackOverflow)
I need to build a python TUI for a project that I am working on. I do not need advice suggestion about the actual TUI libraries out there (like ncurses/npyscreen/Urwid/etc) as my team has already determined that they are too heavyweight for our needs. The TUI takes relatively simple text input and doesn't require all of the nice formatting and widgets. It also will only be accepting input from a single user at any time.
Since we are rolling our own display, that leaves the real question, which is are there options for libs out there that can help implement the event-handling/IO loop that I can reuse? I started the Internet search for GUI/TUI backends and quickly found myself in the Twisted/Tornado/Gevent world, which I am also not sure is the proper avenue to run down. Are these libraries, or possibly Urwid able to let me easy slip in my own display code (to render screens and take simple raw_input()
style data)?
This will only be run in a Python 2.7, Linux environment, but if it works on a Mac, that will be a big plus.
Source: (StackOverflow)
I'm trying to write a script that just uses the terminal, but I don't know how realistic my expectations are. It's a data entry thing I want to make to make my life easier. I would like something that looks like this:
100456 John Doe [] () () () () [ ]
100873 Alice Everly [] () () () () [ ]
...
...
Basically a screen with a list of 20-30 people with text entry boxes and check boxes. I want to be able to arrow up and down and move around. I remember using text based programs way back when and they still just seem more efficient.
I've been looking at ncurses, urwid, straight bash... I think I can get any of these to work, but if anyone has a suggestion on a language or framework that would make this easier, I'd sure appreciate it. I don't want to get a week or two in and then realize I could have done it another way in an hour.
Source: (StackOverflow)
I'm trying to raise an exception within an except:
block but the interpreter tries to be helpful and prints stack traces 'by force'. Is it possible to avoid this?
A little bit of background information:
I'm toying with urwid, a TUI library for python. The user interface is started by calling urwid.MainLoop.run()
and ended by raising urwid.ExitMainLoop()
. So far this works fine but what happens when another exception is raised? E.g. when I'm catching KeyboardInterrupt
(the urwid MainLoop does not), I do some cleanup and want to end the user interface - by raising the appropriate exception. But this results in a screen full of stack traces.
Some little research showed python3 remembers chained exceptions and one can explicitly raise an exception with a 'cause': raise B() from A()
. I learned a few ways to change or append data regarding the raised exceptions but I found no way to 'disable' this feature. I'd like to avoid the printing of stack traces and lines like The above exception was the direct cause of...
and just raise the interface-ending exception within an except:
block like I would outside of one.
Is this possible or am I doing something fundamentally wrong?
Edit:
Here's an example resembling my current architecture, resulting in the same problem:
#!/usr/bin/env python3
import time
class Exit_Main_Loop(Exception):
pass
# UI main loop
def main_loop():
try:
while True:
time.sleep(0.1)
except Exit_Main_Loop as e:
print('Exit_Main_Loop')
# do some UI-related clean up
# my main script
try:
main_loop()
except KeyboardInterrupt as e:
print('KeyboardInterrupt')
# do some clean up
raise Exit_Main_Loop() # signal the UI to terminate
Unfortunately I can't change main_loop
to except KeyboardInterrupt
as well. Is there a pattern to solve this?
Source: (StackOverflow)
import urwid
palette = [('header', 'white', 'black'),
('reveal focus', 'black', 'dark cyan', 'standout'),]
content = urwid.SimpleListWalker([
urwid.AttrMap(w, None, 'reveal focus') for w in [
urwid.Text("This is a text string that is fairly long"),
urwid.Divider("-"),
urwid.Text("Short one"),
urwid.Text("Another"),
urwid.Divider("-"),
urwid.Text("What could be after this?"),
urwid.Text("The end."),]
])
listbox = urwid.ListBox(content)
show_key = urwid.Text("", wrap='clip')
head = urwid.AttrMap(show_key, 'header')
top = urwid.Frame(listbox, head)
def show_all_input(input, raw):
show_key.set_text("Pressed: " + " ".join([
unicode(i) for i in input]))
return input
def exit_on_cr(input):
if input == 'enter':
raise urwid.ExitMainLoop()
loop = urwid.MainLoop(top, palette, input_filter=show_all_input, unhandled_input=exit_on_cr)
loop.run()
Pressing up or down should scroll the list but in my case it doesn't. Is there something wrong ?
EDIT 1
Code works perfectly in fact I didn't understand what scrollable lists are. I thought pressing up or down would select item in the list but it doesn't. What this does is just scroll your terminal when it doesn't have enough space to display all items at once. You must resize your terminal to a very small size to understand what this code does.
EDIT 2
To change focus when pressing up or down, a strange API has to be used. I would have loved to see an API like listbox.focus_next()
/ listbox.focus_previous()
, but you have to handle the positions yourself. Of course, you can create your own functions (or subclass ListBox) to offer a better API
def handle_input(input):
if input == "esc":
raise urwid.ExitMainLoop()
head.original_widget.set_text("key pressed: %s" % input)
lw = listbox.body
if input == "up":
# this can raise an error if we scroll past first position
try:
lw.set_focus(lw.get_prev(lw.get_focus()[1])[1])
except:
pass
elif input == "down":
# this can raise an error if we scroll past last position
try:
lw.set_focus(lw.get_next(lw.get_focus()[1])[1])
except:
pass
EDIT 3
A better API :
def urwid_test():
"""
'black', 'dark red', 'dark green', 'brown', 'dark blue',
'dark magenta', 'dark cyan', 'light gray', 'dark gray',
'light red', 'light green', 'yellow', 'light blue',
'light magenta', 'light cyan', 'white'
"""
class MyListBox(urwid.ListBox):
def focus_next(self):
try:
self.body.set_focus(self.body.get_next(self.body.get_focus()[1])[1])
except:
pass
def focus_previous(self):
try:
self.body.set_focus(self.body.get_prev(self.body.get_focus()[1])[1])
except:
pass
def handle_input(input):
if input == "esc":
raise urwid.ExitMainLoop()
head.original_widget.set_text("key pressed: %s" % input)
if input == "up":
listbox.focus_previous()
elif input == "down":
listbox.focus_next()
palette = [("top","white","black"),
("line","light green","dark green","standout"),
("frame","dark magenta","white"),
]
widgets = [urwid.AttrMap(widget,None,"line") for widget in
[
urwid.Text("Chemma!"),
urwid.Divider("-"),
urwid.Text("Another text widget!"),
urwid.Divider("-"),
urwid.Text("What is your name"),
urwid.Divider("-"),
urwid.Text("Boy ?"),
]
]
head = urwid.AttrMap(urwid.Text("key pressed :",wrap="clip"),"top")
L = urwid.SimpleListWalker(widgets)
listbox = MyListBox(L)
top = urwid.AttrMap(urwid.Frame(listbox,head),"frame")
loop = urwid.MainLoop(top,palette,unhandled_input=handle_input)
loop.screen.set_terminal_properties(colors=256)
loop.run()
if __name__ == "__main__":
urwid_test()
Source: (StackOverflow)
I am using urwid to design a curses ui. I can use display attributes to show text bold, underlined, or standout. Is it possible to use italics?
Source: (StackOverflow)