I need to be able to open a document using its default application in Windows and Mac OS. Basically, I want to do the same thing that happens when you double-click on the document icon in Explorer or Finder. What is the best way to do this in Python?
Advertisement
Answer
open and start are command-interpreter things for Mac OS/X and Windows respectively, to do this.
To call them from Python, you can either use subprocess module or os.system(). 
Here are considerations on which package to use:
- You can call them via - os.system, which works, but…- Escaping: - os.systemonly works with filenames that don’t have any spaces or other shell metacharacters in the pathname (e.g.- A:abcdefa.txt), or else these need to be escaped. There is- shlex.quotefor Unix-like systems, but nothing really standard for Windows. Maybe see also python, windows : parsing command lines with shlex- MacOS/X: os.system("open " + shlex.quote(filename))
- Windows: os.system("start " + filename)where properly speakingfilenameshould be escaped, too.
 
- MacOS/X: 
- You can also call them via - subprocessmodule, but…- For Python 2.7 and newer, simply use - subprocess.check_call(['open', filename]) - In Python 3.5+ you can equivalently use the slightly more complex but also somewhat more versatile - subprocess.run(['open', filename], check=True) - If you need to be compatible all the way back to Python 2.4, you can use - subprocess.call()and implement your own error checking:- try: retcode = subprocess.call("open " + filename, shell=True) if retcode < 0: print >>sys.stderr, "Child was terminated by signal", -retcode else: print >>sys.stderr, "Child returned", retcode except OSError, e: print >>sys.stderr, "Execution failed:", e- Now, what are the advantages of using - subprocess?- Security: In theory, this is more secure, but in fact we’re needing to execute a command line one way or the other; in either environment, we need the environment and services to interpret, get paths, and so forth.  In neither case are we executing arbitrary text, so it doesn’t have an inherent “but you can type 'filename ; rm -rf /'” problem, and if the file name can be corrupted, usingsubprocess.callgives us little additional protection.
- Error handling: It doesn’t actually give us any more error detection, we’re still depending on the retcodein either case; but the behavior to explicitly raise an exception in the case of an error will certainly help you notice if there is a failure (though in some scenarios, a traceback might not at all be more helpful than simply ignoring the error).
- Spawns a (non-blocking) subprocess: We don’t need to wait for the child process, since we’re by problem statement starting a separate process.
 - To the objection “But - subprocessis preferred.” However,- os.system()is not deprecated, and it’s in some sense the simplest tool for this particular job. Conclusion: using- os.system()is therefore also a correct answer.- A marked disadvantage is that the Windows - startcommand requires you to pass in- shell=Truewhich negates most of the benefits of using- subprocess.
- Security: In theory, this is more secure, but in fact we’re needing to execute a command line one way or the other; in either environment, we need the environment and services to interpret, get paths, and so forth.  In neither case are we executing arbitrary text, so it doesn’t have an inherent “but you can type