Home > Net >  Complexe macOS command with suprocess Popen - Python
Complexe macOS command with suprocess Popen - Python

Time:11-12

I want to call this terminal command on macOS in python lsappinfo info -only name lsappinfo front. It returns the name of the current foreground application.

Here is how I understand the command:

  • lsappinfo return information about running apps

  • info allows to select specific data

  • lsappinfo front select the foreground process

  • name select the name of the process only

And here is my current code:

import subprocess

sub = subprocess.Popen(['lsappinfo', 'info', '-only', 'name', '`lsappinfo front`'])
out, err = sub.communicate()
print(err)
print(out)

But I get:

>>> None
>>> None

The expected output of the command is

"LSDisplayName"="AppName"

I succeed using os.system() but I want to achieve it with subprocess since it's the recommended way and I want to store the output. Does someone know how to do it?

CodePudding user response:

did you check if is needed any special permission?

what is the output if you write your command in a .sh file, and then execute the command as ["./{myscript}.sh"] or so (remember to add x perms)?

CodePudding user response:

this works:

cmd1 = ['lsappinfo', 'front']
name = subprocess.run(cmd1, shell=False, capture_output=True).stdout.decode('utf-8').strip("\n")
cmd2 = ['lsappinfo', 'info', '-only', "name", name]
out2 = subprocess.run(cmd2, shell=False, capture_output=True)
print(out2.stdout.decode('utf-8').strip("\n"))

subprocess has issues with bash evals (the backticks). Same with grep. You need to do it in 2 steps in your python code. Bit of a workaround but it works.

Output:

$ python test.py  
"LSDisplayName"="Code"

(Edit: added the strip for the \n at the end.) Use this in a function and you're good to go. Note: It returns "Code" for me since I ran it in VSCode, which was in the foreground at that moment.

CodePudding user response:

The command you actually want to run is:

lsappinfo info -only name $(lsappinfo front)

which calls lsappinfo front to get the ASN of the front process and then passes the result to a second call to lsappinfo to get the name of that process.

The key issue here is that the shell calls the two processes for you, so you would have to use the shell in your Python subprocess call to do the same... or you would have to do a second subprocess call per @Remzinho.

The single step method is:

import subprocess as sp

res = sp.run('lsappinfo info -only name $(lsappinfo front)', shell=True)

Note that backticks are deprecated and $(...) should be preferred. The latter, newer method is also nestable.

lsappinfo info -only name `lsappinfo front`    # worse
lsappinfo info -only name $(lsappinfo front)   # better

CodePudding user response:

do it with zsh directly better !

  • Related