1

I have encountered a problem with my python script. I am using python 3. I am using the os.system function to open an app on my mac. What I would like to do is have the computer print "done" when it has finished opening. The problem is the script prints "done" before the app is even done loading. The app starts launching but the script prints "done" before the app is completely done launching. This is my script:

import os

os.system('open "/Applications/Pages.app"')
print("done.")

Plz help

Thanks in advance

3 Answers3

0

The code is actually working as it should. It might work to think of the open command as something that kick-starts the opening process -- like starting the starter motor on your car. Open will tell your app to open and then it returns, telling you whether or not it has managed to get the ball rolling. Meanwhile, the app that you've opened will go through its own initialisation process until it has fully started up.

I'm not sure how you can tell when your program has fully started up short of just setting a timer for an arbitrary number of seconds. You might be able to make an educated guess by looking at the list of processes on your computer?

0

open is a command, that runs the application as a separate task. If you wanted to wait for the completion, you'd have to directly run the executable inside the app (.app is just a suffix for directories).

But as you don't want to do that: The app itself handles all the loading, MacOS is (probably, I have actually no idea whatsoever about how operating systems work) just copying all the bits and bytes from that executable file into RAM; and then the scheduler from the operating system runs it.

Some applications open a window directly, but not all do. The calls to do that are running through some libraries sometimes, and it generally takes a while. So trying to measure the time it takes to open a window doesn't work either (and applications may initialize other things as well; and measuring time for such tasks isn't a great way to deal with such problems anyway).

The solution is the following: You want to resume if a window by that program is opened, right? If you know the name of the process, it is pretty easy:

import os
import subprocess

devnull = open(os.devnull, 'w')
script = """
tell application "System Events"
  set frontApp to first application process whose name is "{}" and frontmost is true
end tell
"""

...

while subprocess.check_call(["osascript", "-e", script.format("name_of_the_process")], stdout=devnull, stderr=devnull) != 0:
    pass

osascript runs AppleScript "applications", in this case an application that tries to get the process with the name you provided that has to have a window that is on top. This is the name of the directory without the trailing ".app", I'd guess. This doesn't work if this app isn't opened, leaving us with a non-zero exit code (-1719 in this case), while it doesn't have any problems if the app is opened. The variable is set, and the script exits, leaving us with a 0 as an exit code.

If you only want to wait for the process to appear, remove the and frontmost is true from the AppleScript code in the script variable.

My code works as expected on my Mac, but it does print to stdout.

CodenameLambda
  • 1,486
  • 11
  • 23
0

If you really want the behavior you described, I suggest you to look in direction of UI Automation and OS X Accessibility. For example - an atomac python package that could help you to wait until it is loaded.

1) What you need to determine the "symptoms" of completed loading that can be accessed via UI automation.

2) Wait until the "symptoms" appear.

3) You are done.

Mikhail Churbanov
  • 4,436
  • 1
  • 28
  • 36