views:

187

answers:

3

What I'd like to do is something like

 $echo $PATH | python --remain-interactive "x = raw_input().split(':')"
 >>>
 >>> print x
 ['/usr/local/bin', '/usr/bin', '/bin']

I suppose ipython solution would be best. If this isn't achievable, what would be your solution for the situation where I want to process output from various other commands? I've used subprocess before to do it when I was desperate, but it is not ideal.

UPDATE: So this is getting closer to the end result:

 echo $PATH > /tmp/stdout.txt; ipython -i -c 'stdout = open("/tmp/stdout.txt").read()'

Now how can we go about bending this into a form

 echo $PATH | pyout

where pyout is the "magic solution to all my problems". It could be a shell script that writes the piped output and then runs the ipython. Everything done fails for the same reasons bp says.

A: 

Due to the Python axiom of "There should be one - and preferably only one - obvious way to do it" I'm reasonably sure that there won't be a better way to interact with other processes than the subprocess module.

It might help if you could say why something like the following "is not ideal":

>>> process = subprocess.Popen(['cmd', '/c', 'echo %PATH%'], stdout=subprocess.PIPE)
>>> print process.communicate()[0].split(';')

(In your specific example you could use os.environ but I realise that's not really what you're asking.)

Dave Webb
So if I was at the shell command line and wanted to quickly and easily get some output into a working interpreter, do you think this is ideal? Simply put, it doesn't redirect the shell's stdout to a new interactive session. It isn't ideal because it starts the session first and then runs the shell command. I may be able to get a bash function to write a temp file with this and have ipython run it.
vgm64
+1  A: 

In IPython you can do this

x = !echo $$$$PATH

The double escape of $ is a pain though

You could do this I guess

PATH="$PATH"
x = !echo $PATH
x[0].split(":")
gnibbler
A: 

The --remain-interactive switch you are looking for is -i. You also can use the -c switch to specify the command to execute, such as __import__("sys").stdin.read().split(":"). So what you would try is: (do not forget about escaping strings!)

echo $PATH | python -i -c x = __import__(\"sys\").stdin.read().split(\":\")

However, this is all that will be displayed:

>>>

So why doesn't it work? Because you are piping. The python intepreter is trying to interactively read commands from the same sys.stdin you are reading arguments from. Since echo is done executing, sys.stdin is closed and no further input can happen.

For the same reason, something like:

echo $PATH > spam
python -i -c x = __import__(\"sys\").stdin.read().split(\":\") < spam

...will fail.

What I would do is:

echo $PATH > spam.bar
python -i my_app.py spam.bar

After all, open("spam.bar") is a file object just like sys.stdin is :)

badp
Obviously here I'm assuming you do know about `sys.path` and that `echo $PATH` was just some random command you used to illustrate your point.
badp
@bp, sys.path is the path python uses to import modules. It's not the same as $PATH. You are probably thinking of `os.environ["PATH"]`
gnibbler
@bp, a nod to your comment. About your answer, I don't want to have to write a my_app to parse the output. Putting, for example, the .split(':') in its own file would be annoying. That -i switch will be handy in its own right; I thought I misunderstood it because it wasn't working (much like your first example shows).
vgm64