os.py 14.8 KB
Newer Older
1
"""OS routines for Mac, DOS, NT, or Posix depending on what system we're on.
Guido van Rossum's avatar
Guido van Rossum committed
2

3
This exports:
4 5 6
  - all functions from posix, nt, dos, os2, mac, or ce, e.g. unlink, stat, etc.
  - os.path is one of the modules posixpath, ntpath, macpath, or dospath
  - os.name is 'posix', 'nt', 'dos', 'os2', 'mac', or 'ce'
7 8 9
  - os.curdir is a string representing the current directory ('.' or ':')
  - os.pardir is a string representing the parent directory ('..' or '::')
  - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
10
  - os.altsep is the alternate pathname separator (None or '/')
11
  - os.pathsep is the component separator used in $PATH etc
12
  - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
13
  - os.defpath is the default search path for executables
Guido van Rossum's avatar
Guido van Rossum committed
14

15 16 17 18 19 20
Programs that import and use 'os' stand a better chance of being
portable between different platforms.  Of course, they must then
only use functions that are defined by all platforms (e.g., unlink
and opendir), and leave all pathname manipulation to os.path
(e.g., split and join).
"""
Guido van Rossum's avatar
Guido van Rossum committed
21

22
import sys
23

24
_names = sys.builtin_module_names
25

26 27 28
altsep = None

if 'posix' in _names:
29
    name = 'posix'
30
    linesep = '\n'
31 32 33 34 35 36 37 38 39 40
    curdir = '.'; pardir = '..'; sep = '/'; pathsep = ':'
    defpath = ':/bin:/usr/bin'
    from posix import *
    try:
        from posix import _exit
    except ImportError:
        pass
    import posixpath
    path = posixpath
    del posixpath
41
elif 'nt' in _names:
42
    name = 'nt'
43
    linesep = '\r\n'
44 45 46
    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
    defpath = '.;C:\\bin'
    from nt import *
47
    for i in ['_exit']:
48 49 50 51
        try:
            exec "from nt import " + i
        except ImportError:
            pass
52 53 54
    import ntpath
    path = ntpath
    del ntpath
55
elif 'dos' in _names:
56
    name = 'dos'
57
    linesep = '\r\n'
58 59 60 61 62 63 64 65 66 67
    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
    defpath = '.;C:\\bin'
    from dos import *
    try:
        from dos import _exit
    except ImportError:
        pass
    import dospath
    path = dospath
    del dospath
68
elif 'os2' in _names:
69
    name = 'os2'
70
    linesep = '\r\n'
71 72 73 74 75 76 77 78 79 80
    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
    defpath = '.;C:\\bin'
    from os2 import *
    try:
        from os2 import _exit
    except ImportError:
        pass
    import ntpath
    path = ntpath
    del ntpath
81
elif 'mac' in _names:
82
    name = 'mac'
83
    linesep = '\r'
84 85 86 87 88 89 90 91 92 93
    curdir = ':'; pardir = '::'; sep = ':'; pathsep = '\n'
    defpath = ':'
    from mac import *
    try:
        from mac import _exit
    except ImportError:
        pass
    import macpath
    path = macpath
    del macpath
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
elif 'ce' in _names:
    name = 'ce'
    linesep = '\r\n'
    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
    defpath = '\\Windows'
    from ce import *
    for i in ['_exit']:
        try:
            exec "from ce import " + i
        except ImportError:
            pass
    # We can use the standard Windows path.
    import ntpath
    path = ntpath
    del ntpath
Guido van Rossum's avatar
Guido van Rossum committed
109
else:
110
    raise ImportError, 'no os specific module found'
111

112 113
del _names

114 115
sys.modules['os.path'] = path

116 117 118 119 120 121 122 123 124 125 126 127 128
# Super directory utilities.
# (Inspired by Eric Raymond; the doc strings are mostly his)

def makedirs(name, mode=0777):
    """makedirs(path [, mode=0777]) -> None

    Super-mkdir; create a leaf directory and all intermediate ones.
    Works like mkdir, except that any intermediate path segment (not
    just the rightmost) will be created if it does not exist.  This is
    recursive.

    """
    head, tail = path.split(name)
129 130
    if not tail:
        head, tail = path.split(head)
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    if head and tail and not path.exists(head):
        makedirs(head, mode)
    mkdir(name, mode)

def removedirs(name):
    """removedirs(path) -> None

    Super-rmdir; remove a leaf directory and empty all intermediate
    ones.  Works like rmdir except that, if the leaf directory is
    successfully removed, directories corresponding to rightmost path
    segments will be pruned way until either the whole path is
    consumed or an error occurs.  Errors during this latter phase are
    ignored -- they generally mean that a directory was not empty.

    """
    rmdir(name)
    head, tail = path.split(name)
148 149
    if not tail:
        head, tail = path.split(head)
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    while head and tail:
        try:
            rmdir(head)
        except error:
            break
        head, tail = path.split(head)

