In xonsh how can I receive from a pipe to a python expression?

Question:

In the xonsh shell how can I receive from a pipe to a python expression? Example with a find command as pipe provider:

find $WORKON_HOME -name pyvenv.cfg -print | for p in <stdin>: $(ls -dl @(p))

The for p in <stdin>: is obviously pseudo code. What do I have to replace it with?

Note: In bash I would use a construct like this:

... | while read p; do ... done
Asked By: halloleo

||

Answers:

The easiest way to pipe input into a Python expression is to use a function that is a callable alias, which happens to accept a stdin file-like object. For example,

def func(args, stdin=None):
    for line in stdin:
        ls -dl @(line.strip())

find $WORKON_HOME -name pyvenv.cfg -print | @(func)

Of course you could skip the @(func) by putting func in aliases,

aliases['myls'] = func
find $WORKON_HOME -name pyvenv.cfg -print | myls

Or if all you wanted to do was iterate over the output of find, you don’t even need to pipe.

for line in !(find $WORKON_HOME -name pyvenv.cfg -print):
    ls -dl @(line.strip())
Answered By: Anthony Scopatz

Drawing on the answer from Anthony Scopatz you can do this on one line with a callable alias as a lambda. The function takes the third form, def mycmd2(args, stdin=None). I discarded args with _ because I don’t need it and shortened stdin to s for convenience. Here is a command to hash a file:

type image.qcow2 | @(lambda _,s: hashlib.sha256(s.read()).hexdigest())
Answered By: Stephen Nichols
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.