5

I'm trying to determine if the operating system is Unix-based from a Python script. I can think of two ways to do this but both of them have disadvantages:

  • Check if platform.system() is in a tuple such as ("Linux", "Darwin"). The problem with this is that I don't want to provide a list of every Unix-like system every made, in particular there are many *BSD varieties.
  • Check if the function os.fchmod exists, as this function is only available on Unix. This doesn't seem like a clean or "Pythonic" way to do it.
user2722730
  • 53
  • 1
  • 3
  • 5
    [EAFP](http://docs.python.org/2/glossary.html) - Just let your script do whatever it does. It will presumably fail on Windows; just make certain that it fails the way you want it to. – Robᵩ Aug 27 '13 at 18:34
  • 1
    Check if `os.name == 'posix'`? – Wooble Aug 27 '13 at 18:35
  • How about checking if it doesnt contain "Windows"? – shahkalpesh Aug 27 '13 at 18:36
  • 3
    [This question](http://stackoverflow.com/questions/1854/python-what-os-am-i-running-on) may help others too. – squiguy Aug 27 '13 at 18:38
  • 1
    @rob I'd like my code to run on both Windows and Unix, so I don't want it to fail on Windows. To do platform-dependent things, I need to know what operating system Python is running on. – user2722730 Aug 27 '13 at 19:07
  • @wooble This seems like it could work. – user2722730 Aug 27 '13 at 19:08
  • @Robᵩ I think treating a certain OS as an "exceptional" case would be wasteful. I mean, if you use "try: [linux thing] except: [windows thing]", it will *always* run slower on Windows. It would be desirable to somehow cache which method was successful so that it can be used from then on (I think we can safely assume the OS will never change during the execution of the script). – nmclean Aug 27 '13 at 19:20
  • @nmclean Right, that is what you should do. Create an abstraction, and N implementations (one per platform). Once you know which platform you are on, select the particular abstraction and then always use that one. – cdhowie Aug 27 '13 at 21:38

2 Answers2

7
import sys
if 'win' in sys.platform():
    #windows
else:
    #not windows

or, you can try importing a platform dependent library

try:
    import windows_only as generic
except ImportException:
    try:
          import unix_only as generic
    except ImportException:
          import stdlib.module as generic

 print generic.common_function()

and then there's the always reliable

>>> import os
>>> os.name
nt
blakev
  • 4,154
  • 2
  • 32
  • 52
  • Note that `os.name` is probably the granularity the OP wants -- `"posix"` for Unix-like systems, `"nt"` for Windows. The docs say that 'posix', 'nt', 'os2', 'ce', 'java', and 'riscos' are in use. – Russell Borogove Aug 27 '13 at 23:10
  • 1
    `if 'win' in sys.platform()` will trigger for 'darwin', which is not the desired behavior (since Darwin is a Unix-based platform if I'm not mistaken). – Galactic Ketchup Sep 01 '22 at 19:47
6

The Pythonic way to do it is not to care what platform you are on.

If there are multiple different facilities to accomplish something depending on the platform, then abstract them behind a function or class, which should try a facility and move on to another if that facility is not available on the current platform.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • This seems like a sensible thing to do. How would you suggest implementing the "try and move on" procedure in code? Like this: `try: something_for_windows() except: something_for_unix()`? If so, how would implement it if you were targeting more than two different types of operating system (for example: Windows, Linux and Mac/Darwin)? – user2722730 Aug 27 '13 at 18:55
  • @user2722730 try/except is one way to do it. If the API in question returns error codes if the facility is not present then you would test those instead. If you have more than two, then you would keep nesting these control structures. Alternatively, once you know which facility is supported you could swap out the default "try a bunch of stuff" implementation for one that calls the detected facility. – cdhowie Aug 27 '13 at 19:15
  • I need to import platform-specific Python modules to do platform-specific tasks, so no API error codes there. To do so by your suggestion on the 3 platforms I mentioned, I would need to have a try-except in a try-except. This seems like an ugly way to do it, especially since 3 is an odd number, the final except would have no code inside it, or I would need to manually re-raise whatever exception was caught for the Python script to quit and print the error. – user2722730 Aug 27 '13 at 19:23
  • 1
    @user2722730 That's roughly what you have to do. Try to import each module until one succeeds, then have your abstraction use that module. This is a rather common pattern in the Python world actually. – cdhowie Aug 27 '13 at 19:27
  • The problem is that each different module for different platforms have completely different methods, and therefore aren't interchangeable, so I'll have to use try-except in my actual code. There are certain platform-dependent functions in my script that may be run hundreds of time a second, it seems ridiculous to use try-except in this case when I *know* what modules work for what platforms. @nmclean's comment reply on the original post makes a lot of sense; treating a certain OS as an "exceptional" case would be wasteful. I think I'll stick with IF statements to run the right code. – user2722730 Aug 27 '13 at 21:21
  • Just to add: I can certainly understand using try-except for interchangeable modules like json and simplejson, but certainly not for platform-dependent modules such as the Windows API versus Linux-specific modules such as dbus. Though, perhaps I should have been clearer in the original question. This makes sense: http://stackoverflow.com/questions/3496592/conditional-import-of-modules-in-python – user2722730 Aug 27 '13 at 21:24
  • @user2722730 Ideally you could create abstractions for each high-level operation you need to do. You don't need to try/catch every time -- once you know which modules you have access to you can use the appropriate abstraction. If you are doing a lot of OS-specific low-level type stuff then that is screaming for a higher-level abstraction. Your base logic shouldn't care what platform it is running on, leave that up to the particular abstraction implementation. – cdhowie Aug 27 '13 at 21:36
  • This doesn't answer the question that was asked. I'm all for giving good advice on this site, but _this_ answer doesn't answer _this_ question. If it first addressed the question that was asked, and then segued into advice on better ways to do the same thing, I think it would be a more useful answer. – Bryan Oakley Aug 27 '13 at 23:27
  • @BryanOakley Part of a good answer is to know whether the right question was asked. – cdhowie Aug 28 '13 at 18:03
  • @cdhowie: agreed. However, I still like to see answers that address the specific question that was asked, since sometimes people do really want an answer to the actual question that they asked. It's sometimes hard to know just by reading the question. – Bryan Oakley Aug 28 '13 at 19:13
  • I've thought about this and it does seem to make sense to make the base logic "platform-blind" and use abstractions. I can't think of any scenario where it would be necessary to actually detect and compare the name of the operating system, even when checking for updates to binaries for example: the code should download updates based on what "branch" of the program is running, which could be hardcoded into the configuration of released binaries. – user2722730 Sep 06 '13 at 22:13