def renames(old, new):
    """renames(old, new) -> None

    Super-rename; create directories as necessary and delete any left
    empty.  Works like rename, except creation of any intermediate
    directories needed to make the new pathname good is attempted
    first.  After the rename, directories corresponding to rightmost
    path segments of the old name will be pruned way until either the
    whole path is consumed or a nonempty directory is found.

    Note: this function can fail with the new directory structure made
    if you lack permissions needed to unlink the leaf directory or
    file.

    """
    head, tail = path.split(new)
    if head and tail and not path.exists(head):
        makedirs(head)
    rename(old, new)
    head, tail = path.split(old)
    if head and tail:
        try:
            removedirs(head)
        except error:
            pass

183 184
# Make sure os.environ exists, at least
try:
185
    environ
186
except NameError:
187
    environ = {}
188

189
def execl(file, *args):
Guido van Rossum's avatar
Guido van Rossum committed
190 191 192 193
    """execl(file, *args)

    Execute the executable file with argument list args, replacing the
    current process. """
194
    execv(file, args)
195 196

def execle(file, *args):
Guido van Rossum's avatar
Guido van Rossum committed
197 198 199 200
    """execle(file, *args, env)

    Execute the executable file with argument list args and
    environment env, replacing the current process. """
201 202
    env = args[-1]
    execve(file, args[:-1], env)
203 204

def execlp(file, *args):
Guido van Rossum's avatar
Guido van Rossum committed
205 206 207 208
    """execlp(file, *args)

    Execute the executable file (which is searched for along $PATH)
    with argument list args, replacing the current process. """
209
    execvp(file, args)
210

211
def execlpe(file, *args):
Guido van Rossum's avatar
Guido van Rossum committed
212 213 214 215 216
    """execlpe(file, *args, env)

    Execute the executable file (which is searched for along $PATH)
    with argument list args and environment env, replacing the current
    process. """    
217 218
    env = args[-1]
    execvpe(file, args[:-1], env)
219

220
def execvp(file, args):
Guido van Rossum's avatar
Guido van Rossum committed
221 222 223 224
    """execp(file, args)

    Execute the executable file (which is searched for along $PATH)
    with argument list args, replacing the current process.
225
    args may be a list or tuple of strings. """
226
    _execvpe(file, args)
227 228

def execvpe(file, args, env):
Guido van Rossum's avatar
Guido van Rossum committed
229 230 231 232 233
    """execv(file, args, env)

    Execute the executable file (which is searched for along $PATH)
    with argument list args and environment env , replacing the
    current process.
234
    args may be a list or tuple of strings. """    
235
    _execvpe(file, args, env)
236 237

_notfound = None
238 239
def _execvpe(file, args, env=None):
    if env is not None:
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
        func = execve
        argrest = (args, env)
    else:
        func = execv
        argrest = (args,)
        env = environ
    global _notfound
    head, tail = path.split(file)
    if head:
        apply(func, (file,) + argrest)
        return
    if env.has_key('PATH'):
        envpath = env['PATH']
    else:
        envpath = defpath
255
    PATH = envpath.split(pathsep)
256 257 258
    if not _notfound:
        import tempfile
        # Exec a file that is guaranteed not to exist
259
        try: execv(tempfile.mktemp(), ('blah',))
260 261 262 263 264 265 266 267 268 269
        except error, _notfound: pass
    exc, arg = error, _notfound
    for dir in PATH:
        fullname = path.join(dir, file)
        try:
            apply(func, (fullname,) + argrest)
        except error, (errno, msg):
            if errno != arg[0]:
                exc, arg = error, (errno, msg)
    raise exc, arg
Guido van Rossum's avatar
Guido van Rossum committed
270

271 272
# Change environ to automatically call putenv() if it exists
try:
273 274
    # This will fail if there's no putenv
    putenv
275
except NameError:
276
    pass
277
else:
278 279
    import UserDict

280 281
    if name in ('os2', 'nt', 'dos'):  # Where Env Var Names Must Be UPPERCASE
        # But we store them as upper case
282 283 284
        class _Environ(UserDict.UserDict):
            def __init__(self, environ):
                UserDict.UserDict.__init__(self)
285 286
                data = self.data
                for k, v in environ.items():
287
                    data[k.upper()] = v
288 289
            def __setitem__(self, key, item):
                putenv(key, item)
290
                self.data[key.upper()] = item
291
            def __getitem__(self, key):
292 293 294
                return self.data[key.upper()]
            def __delitem__(self, key):
                del self.data[key.upper()]
295
            def has_key(self, key):
296 297 298 299 300 301
                return self.data.has_key(key.upper())
            def get(self, key, failobj=None):
                return self.data.get(key.upper(), failobj)
            def update(self, dict):
                for k, v in dict.items():
                    self[k] = v
302 303 304 305 306 307 308 309 310

    else:  # Where Env Var Names Can Be Mixed Case
        class _Environ(UserDict.UserDict):
            def __init__(self, environ):
                UserDict.UserDict.__init__(self)
                self.data = environ
            def __setitem__(self, key, item):
                putenv(key, item)
                self.data[key] = item
