os.py revision 81e4b1c5c8307285c89952c3ee9c9f5c3d4896f3
1r"""OS routines for Mac, DOS, NT, or Posix depending on what system we're on. 2 3This exports: 4 - all functions from posix, nt, dos, os2, mac, or ce, e.g. unlink, stat, etc. 5 - os.path is one of the modules posixpath, ntpath, macpath, or dospath 6 - os.name is 'posix', 'nt', 'dos', 'os2', 'mac', 'ce' or 'riscos' 7 - os.curdir is a string representing the current directory ('.' or ':') 8 - os.pardir is a string representing the parent directory ('..' or '::') 9 - 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 14 15Programs that import and use 'os' stand a better chance of being 16portable between different platforms. Of course, they must then 17only use functions that are defined by all platforms (e.g., unlink 18and opendir), and leave all pathname manipulation to os.path 19(e.g., split and join). 20""" 21 22#' 23 24import sys 25 26_names = sys.builtin_module_names 27 28altsep = None 29 30__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", 31 "defpath", "name"] 32 33def _get_exports_list(module): 34 try: 35 return list(module.__all__) 36 except AttributeError: 37 return [n for n in dir(module) if n[0] != '_'] 38 39if 'posix' in _names: 40 name = 'posix' 41 linesep = '\n' 42 curdir = '.'; pardir = '..'; sep = '/'; pathsep = ':' 43 defpath = ':/bin:/usr/bin' 44 from posix import * 45 try: 46 from posix import _exit 47 except ImportError: 48 pass 49 import posixpath 50 path = posixpath 51 del posixpath 52 53 import posix 54 __all__.extend(_get_exports_list(posix)) 55 del posix 56 57elif 'nt' in _names: 58 name = 'nt' 59 linesep = '\r\n' 60 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';' 61 defpath = '.;C:\\bin' 62 from nt import * 63 for i in ['_exit']: 64 try: 65 exec "from nt import " + i 66 except ImportError: 67 pass 68 import ntpath 69 path = ntpath 70 del ntpath 71 72 import nt 73 __all__.extend(_get_exports_list(nt)) 74 del nt 75 76elif 'dos' in _names: 77 name = 'dos' 78 linesep = '\r\n' 79 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';' 80 defpath = '.;C:\\bin' 81 from dos import * 82 try: 83 from dos import _exit 84 except ImportError: 85 pass 86 import dospath 87 path = dospath 88 del dospath 89 90 import dos 91 __all__.extend(_get_exports_list(dos)) 92 del dos 93 94elif 'os2' in _names: 95 name = 'os2' 96 linesep = '\r\n' 97 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';' 98 defpath = '.;C:\\bin' 99 from os2 import * 100 try: 101 from os2 import _exit 102 except ImportError: 103 pass 104 import ntpath 105 path = ntpath 106 del ntpath 107 108 import os2 109 __all__.extend(_get_exports_list(os2)) 110 del os2 111 112elif 'mac' in _names: 113 name = 'mac' 114 linesep = '\r' 115 curdir = ':'; pardir = '::'; sep = ':'; pathsep = '\n' 116 defpath = ':' 117 from mac import * 118 try: 119 from mac import _exit 120 except ImportError: 121 pass 122 import macpath 123 path = macpath 124 del macpath 125 126 import mac 127 __all__.extend(_get_exports_list(mac)) 128 del mac 129 130elif 'ce' in _names: 131 name = 'ce' 132 linesep = '\r\n' 133 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';' 134 defpath = '\\Windows' 135 from ce import * 136 for i in ['_exit']: 137 try: 138 exec "from ce import " + i 139 except ImportError: 140 pass 141 # We can use the standard Windows path. 142 import ntpath 143 path = ntpath 144 del ntpath 145 146 import ce 147 __all__.extend(_get_exports_list(ce)) 148 del ce 149 150elif 'riscos' in _names: 151 name = 'riscos' 152 linesep = '\n' 153 curdir = '@'; pardir = '^'; sep = '.'; pathsep = ',' 154 defpath = '<Run$Dir>' 155 from riscos import * 156 try: 157 from riscos import _exit 158 except ImportError: 159 pass 160 import riscospath 161 path = riscospath 162 del riscospath 163 from riscosenviron import environ 164 165 import riscos 166 __all__.extend(_get_exports_list(riscos)) 167 del riscos 168 169else: 170 raise ImportError, 'no os specific module found' 171 172__all__.append("path") 173 174del _names 175 176sys.modules['os.path'] = path 177 178#' 179 180# Super directory utilities. 181# (Inspired by Eric Raymond; the doc strings are mostly his) 182 183def makedirs(name, mode=0777): 184 """makedirs(path [, mode=0777]) -> None 185 186 Super-mkdir; create a leaf directory and all intermediate ones. 187 Works like mkdir, except that any intermediate path segment (not 188 just the rightmost) will be created if it does not exist. This is 189 recursive. 190 191 """ 192 head, tail = path.split(name) 193 if not tail: 194 head, tail = path.split(head) 195 if head and tail and not path.exists(head): 196 makedirs(head, mode) 197 mkdir(name, mode) 198 199def removedirs(name): 200 """removedirs(path) -> None 201 202 Super-rmdir; remove a leaf directory and empty all intermediate 203 ones. Works like rmdir except that, if the leaf directory is 204 successfully removed, directories corresponding to rightmost path 205 segments will be pruned way until either the whole path is 206 consumed or an error occurs. Errors during this latter phase are 207 ignored -- they generally mean that a directory was not empty. 208 209 """ 210 rmdir(name) 211 head, tail = path.split(name) 212 if not tail: 213 head, tail = path.split(head) 214 while head and tail: 215 try: 216 rmdir(head) 217 except error: 218 break 219 head, tail = path.split(head) 220 221def renames(old, new): 222 """renames(old, new) -> None 223 224 Super-rename; create directories as necessary and delete any left 225 empty. Works like rename, except creation of any intermediate 226 directories needed to make the new pathname good is attempted 227 first. After the rename, directories corresponding to rightmost 228 path segments of the old name will be pruned way until either the 229 whole path is consumed or a nonempty directory is found. 230 231 Note: this function can fail with the new directory structure made 232 if you lack permissions needed to unlink the leaf directory or 233 file. 234 235 """ 236 head, tail = path.split(new) 237 if head and tail and not path.exists(head): 238 makedirs(head) 239 rename(old, new) 240 head, tail = path.split(old) 241 if head and tail: 242 try: 243 removedirs(head) 244 except error: 245 pass 246 247__all__.extend(["makedirs", "removedirs", "renames"]) 248 249# Make sure os.environ exists, at least 250try: 251 environ 252except NameError: 253 environ = {} 254 255def execl(file, *args): 256 """execl(file, *args) 257 258 Execute the executable file with argument list args, replacing the 259 current process. """ 260 execv(file, args) 261 262def execle(file, *args): 263 """execle(file, *args, env) 264 265 Execute the executable file with argument list args and 266 environment env, replacing the current process. """ 267 env = args[-1] 268 execve(file, args[:-1], env) 269 270def execlp(file, *args): 271 """execlp(file, *args) 272 273 Execute the executable file (which is searched for along $PATH) 274 with argument list args, replacing the current process. """ 275 execvp(file, args) 276 277def execlpe(file, *args): 278 """execlpe(file, *args, env) 279 280 Execute the executable file (which is searched for along $PATH) 281 with argument list args and environment env, replacing the current 282 process. """ 283 env = args[-1] 284 execvpe(file, args[:-1], env) 285 286def execvp(file, args): 287 """execp(file, args) 288 289 Execute the executable file (which is searched for along $PATH) 290 with argument list args, replacing the current process. 291 args may be a list or tuple of strings. """ 292 _execvpe(file, args) 293 294def execvpe(file, args, env): 295 """execv(file, args, env) 296 297 Execute the executable file (which is searched for along $PATH) 298 with argument list args and environment env , replacing the 299 current process. 300 args may be a list or tuple of strings. """ 301 _execvpe(file, args, env) 302 303__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) 304 305_notfound = None 306def _execvpe(file, args, env=None): 307 if env is not None: 308 func = execve 309 argrest = (args, env) 310 else: 311 func = execv 312 argrest = (args,) 313 env = environ 314 global _notfound 315 head, tail = path.split(file) 316 if head: 317 apply(func, (file,) + argrest) 318 return 319 if env.has_key('PATH'): 320 envpath = env['PATH'] 321 else: 322 envpath = defpath 323 PATH = envpath.split(pathsep) 324 if not _notfound: 325 if sys.platform[:4] == 'beos': 326 # Process handling (fork, wait) under BeOS (up to 5.0) 327 # doesn't interoperate reliably with the thread interlocking 328 # that happens during an import. The actual error we need 329 # is the same on BeOS for posix.open() et al., ENOENT. 330 try: unlink('/_#.# ## #.#') 331 except error, _notfound: pass 332 else: 333 import tempfile 334 t = tempfile.mktemp() 335 # Exec a file that is guaranteed not to exist 336 try: execv(t, ('blah',)) 337 except error, _notfound: pass 338 exc, arg = error, _notfound 339 for dir in PATH: 340 fullname = path.join(dir, file) 341 try: 342 apply(func, (fullname,) + argrest) 343 except error, (errno, msg): 344 if errno != arg[0]: 345 exc, arg = error, (errno, msg) 346 raise exc, arg 347 348 349if name != "riscos": 350 # Change environ to automatically call putenv() if it exists 351 try: 352 # This will fail if there's no putenv 353 putenv 354 except NameError: 355 pass 356 else: 357 import UserDict 358 359 if name in ('os2', 'nt', 'dos'): # Where Env Var Names Must Be UPPERCASE 360 # But we store them as upper case 361 class _Environ(UserDict.UserDict): 362 def __init__(self, environ): 363 UserDict.UserDict.__init__(self) 364 data = self.data 365 for k, v in environ.items(): 366 data[k.upper()] = v 367 def __setitem__(self, key, item): 368 putenv(key, item) 369 self.data[key.upper()] = item 370 def __getitem__(self, key): 371 return self.data[key.upper()] 372 def __delitem__(self, key): 373 del self.data[key.upper()] 374 def has_key(self, key): 375 return self.data.has_key(key.upper()) 376 def get(self, key, failobj=None): 377 return self.data.get(key.upper(), failobj) 378 def update(self, dict): 379 for k, v in dict.items(): 380 self[k] = v 381 382 else: # Where Env Var Names Can Be Mixed Case 383 class _Environ(UserDict.UserDict): 384 def __init__(self, environ): 385 UserDict.UserDict.__init__(self) 386 self.data = environ 387 def __setitem__(self, key, item): 388 putenv(key, item) 389 self.data[key] = item 390 def update(self, dict): 391 for k, v in dict.items(): 392 self[k] = v 393 394 environ = _Environ(environ) 395 396 def getenv(key, default=None): 397 """Get an environment variable, return None if it doesn't exist. 398 The optional second argument can specify an alternate default.""" 399 return environ.get(key, default) 400 __all__.append("getenv") 401 402def _exists(name): 403 try: 404 eval(name) 405 return 1 406 except NameError: 407 return 0 408 409# Supply spawn*() (probably only for Unix) 410if _exists("fork") and not _exists("spawnv") and _exists("execv"): 411 412 P_WAIT = 0 413 P_NOWAIT = P_NOWAITO = 1 414 415 # XXX Should we support P_DETACH? I suppose it could fork()**2 416 # and close the std I/O streams. Also, P_OVERLAY is the same 417 # as execv*()? 418 419 def _spawnvef(mode, file, args, env, func): 420 # Internal helper; func is the exec*() function to use 421 pid = fork() 422 if not pid: 423 # Child 424 try: 425 if env is None: 426 func(file, args) 427 else: 428 func(file, args, env) 429 except: 430 _exit(127) 431 else: 432 # Parent 433 if mode == P_NOWAIT: 434 return pid # Caller is responsible for waiting! 435 while 1: 436 wpid, sts = waitpid(pid, 0) 437 if WIFSTOPPED(sts): 438 continue 439 elif WIFSIGNALED(sts): 440 return -WTERMSIG(sts) 441 elif WIFEXITED(sts): 442 return WEXITSTATUS(sts) 443 else: 444 raise error, "Not stopped, signaled or exited???" 445 446 def spawnv(mode, file, args): 447 """spawnv(mode, file, args) -> integer 448 449Execute file with arguments from args in a subprocess. 450If mode == P_NOWAIT return the pid of the process. 451If mode == P_WAIT return the process's exit code if it exits normally; 452otherwise return -SIG, where SIG is the signal that killed it. """ 453 return _spawnvef(mode, file, args, None, execv) 454 455 def spawnve(mode, file, args, env): 456 """spawnve(mode, file, args, env) -> integer 457 458Execute file with arguments from args in a subprocess with the 459specified environment. 460If mode == P_NOWAIT return the pid of the process. 461If mode == P_WAIT return the process's exit code if it exits normally; 462otherwise return -SIG, where SIG is the signal that killed it. """ 463 return _spawnvef(mode, file, args, env, execve) 464 465 # Note: spawnvp[e] is't currently supported on Windows 466 467 def spawnvp(mode, file, args): 468 """spawnvp(mode, file, args) -> integer 469 470Execute file (which is looked for along $PATH) with arguments from 471args in a subprocess. 472If mode == P_NOWAIT return the pid of the process. 473If mode == P_WAIT return the process's exit code if it exits normally; 474otherwise return -SIG, where SIG is the signal that killed it. """ 475 return _spawnvef(mode, file, args, None, execvp) 476 477 def spawnvpe(mode, file, args, env): 478 """spawnvpe(mode, file, args, env) -> integer 479 480Execute file (which is looked for along $PATH) with arguments from 481args in a subprocess with the supplied environment. 482If mode == P_NOWAIT return the pid of the process. 483If mode == P_WAIT return the process's exit code if it exits normally; 484otherwise return -SIG, where SIG is the signal that killed it. """ 485 return _spawnvef(mode, file, args, env, execvpe) 486 487if _exists("spawnv"): 488 # These aren't supplied by the basic Windows code 489 # but can be easily implemented in Python 490 491 def spawnl(mode, file, *args): 492 """spawnl(mode, file, *args) -> integer 493 494Execute file with arguments from args in a subprocess. 495If mode == P_NOWAIT return the pid of the process. 496If mode == P_WAIT return the process's exit code if it exits normally; 497otherwise return -SIG, where SIG is the signal that killed it. """ 498 return spawnv(mode, file, args) 499 500 def spawnle(mode, file, *args): 501 """spawnle(mode, file, *args, env) -> integer 502 503Execute file with arguments from args in a subprocess with the 504supplied environment. 505If mode == P_NOWAIT return the pid of the process. 506If mode == P_WAIT return the process's exit code if it exits normally; 507otherwise return -SIG, where SIG is the signal that killed it. """ 508 env = args[-1] 509 return spawnve(mode, file, args[:-1], env) 510 511if _exists("spawnvp"): 512 # At the moment, Windows doesn't implement spawnvp[e], 513 # so it won't have spawnlp[e] either. 514 def spawnlp(mode, file, *args): 515 """spawnlp(mode, file, *args, env) -> integer 516 517Execute file (which is looked for along $PATH) with arguments from 518args in a subprocess with the supplied environment. 519If mode == P_NOWAIT return the pid of the process. 520If mode == P_WAIT return the process's exit code if it exits normally; 521otherwise return -SIG, where SIG is the signal that killed it. """ 522 return spawnvp(mode, file, args) 523 524 def spawnlpe(mode, file, *args): 525 """spawnlpe(mode, file, *args, env) -> integer 526 527Execute file (which is looked for along $PATH) with arguments from 528args in a subprocess with the supplied environment. 529If mode == P_NOWAIT return the pid of the process. 530If mode == P_WAIT return the process's exit code if it exits normally; 531otherwise return -SIG, where SIG is the signal that killed it. """ 532 env = args[-1] 533 return spawnvpe(mode, file, args[:-1], env) 534 535 536 __all__.extend(["spawnlp","spawnlpe","spawnv", "spawnve","spawnvp", 537 "spawnvpe","spawnl","spawnle",]) 538 539 540# Supply popen2 etc. (for Unix) 541if _exists("fork"): 542 if not _exists("popen2"): 543 def popen2(cmd, mode="t", bufsize=-1): 544 import popen2 545 stdout, stdin = popen2.popen2(cmd, bufsize) 546 return stdin, stdout 547 __all__.append("popen2") 548 549 if not _exists("popen3"): 550 def popen3(cmd, mode="t", bufsize=-1): 551 import popen2 552 stdout, stdin, stderr = popen2.popen3(cmd, bufsize) 553 return stdin, stdout, stderr 554 __all__.append("popen3") 555 556 if not _exists("popen4"): 557 def popen4(cmd, mode="t", bufsize=-1): 558 import popen2 559 stdout, stdin = popen2.popen4(cmd, bufsize) 560 return stdin, stdout 561 __all__.append("popen4") 562