anothernode
anothernode

Reputation: 5397

Python script using curses fails on macOS

I'm trying to run the nettop.py script from the psutil repository using Python 3.6.4. It's primarily meant to demonstrate the usage of Python's psutil module.

It's working fine on Ubuntu, but running it on macOS fails with the following error:

Traceback (most recent call last):
  File "nettop.py", line 167, in <module>
    main()
  File "nettop.py", line 160, in main
    refresh_window(*args)
  File "nettop.py", line 138, in refresh_window
    stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
  File "nettop.py", line 67, in print_line
    win.addstr(lineno, 0, line, 0)
_curses.error: addwstr() returned ERR

That win object in the last line of the Traceback is defined in nettop.py:53 and comes from the curses module:

win = curses.initscr()

I have no idea where that addwstr() function comes from.

Can someone shed some light on this? Any ideas on how I could get this to run on macOS?

Upvotes: 1

Views: 2232

Answers (1)

Thomas Dickey
Thomas Dickey

Reputation: 54505

The screensize is probably relevant, since it's assuming that a full set of messages will be written before it resets the lineno variable to zero at the end of the loop.

The print_line function aggravates that by raising an exception rather than checking for the conditions which would cause the curses addstr to return an error:

  • line too line
  • line past the end of the screen

For example, here's a (crude) workaround for that:

diff --git a/scripts/nettop.py b/scripts/nettop.py
index e13903c1..d263eb99 100755
--- a/scripts/nettop.py
+++ b/scripts/nettop.py
@@ -59,9 +59,11 @@ lineno = 0
 def print_line(line, highlight=False):
     """A thin wrapper around curses's addstr()."""
     global lineno
+    if lineno >= win.getmaxyx()[0]:
+        lineno = win.getmaxyx()[0] - 1
     try:
         if highlight:
-            line += " " * (win.getmaxyx()[1] - len(line))
+            line += " " * (win.getmaxyx()[1] - len(line) - 1)
             win.addstr(lineno, 0, line, curses.A_REVERSE)
         else:
             win.addstr(lineno, 0, line, 0)

which doesn't go very deep (since the script also assumes the screen is always wide enough).

Whether it calls addstr or addwstr underneath does not matter much, since both make the same sort of checks.

Upvotes: 3

Related Questions