311 312 313
            def update(self, dict):
                for k, v in dict.items():
                    self[k] = v
314 315

    environ = _Environ(environ)
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367

def getenv(key, default=None):
    """Get an environment variable, return None if it doesn't exist.

    The optional second argument can specify an alternative default."""
    return environ.get(key, default)

def _exists(name):
    try:
        eval(name)
        return 1
    except NameError:
        return 0

# Supply spawn*() (probably only for Unix)
if _exists("fork") and not _exists("spawnv") and _exists("execv"):

    P_WAIT = 0
    P_NOWAIT = P_NOWAITO = 1

    # XXX Should we support P_DETACH?  I suppose it could fork()**2
    # and close the std I/O streams.  Also, P_OVERLAY is the same
    # as execv*()?

    def _spawnvef(mode, file, args, env, func):
        # Internal helper; func is the exec*() function to use
        pid = fork()
        if not pid:
            # Child
            try:
                if env is None:
                    func(file, args)
                else:
                    func(file, args, env)
            except:
                _exit(127)
        else:
            # Parent
            if mode == P_NOWAIT:
                return pid # Caller is responsible for waiting!
            while 1:
                wpid, sts = waitpid(pid, 0)
                if WIFSTOPPED(sts):
                    continue
                elif WIFSIGNALED(sts):
                    return -WTERMSIG(sts)
                elif WIFEXITED(sts):
                    return WEXITSTATUS(sts)
                else:
                    raise error, "Not stopped, signaled or exited???"

    def spawnv(mode, file, args):
368 369 370 371 372
        """spawnv(mode, file, args) -> integer

Execute file with arguments from args in a subprocess.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
Guido van Rossum's avatar
Guido van Rossum committed
373
otherwise return -SIG, where SIG is the signal that killed it. """   
374 375 376
        return _spawnvef(mode, file, args, None, execv)

    def spawnve(mode, file, args, env):
377 378 379 380 381 382 383
        """spawnve(mode, file, args, env) -> integer

Execute file with arguments from args in a subprocess with the
specified environment.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
384 385
        return _spawnvef(mode, file, args, env, execve)

386 387 388
    # Note: spawnvp[e] is't currently supported on Windows

    def spawnvp(mode, file, args):
389 390 391 392 393 394 395
        """spawnvp(mode, file, args) -> integer

Execute file (which is looked for along $PATH) with arguments from
args in a subprocess.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
396 397 398
        return _spawnvef(mode, file, args, None, execvp)

    def spawnvpe(mode, file, args, env):
399 400 401 402 403 404 405
        """spawnvpe(mode, file, args, env) -> integer

Execute file (which is looked for along $PATH) with arguments from
args in a subprocess with the supplied environment.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
406 407 408 409 410
        return _spawnvef(mode, file, args, env, execvpe)

if _exists("spawnv"):
    # These aren't supplied by the basic Windows code
    # but can be easily implemented in Python
411 412

    def spawnl(mode, file, *args):
413 414 415 416 417 418
        """spawnl(mode, file, *args) -> integer

Execute file with arguments from args in a subprocess.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
419 420 421
        return spawnv(mode, file, args)

    def spawnle(mode, file, *args):
422 423 424 425 426 427 428
        """spawnle(mode, file, *args, env) -> integer

Execute file with arguments from args in a subprocess with the
supplied environment.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
429 430 431
        env = args[-1]
        return spawnve(mode, file, args[:-1], env)

432 433 434
if _exists("spawnvp"):
    # At the moment, Windows doesn't implement spawnvp[e],
    # so it won't have spawnlp[e] either.
435
    def spawnlp(mode, file, *args):
436 437 438 439 440 441 442
        """spawnlp(mode, file, *args, env) -> integer

Execute file (which is looked for along $PATH) with arguments from
args in a subprocess with the supplied environment.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
443 444 445
        return spawnvp(mode, file, args)

    def spawnlpe(mode, file, *args):
446 447 448 449 450 451 452
        """spawnlpe(mode, file, *args, env) -> integer

Execute file (which is looked for along $PATH) with arguments from
args in a subprocess with the supplied environment.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
453 454
        env = args[-1]
        return spawnvpe(mode, file, args[:-1], env)
455 456


457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
# Supply popen2 etc. (for Unix)
if _exists("fork"):
    if not _exists("popen2"):
        def popen2(cmd, mode="t", bufsize=-1):
            assert mode[:1] in ("b", "t")
            import popen2
            stdout, stdin = popen2.popen2(cmd, bufsize)
            return stdin, stdout

    if not _exists("popen3"):
        def popen3(cmd, mode="t", bufsize=-1):
            assert mode[:1] in ("b", "t")
            import popen2
            stdout, stdin, stderr = popen2.popen3(cmd, bufsize)
            return stdin, stdout, stderr