0

I am programming a Ros interface in python, and I would like to be able to select the node I want to run from a list showing all available nodes once I choose a package.

In other words I would like to create the list of all nodes contained in a package getting the output I would have in the terminal if I type:

rosrun <package-name> \t\t

In terms of python code, a wrong example of what I am trying to do could be:

from subprocess import Popen, PIPE

p = Popen (["rosrun", "<package-name>", "\t\t"], stdout = PIPE, stderr = PIPE)
out, err = p.communicate ()
print (out.decode ("ascii"))
print (err.decode ("ascii"))

But this does not work because "\t\t" is not processed in Popen like it is in the terminal.

Is there any way to get this working or is it impossible to emulate the double-tab completion of the terminal from inside a python script?

Is Popen to be used in a different way to do this or should I totally change the code using other facilities?

Please help me :)

  • I'm not sure the right way to do this, but I'm not surprised this approach doesn't work. In this example you are running a process `rosrun` directly, and asking it to do the tab completion, but normally it is the shell that does the tab completion before invoking the program. Perhaps if you try running that with `shell=True`. . . but I'm not super confident of that. – Eric Renouf Sep 02 '16 at 01:09
  • Yes I wrote that example only to explain what I need. No, `shell=True` does not solve, I had already tried... I read something about **pty** but I don't even know what it is. – Lorenzo Sciarra Sep 02 '16 at 12:22
  • Check out this question that might do a lot of what you want: http://stackoverflow.com/q/9137245/4687135 – Eric Renouf Sep 02 '16 at 12:26

1 Answers1

0

Finally I solved this by myself, I went right throw Ros own code and found out how it generates the bash completion output.

My code now is like this:

from subprocess import Popen, PIPE
package = "<package>"
comm = str("catkin_find --first-only --without-underlays --libexec " + package).split ()
out, err = Popen (comm, stdout = PIPE, stderr = PIPE).communicate ()
out = out.decode ("ascii")
if (out.strip () == ""):
    return
comm = "find -L " + out.strip () + " -type f -exec basename {} ';'"
out, err = Popen (comm, shell = True, stdout = PIPE, stderr = PIPE).communicate ()
out = out.decode ("ascii")
print (out.strip ())

I simplified Ros code, it was originally more complicated, but this version does what I need for now.

I hope it can be useful also for others.

Thanks for the advices :)