Home | History | Annotate | Download | only in Lib
      1 r"""OS routines for NT or Posix depending on what system we're on.
      2 
      3 This exports:
      4   - all functions from posix, nt, os2, or ce, e.g. unlink, stat, etc.
      5   - os.path is one of the modules posixpath, or ntpath
      6   - os.name is 'posix', 'nt', 'os2', '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.extsep is the extension separator ('.' or '/')
     11   - os.altsep is the alternate pathname separator (None or '/')
     12   - os.pathsep is the component separator used in $PATH etc
     13   - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
     14   - os.defpath is the default search path for executables
     15   - os.devnull is the file path of the null device ('/dev/null', etc.)
     16 
     17 Programs that import and use 'os' stand a better chance of being
     18 portable between different platforms.  Of course, they must then
     19 only use functions that are defined by all platforms (e.g., unlink
     20 and opendir), and leave all pathname manipulation to os.path
     21 (e.g., split and join).
     22 """
     23 
     24 #'
     25 
     26 import sys, errno
     27 
     28 _names = sys.builtin_module_names
     29 
     30 # Note:  more names are added to __all__ later.
     31 __all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep",
     32            "defpath", "name", "path", "devnull",
     33            "SEEK_SET", "SEEK_CUR", "SEEK_END"]
     34 
     35 def _get_exports_list(module):
     36     try:
     37         return list(module.__all__)
     38     except AttributeError:
     39         return [n for n in dir(module) if n[0] != '_']
     40 
     41 if 'posix' in _names:
     42     name = 'posix'
     43     linesep = '\n'
     44     from posix import *
     45     try:
     46         from posix import _exit
     47     except ImportError:
     48         pass
     49     import posixpath as path
     50 
     51     import posix
     52     __all__.extend(_get_exports_list(posix))
     53     del posix
     54 
     55 elif 'nt' in _names:
     56     name = 'nt'
     57     linesep = '\r\n'
     58     from nt import *
     59     try:
     60         from nt import _exit
     61     except ImportError:
     62         pass
     63     import ntpath as path
     64 
     65     import nt
     66     __all__.extend(_get_exports_list(nt))
     67     del nt
     68 
     69 elif 'os2' in _names:
     70     name = 'os2'
     71     linesep = '\r\n'
     72     from os2 import *
     73     try:
     74         from os2 import _exit
     75     except ImportError:
     76         pass
     77     if sys.version.find('EMX GCC') == -1:
     78         import ntpath as path
     79     else:
     80         import os2emxpath as path
     81         from _emx_link import link
     82 
     83     import os2
     84     __all__.extend(_get_exports_list(os2))
     85     del os2
     86 
     87 elif 'ce' in _names:
     88     name = 'ce'
     89     linesep = '\r\n'
     90     from ce import *
     91     try:
     92         from ce import _exit
     93     except ImportError:
     94         pass
     95     # We can use the standard Windows path.
     96     import ntpath as path
     97 
     98     import ce
     99     __all__.extend(_get_exports_list(ce))
    100     del ce
    101 
    102 elif 'riscos' in _names:
    103     name = 'riscos'
    104     linesep = '\n'
    105     from riscos import *
    106     try:
    107         from riscos import _exit
    108     except ImportError:
    109         pass
    110     import riscospath as path
    111 
    112     import riscos
    113     __all__.extend(_get_exports_list(riscos))
    114     del riscos
    115 
    116 else:
    117     raise ImportError, 'no os specific module found'
    118 
    119 sys.modules['os.path'] = path
    120 from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
    121     devnull)
    122 
    123 del _names
    124 
    125 # Python uses fixed values for the SEEK_ constants; they are mapped
    126 # to native constants if necessary in posixmodule.c
    127 SEEK_SET = 0
    128 SEEK_CUR = 1
    129 SEEK_END = 2
    130 
    131 #'
    132 
    133 # Super directory utilities.
    134 # (Inspired by Eric Raymond; the doc strings are mostly his)
    135 
    136 def makedirs(name, mode=0777):
    137     """makedirs(path [, mode=0777])
    138 
    139     Super-mkdir; create a leaf directory and all intermediate ones.
    140     Works like mkdir, except that any intermediate path segment (not
    141     just the rightmost) will be created if it does not exist.  This is
    142     recursive.
    143 
    144     """
    145     head, tail = path.split(name)
    146     if not tail:
    147         head, tail = path.split(head)
    148     if head and tail and not path.exists(head):
    149         try:
    150             makedirs(head, mode)
    151         except OSError, e:
    152             # be happy if someone already created the path
    153             if e.errno != errno.EEXIST:
    154                 raise
    155         if tail == curdir:           # xxx/newdir/. exists if xxx/newdir exists
    156             return
    157     mkdir(name, mode)
    158 
    159 def removedirs(name):
    160     """removedirs(path)
    161 
    162     Super-rmdir; remove a leaf directory and all empty intermediate
    163     ones.  Works like rmdir except that, if the leaf directory is
    164     successfully removed, directories corresponding to rightmost path
    165     segments will be pruned away until either the whole path is
    166     consumed or an error occurs.  Errors during this latter phase are
    167     ignored -- they generally mean that a directory was not empty.
    168 
    169     """
    170     rmdir(name)
    171     head, tail = path.split(name)
    172     if not tail:
    173         head, tail = path.split(head)
    174     while head and tail:
    175         try:
    176             rmdir(head)
    177         except error:
    178             break
    179         head, tail = path.split(head)
    180 
    181 def renames(old, new):
    182     """renames(old, new)
    183 
    184     Super-rename; create directories as necessary and delete any left
    185     empty.  Works like rename, except creation of any intermediate
    186     directories needed to make the new pathname good is attempted
    187     first.  After the rename, directories corresponding to rightmost
    188     path segments of the old name will be pruned until either the
    189     whole path is consumed or a nonempty directory is found.
    190 
    191     Note: this function can fail with the new directory structure made
    192     if you lack permissions needed to unlink the leaf directory or
    193     file.
    194 
    195     """
    196     head, tail = path.split(new)
    197     if head and tail and not path.exists(head):
    198         makedirs(head)
    199     rename(old, new)
    200     head, tail = path.split(old)
    201     if head and tail:
    202         try:
    203             removedirs(head)
    204         except error:
    205             pass
    206 
    207 __all__.extend(["makedirs", "removedirs", "renames"])
    208 
    209 def walk(top, topdown=True, onerror=None, followlinks=False):
    210     """Directory tree generator.
    211 
    212     For each directory in the directory tree rooted at top (including top
    213     itself, but excluding '.' and '..'), yields a 3-tuple
    214 
    215         dirpath, dirnames, filenames
    216 
    217     dirpath is a string, the path to the directory.  dirnames is a list of
    218     the names of the subdirectories in dirpath (excluding '.' and '..').
    219     filenames is a list of the names of the non-directory files in dirpath.
    220     Note that the names in the lists are just names, with no path components.
    221     To get a full path (which begins with top) to a file or directory in
    222     dirpath, do os.path.join(dirpath, name).
    223 
    224     If optional arg 'topdown' is true or not specified, the triple for a
    225     directory is generated before the triples for any of its subdirectories
    226     (directories are generated top down).  If topdown is false, the triple
    227     for a directory is generated after the triples for all of its
    228     subdirectories (directories are generated bottom up).
    229 
    230     When topdown is true, the caller can modify the dirnames list in-place
    231     (e.g., via del or slice assignment), and walk will only recurse into the
    232     subdirectories whose names remain in dirnames; this can be used to prune the
    233     search, or to impose a specific order of visiting.  Modifying dirnames when
    234     topdown is false is ineffective, since the directories in dirnames have
    235     already been generated by the time dirnames itself is generated. No matter
    236     the value of topdown, the list of subdirectories is retrieved before the
    237     tuples for the directory and its subdirectories are generated.
    238 
    239     By default errors from the os.listdir() call are ignored.  If
    240     optional arg 'onerror' is specified, it should be a function; it
    241     will be called with one argument, an os.error instance.  It can
    242     report the error to continue with the walk, or raise the exception
    243     to abort the walk.  Note that the filename is available as the
    244     filename attribute of the exception object.
    245 
    246     By default, os.walk does not follow symbolic links to subdirectories on
    247     systems that support them.  In order to get this functionality, set the
    248     optional argument 'followlinks' to true.
    249 
    250     Caution:  if you pass a relative pathname for top, don't change the
    251     current working directory between resumptions of walk.  walk never
    252     changes the current directory, and assumes that the client doesn't
    253     either.
    254 
    255     Example:
    256 
    257     import os
    258     from os.path import join, getsize
    259     for root, dirs, files in os.walk('python/Lib/email'):
    260         print root, "consumes",
    261         print sum([getsize(join(root, name)) for name in files]),
    262         print "bytes in", len(files), "non-directory files"
    263         if 'CVS' in dirs:
    264             dirs.remove('CVS')  # don't visit CVS directories
    265 
    266     """
    267 
    268     islink, join, isdir = path.islink, path.join, path.isdir
    269 
    270     # We may not have read permission for top, in which case we can't
    271     # get a list of the files the directory contains.  os.path.walk
    272     # always suppressed the exception then, rather than blow up for a
    273     # minor reason when (say) a thousand readable directories are still
    274     # left to visit.  That logic is copied here.
    275     try:
    276         # Note that listdir and error are globals in this module due
    277         # to earlier import-*.
    278         names = listdir(top)
    279     except error, err:
    280         if onerror is not None:
    281             onerror(err)
    282         return
    283 
    284     dirs, nondirs = [], []
    285     for name in names:
    286         if isdir(join(top, name)):
    287             dirs.append(name)
    288         else:
    289             nondirs.append(name)
    290 
    291     if topdown:
    292         yield top, dirs, nondirs
    293     for name in dirs:
    294         new_path = join(top, name)
    295         if followlinks or not islink(new_path):
    296             for x in walk(new_path, topdown, onerror, followlinks):
    297                 yield x
    298     if not topdown:
    299         yield top, dirs, nondirs
    300 
    301 __all__.append("walk")
    302 
    303 # Make sure os.environ exists, at least
    304 try:
    305     environ
    306 except NameError:
    307     environ = {}
    308 
    309 def execl(file, *args):
    310     """execl(file, *args)
    311 
    312     Execute the executable file with argument list args, replacing the
    313     current process. """
    314     execv(file, args)
    315 
    316 def execle(file, *args):
    317     """execle(file, *args, env)
    318 
    319     Execute the executable file with argument list args and
    320     environment env, replacing the current process. """
    321     env = args[-1]
    322     execve(file, args[:-1], env)
    323 
    324 def execlp(file, *args):
    325     """execlp(file, *args)
    326 
    327     Execute the executable file (which is searched for along $PATH)
    328     with argument list args, replacing the current process. """
    329     execvp(file, args)
    330 
    331 def execlpe(file, *args):
    332     """execlpe(file, *args, env)
    333 
    334     Execute the executable file (which is searched for along $PATH)
    335     with argument list args and environment env, replacing the current
    336     process. """
    337     env = args[-1]
    338     execvpe(file, args[:-1], env)
    339 
    340 def execvp(file, args):
    341     """execvp(file, args)
    342 
    343     Execute the executable file (which is searched for along $PATH)
    344     with argument list args, replacing the current process.
    345     args may be a list or tuple of strings. """
    346     _execvpe(file, args)
    347 
    348 def execvpe(file, args, env):
    349     """execvpe(file, args, env)
    350 
    351     Execute the executable file (which is searched for along $PATH)
    352     with argument list args and environment env , replacing the
    353     current process.
    354     args may be a list or tuple of strings. """
    355     _execvpe(file, args, env)
    356 
    357 __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
    358 
    359 def _execvpe(file, args, env=None):
    360     if env is not None:
    361         func = execve
    362         argrest = (args, env)
    363     else:
    364         func = execv
    365         argrest = (args,)
    366         env = environ
    367 
    368     head, tail = path.split(file)
    369     if head:
    370         func(file, *argrest)
    371         return
    372     if 'PATH' in env:
    373         envpath = env['PATH']
    374     else:
    375         envpath = defpath
    376     PATH = envpath.split(pathsep)
    377     saved_exc = None
    378     saved_tb = None
    379     for dir in PATH:
    380         fullname = path.join(dir, file)
    381         try:
    382             func(fullname, *argrest)
    383         except error, e:
    384             tb = sys.exc_info()[2]
    385             if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
    386                 and saved_exc is None):
    387                 saved_exc = e
    388                 saved_tb = tb
    389     if saved_exc:
    390         raise error, saved_exc, saved_tb
    391     raise error, e, tb
    392 
    393 # Change environ to automatically call putenv() if it exists
    394 try:
    395     # This will fail if there's no putenv
    396     putenv
    397 except NameError:
    398     pass
    399 else:
    400     import UserDict
    401 
    402     # Fake unsetenv() for Windows
    403     # not sure about os2 here but
    404     # I'm guessing they are the same.
    405 
    406     if name in ('os2', 'nt'):
    407         def unsetenv(key):
    408             putenv(key, "")
    409 
    410     if name == "riscos":
    411         # On RISC OS, all env access goes through getenv and putenv
    412         from riscosenviron import _Environ
    413     elif name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
    414         # But we store them as upper case
    415         class _Environ(UserDict.IterableUserDict):
    416             def __init__(self, environ):
    417                 UserDict.UserDict.__init__(self)
    418                 data = self.data
    419                 for k, v in environ.items():
    420                     data[k.upper()] = v
    421             def __setitem__(self, key, item):
    422                 putenv(key, item)
    423                 self.data[key.upper()] = item
    424             def __getitem__(self, key):
    425                 return self.data[key.upper()]
    426             try:
    427                 unsetenv
    428             except NameError:
    429                 def __delitem__(self, key):
    430                     del self.data[key.upper()]
    431             else:
    432                 def __delitem__(self, key):
    433                     unsetenv(key)
    434                     del self.data[key.upper()]
    435                 def clear(self):
    436                     for key in self.data.keys():
    437                         unsetenv(key)
    438                         del self.data[key]
    439                 def pop(self, key, *args):
    440                     unsetenv(key)
    441                     return self.data.pop(key.upper(), *args)
    442             def has_key(self, key):
    443                 return key.upper() in self.data
    444             def __contains__(self, key):
    445                 return key.upper() in self.data
    446             def get(self, key, failobj=None):
    447                 return self.data.get(key.upper(), failobj)
    448             def update(self, dict=None, **kwargs):
    449                 if dict:
    450                     try:
    451                         keys = dict.keys()
    452                     except AttributeError:
    453                         # List of (key, value)
    454                         for k, v in dict:
    455                             self[k] = v
    456                     else:
    457                         # got keys
    458                         # cannot use items(), since mappings
    459                         # may not have them.
    460                         for k in keys:
    461                             self[k] = dict[k]
    462                 if kwargs:
    463                     self.update(kwargs)
    464             def copy(self):
    465                 return dict(self)
    466 
    467     else:  # Where Env Var Names Can Be Mixed Case
    468         class _Environ(UserDict.IterableUserDict):
    469             def __init__(self, environ):
    470                 UserDict.UserDict.__init__(self)
    471                 self.data = environ
    472             def __setitem__(self, key, item):
    473                 putenv(key, item)
    474                 self.data[key] = item
    475             def update(self,  dict=None, **kwargs):
    476                 if dict:
    477                     try:
    478                         keys = dict.keys()
    479                     except AttributeError:
    480                         # List of (key, value)
    481                         for k, v in dict:
    482                             self[k] = v
    483                     else:
    484                         # got keys
    485                         # cannot use items(), since mappings
    486                         # may not have them.
    487                         for k in keys:
    488                             self[k] = dict[k]
    489                 if kwargs:
    490                     self.update(kwargs)
    491             try:
    492                 unsetenv
    493             except NameError:
    494                 pass
    495             else:
    496                 def __delitem__(self, key):
    497                     unsetenv(key)
    498                     del self.data[key]
    499                 def clear(self):
    500                     for key in self.data.keys():
    501                         unsetenv(key)
    502                         del self.data[key]
    503                 def pop(self, key, *args):
    504                     unsetenv(key)
    505                     return self.data.pop(key, *args)
    506             def copy(self):
    507                 return dict(self)
    508 
    509 
    510     environ = _Environ(environ)
    511 
    512 def getenv(key, default=None):
    513     """Get an environment variable, return None if it doesn't exist.
    514     The optional second argument can specify an alternate default."""
    515     return environ.get(key, default)
    516 __all__.append("getenv")
    517 
    518 def _exists(name):
    519     return name in globals()
    520 
    521 # Supply spawn*() (probably only for Unix)
    522 if _exists("fork") and not _exists("spawnv") and _exists("execv"):
    523 
    524     P_WAIT = 0
    525     P_NOWAIT = P_NOWAITO = 1
    526 
    527     # XXX Should we support P_DETACH?  I suppose it could fork()**2
    528     # and close the std I/O streams.  Also, P_OVERLAY is the same
    529     # as execv*()?
    530 
    531     def _spawnvef(mode, file, args, env, func):
    532         # Internal helper; func is the exec*() function to use
    533         pid = fork()
    534         if not pid:
    535             # Child
    536             try:
    537                 if env is None:
    538                     func(file, args)
    539                 else:
    540                     func(file, args, env)
    541             except:
    542                 _exit(127)
    543         else:
    544             # Parent
    545             if mode == P_NOWAIT:
    546                 return pid # Caller is responsible for waiting!
    547             while 1:
    548                 wpid, sts = waitpid(pid, 0)
    549                 if WIFSTOPPED(sts):
    550                     continue
    551                 elif WIFSIGNALED(sts):
    552                     return -WTERMSIG(sts)
    553                 elif WIFEXITED(sts):
    554                     return WEXITSTATUS(sts)
    555                 else:
    556                     raise error, "Not stopped, signaled or exited???"
    557 
    558     def spawnv(mode, file, args):
    559         """spawnv(mode, file, args) -> integer
    560 
    561 Execute file with arguments from args in a subprocess.
    562 If mode == P_NOWAIT return the pid of the process.
    563 If mode == P_WAIT return the process's exit code if it exits normally;
    564 otherwise return -SIG, where SIG is the signal that killed it. """
    565         return _spawnvef(mode, file, args, None, execv)
    566 
    567     def spawnve(mode, file, args, env):
    568         """spawnve(mode, file, args, env) -> integer
    569 
    570 Execute file with arguments from args in a subprocess with the
    571 specified environment.
    572 If mode == P_NOWAIT return the pid of the process.
    573 If mode == P_WAIT return the process's exit code if it exits normally;
    574 otherwise return -SIG, where SIG is the signal that killed it. """
    575         return _spawnvef(mode, file, args, env, execve)
    576 
    577     # Note: spawnvp[e] is't currently supported on Windows
    578 
    579     def spawnvp(mode, file, args):
    580         """spawnvp(mode, file, args) -> integer
    581 
    582 Execute file (which is looked for along $PATH) with arguments from
    583 args in a subprocess.
    584 If mode == P_NOWAIT return the pid of the process.
    585 If mode == P_WAIT return the process's exit code if it exits normally;
    586 otherwise return -SIG, where SIG is the signal that killed it. """
    587         return _spawnvef(mode, file, args, None, execvp)
    588 
    589     def spawnvpe(mode, file, args, env):
    590         """spawnvpe(mode, file, args, env) -> integer
    591 
    592 Execute file (which is looked for along $PATH) with arguments from
    593 args in a subprocess with the supplied environment.
    594 If mode == P_NOWAIT return the pid of the process.
    595 If mode == P_WAIT return the process's exit code if it exits normally;
    596 otherwise return -SIG, where SIG is the signal that killed it. """
    597         return _spawnvef(mode, file, args, env, execvpe)
    598 
    599 if _exists("spawnv"):
    600     # These aren't supplied by the basic Windows code
    601     # but can be easily implemented in Python
    602 
    603     def spawnl(mode, file, *args):
    604         """spawnl(mode, file, *args) -> integer
    605 
    606 Execute file with arguments from args in a subprocess.
    607 If mode == P_NOWAIT return the pid of the process.
    608 If mode == P_WAIT return the process's exit code if it exits normally;
    609 otherwise return -SIG, where SIG is the signal that killed it. """
    610         return spawnv(mode, file, args)
    611 
    612     def spawnle(mode, file, *args):
    613         """spawnle(mode, file, *args, env) -> integer
    614 
    615 Execute file with arguments from args in a subprocess with the
    616 supplied environment.
    617 If mode == P_NOWAIT return the pid of the process.
    618 If mode == P_WAIT return the process's exit code if it exits normally;
    619 otherwise return -SIG, where SIG is the signal that killed it. """
    620         env = args[-1]
    621         return spawnve(mode, file, args[:-1], env)
    622 
    623 
    624     __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",])
    625 
    626 
    627 if _exists("spawnvp"):
    628     # At the moment, Windows doesn't implement spawnvp[e],
    629     # so it won't have spawnlp[e] either.
    630     def spawnlp(mode, file, *args):
    631         """spawnlp(mode, file, *args) -> integer
    632 
    633 Execute file (which is looked for along $PATH) with arguments from
    634 args in a subprocess with the supplied environment.
    635 If mode == P_NOWAIT return the pid of the process.
    636 If mode == P_WAIT return the process's exit code if it exits normally;
    637 otherwise return -SIG, where SIG is the signal that killed it. """
    638         return spawnvp(mode, file, args)
    639 
    640     def spawnlpe(mode, file, *args):
    641         """spawnlpe(mode, file, *args, env) -> integer
    642 
    643 Execute file (which is looked for along $PATH) with arguments from
    644 args in a subprocess with the supplied environment.
    645 If mode == P_NOWAIT return the pid of the process.
    646 If mode == P_WAIT return the process's exit code if it exits normally;
    647 otherwise return -SIG, where SIG is the signal that killed it. """
    648         env = args[-1]
    649         return spawnvpe(mode, file, args[:-1], env)
    650 
    651 
    652     __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",])
    653 
    654 
    655 # Supply popen2 etc. (for Unix)
    656 if _exists("fork"):
    657     if not _exists("popen2"):
    658         def popen2(cmd, mode="t", bufsize=-1):
    659             """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
    660             may be a sequence, in which case arguments will be passed directly to
    661             the program without shell intervention (as with os.spawnv()).  If 'cmd'
    662             is a string it will be passed to the shell (as with os.system()). If
    663             'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
    664             file objects (child_stdin, child_stdout) are returned."""
    665             import warnings
    666             msg = "os.popen2 is deprecated.  Use the subprocess module."
    667             warnings.warn(msg, DeprecationWarning, stacklevel=2)
    668 
    669             import subprocess
    670             PIPE = subprocess.PIPE
    671             p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
    672                                  bufsize=bufsize, stdin=PIPE, stdout=PIPE,
    673                                  close_fds=True)
    674             return p.stdin, p.stdout
    675         __all__.append("popen2")
    676 
    677     if not _exists("popen3"):
    678         def popen3(cmd, mode="t", bufsize=-1):
    679             """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
    680             may be a sequence, in which case arguments will be passed directly to
    681             the program without shell intervention (as with os.spawnv()).  If 'cmd'
    682             is a string it will be passed to the shell (as with os.system()). If
    683             'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
    684             file objects (child_stdin, child_stdout, child_stderr) are returned."""
    685             import warnings
    686             msg = "os.popen3 is deprecated.  Use the subprocess module."
    687             warnings.warn(msg, DeprecationWarning, stacklevel=2)
    688 
    689             import subprocess
    690             PIPE = subprocess.PIPE
    691             p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
    692                                  bufsize=bufsize, stdin=PIPE, stdout=PIPE,
    693                                  stderr=PIPE, close_fds=True)
    694             return p.stdin, p.stdout, p.stderr
    695         __all__.append("popen3")
    696 
    697     if not _exists("popen4"):
    698         def popen4(cmd, mode="t", bufsize=-1):
    699             """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
    700             may be a sequence, in which case arguments will be passed directly to
    701             the program without shell intervention (as with os.spawnv()).  If 'cmd'
    702             is a string it will be passed to the shell (as with os.system()). If
    703             'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
    704             file objects (child_stdin, child_stdout_stderr) are returned."""
    705             import warnings
    706             msg = "os.popen4 is deprecated.  Use the subprocess module."
    707             warnings.warn(msg, DeprecationWarning, stacklevel=2)
    708 
    709             import subprocess
    710             PIPE = subprocess.PIPE
    711             p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
    712                                  bufsize=bufsize, stdin=PIPE, stdout=PIPE,
    713                                  stderr=subprocess.STDOUT, close_fds=True)
    714             return p.stdin, p.stdout
    715         __all__.append("popen4")
    716 
    717 import copy_reg as _copy_reg
    718 
    719 def _make_stat_result(tup, dict):
    720     return stat_result(tup, dict)
    721 
    722 def _pickle_stat_result(sr):
    723     (type, args) = sr.__reduce__()
    724     return (_make_stat_result, args)
    725 
    726 try:
    727     _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
    728 except NameError: # stat_result may not exist
    729     pass
    730 
    731 def _make_statvfs_result(tup, dict):
    732     return statvfs_result(tup, dict)
    733 
    734 def _pickle_statvfs_result(sr):
    735     (type, args) = sr.__reduce__()
    736     return (_make_statvfs_result, args)
    737 
    738 try:
    739     _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
    740                      _make_statvfs_result)
    741 except NameError: # statvfs_result may not exist
    742     pass
    743