On 2010-07-14, Steven W. Orr <ste...@syslang.net> wrote: > On 07/12/10 21:29, quoth Kenny Meyer: > >> I have to figure out if a string is callable on a Linux system. I'm >> actually doing this: >> >> def is_valid_command(command): >> retcode = 100 # initialize >> if command: >> retcode = subprocess.call(command, shell=True) >> if retcode is 0: >> print "Valid command." >> else: >> print "Looks not so good..." >> >> is_valid_command("ls") >> >> Never mind the code, because this is not the original. The side >> effect of subprocess.call() is that it *actually* executes it, but I >> just need the return code. What are better ways of doing this? > > Luke! Use the force! > > #! /usr/bin/python > > import os > def is_valid_command(command): > looking_good = False > for ii in os.environ['PATH'].split(':'): > if os.access(ii + '/' + command, os.X_OK): > looking_good = True > break > print ["Looks not so good...", "Valid command."][looking_good] > > is_valid_command('python') > is_valid_command('pythoon')
Just to be clear, that's not the same as the OP's code in two respects: 1) It doesn't handle shell builtins or aliases. 2) It determines not whether a command is valid (returns 0), but whether a command exists as an executable. "Valid" is a rather small subset of "exists". Of course the OP didn't explain what he meant by "callable", so all we have to go on is his posted code. > This way you don't start up any subprocesses and you are actually > doing what the shell would do for you. > > THE ONLY DIFFERENCE is that a persistent bash would hash all of the > contents of what lives in PATH and so might have a slight shot of > being faster under somewhat obscure conditions. No, there are other differences. See above. > I would strongly encourage you to not execute an arbitrary string to > see if it returns a pretty return code. > > is_valid_command('{cd /; rm -rf /}') > > Warning: > * It only checks if the command exists in PATH and is executable TO > YOU: Which is different than determining whether a command (including arguments) is valid (callable and returns 0). However, running a command to determine if it's valid is going to cause problems sooner or later due to side-effects of that command. For example, the first time you the command "rm /path/to/a/file" it may be valid, but the second time it won't be. > * Do not make fun of is_valid_command. It will get angry. And don't taunt happy fun ball! > * You might also want to beef it up a la > pp = ii + '/' + command > if os.access(pp, (os.X_OK) and not os.stat.isdir(p)): > so you are checking executable files and not directories etc... > * More warnings can be amplified upon over pitchers of beer. -- Grant Edwards grant.b.edwards Yow! My mind is making at ashtrays in Dayton ... gmail.com -- http://mail.python.org/mailman/listinfo/python-list