Jeenu
Jeenu

Reputation: 2231

Page current stdout to less, in Python

I've a snippet like this:

my_string = "foo bar"
def print_string(fd=sys.stdout):
    print(my_string, file=fd)

How do I get to pipe the output of print_string to a pager, say, less?

I'm aware of using subprocess.Popen with stdin=PIPE, and then using proc.communicate(), but then I can only write my_string directly, not redirect from an existing descriptor.

Although a bit silly, but I tried the below; I'm not surprised that it doesn't work:

proc = subprocess.Popen("less -".split(), stdin=sys.stdout)
print_string()
proc.wait()

Git commands seems to do the same thing, effectively: pipes its output through a pager; and I was trying to achieve a similar effect.

Upvotes: 2

Views: 996

Answers (1)

syntonym
syntonym

Reputation: 7384

Less needs to read from the "real" stdin to get key presses, otherwise it can't react to user input. Instead you can create a temporary file and let less read that:

import subprocess
import tempfile

with tempfile.NamedTemporaryFile("w") as f:
    f.write("hello world!")
    f.flush() // flush or otherwise the content 
              // might not be written when less tries to read
    p = subprocess.Popen(["/usr/bin/less", f.name])
    p.wait()

This might have security consequences, best to read the documentation on tempfile before using it on something super secure.

I'm also not sure how git does it or if there is a better way, but it worked in my short tests.

Upvotes: 2

Related Questions