Home | History | Annotate | Download | only in python2.7
      1 r"""OS routines for Mac, 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 way 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
    233     the search, or to impose a specific order of visiting.  Modifying
    234     dirnames when topdown is false is ineffective, since the directories in
    235     dirnames have already been generated by the time dirnames itself is
    236     generated.
    237 
    238     By default errors from the os.listdir() call are ignored.  If
    239     optional arg 'onerror' is specified, it should be a function; it
    240     will be called with one argument, an os.error instance.  It can
    241     report the error to continue with the walk, or raise the exception
    242     to abort the walk.  Note that the filename is available as the
    243     filename attribute of the exception object.
    244 
    245     By default, os.walk does not follow symbolic links to subdirectories on
    246     systems that support them.  In order to get this functionality, set the
    247     optional argument 'followlinks' to true.
    248 
    249     Caution:  if you pass a relative pathname for top, don't change the
    250     current working directory between resumptions of walk.  walk never
    251     changes the current directory, and assumes that the client doesn't
    252     either.
    253 
    254     Example:
    255 
    256     import os
    257     from os.path import join, getsize
    258     for root, dirs, files in os.walk('python/Lib/email'):
    259         print root, "consumes",
    260         print sum([getsize(join(root, name)) for name in files]),
    261         print "bytes in", len(files), "non-directory files"
    262         if 'CVS' in dirs:
    263             dirs.remove('CVS')  # don't visit CVS directories
    264     """
    265 
    266     islink, join, isdir = path.islink, path.join, path.isdir
    267 
    268     # We may not have read permission for top, in which case we can't
    269     # get a list of the files the directory contains.  os.path.walk
    270     # always suppressed the exception then, rather than blow up for a
    271     # minor reason when (say) a thousand readable directories are still
    272     # left to visit.  That logic is copied here.
    273     try:
    274         # Note that listdir and error are globals in this module due
    275         # to earlier import-*.
    276         names = listdir(top)
    277     except error, err:
    278         if onerror is not None:
    279             onerror(err)
    280         return
    281 
    282     dirs, nondirs = [], []
    283     for name in names:
    284         if isdir(join(top, name)):
    285             dirs.append(name)
    286         else:
    287             nondirs.append(name)
    288 
    289     if topdown:
    290         yield top, dirs, nondirs
    291     for name in dirs:
    292         new_path = join(top, name)
    293         if followlinks or not islink(new_path):
    294             for x in walk(new_path, topdown, onerror, followlinks):
    295                 yield x
    296     if not topdown:
    297         yield top, dirs, nondirs
    298 
    299 __all__.append("walk")
    300 
    301 # Make sure os.environ exists, at least
    302 try:
    303     environ
    304 except NameError:
    305     environ = {}
    306 
    307 def execl(file, *args):
    308     """execl(file, *args)
    309 
    310     Execute the executable file with argument list args, replacing the
    311     current process. """
    312     execv(file, args)
    313 
    314 def execle(file, *args):
    315     """execle(file, *args, env)
    316 
    317     Execute the executable file with argument list args and
    318     environment env, replacing the current process. """
    319     env = args[-1]
    320     execve(file, args[:-1], env)
    321 
    322 def execlp(file, *args):
    323     """execlp(file, *args)
    324 
    325     Execute the executable file (which is searched for along $PATH)
    326     with argument list args, replacing the current process. """
    327     execvp(file, args)
    328 
    329 def execlpe(file, *args):
    330     """execlpe(file, *args, env)
    331 
    332     Execute the executable file (which is searched for along $PATH)
    333     with argument list args and environment env, replacing the current
    334     process. """
    335     env = args[-1]
    336     execvpe(file, args[:-1], env)
    337 
    338 def execvp(file, args):
    339     """execvp(file, args)
    340 
    341     Execute the executable file (which is searched for along $PATH)
    342     with argument list args, replacing the current process.
    343     args may be a list or tuple of strings. """
    344     _execvpe(file, args)
    345 
    346 def execvpe(file, args, env):
    347     """execvpe(file, args, env)
    348 
    349     Execute the executable file (which is searched for along $PATH)
    350     with argument list args and environment env , replacing the
    351     current process.
    352     args may be a list or tuple of strings. """
    353     _execvpe(file, args, env)
    354 
    355 __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
    356 
    357 def _execvpe(file, args, env=None):
    358     if env is not None:
    359         func = execve
    360         argrest = (args, env)
    361     else:
    362         func = execv
    363         argrest = (args,)
    364         env = environ
    365 
    366     head, tail = path.split(file)
    367     if head:
    368         func(file, *argrest)
    369         return
    370     if 'PATH' in env:
    371         envpath = env['PATH']
    372     else:
    373         envpath = defpath
    374     PATH = envpath.split(pathsep)
    375     saved_exc = None
    376     saved_tb = None
    377     for dir in PATH:
    378         fullname = path.join(dir, file)
    379         try:
    380             func(fullname, *argrest)
    381         except error, e:
    382             tb = sys.exc_info()[2]
    383             if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
    384                 and saved_exc is None):
    385                 saved_exc = e
    386                 saved_tb = tb
    387     if saved_exc:
    388         raise error, saved_exc, saved_tb
    389     raise error, e, tb
    390 
    391 # Change environ to automatically call putenv() if it exists
    392 try:
    393     # This will fail if there's no putenv
    394     putenv
    395 except NameError:
    396     pass
    397 else:
    398     import UserDict
    399 
    400     # Fake unsetenv() for Windows
    401     # not sure about os2 here but
    402     # I'm guessing they are the same.
    403 
    404     if name in ('os2', 'nt'):
    405         def unsetenv(key):
    406             putenv(key, "")
    407 
    408     if name == "riscos":
    409         # On RISC OS, all env access goes through getenv and putenv
    410         from riscosenviron import _Environ
    411     elif name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
    412         # But we store them as upper case
    413         class _Environ(UserDict.IterableUserDict):
    414             def __init__(self, environ):
    415                 UserDict.UserDict.__init__(self)
    416                 data = self.data
    417                 for k, v in environ.items():
    418                     data[k.upper()] = v
    419             def __setitem__(self, key, item):
    420                 putenv(key, item)
    421                 self.data[key.upper()] = item
    422             def __getitem__(self, key):
    423                 return self.data[key.upper()]
    424             try:
    425                 unsetenv
    426             except NameError:
    427                 def __delitem__(self, key):
    428                     del self.data[key.upper()]
    429             else:
    430                 def __delitem__(self, key):
    431                     unsetenv(key)
    432                     del self.data[key.upper()]
    433                 def clear(self):
    434                     for key in self.data.keys():
    435                         unsetenv(key)
    436                         del self.data[key]
    437                 def pop(self, key, *args):
    438                     unsetenv(key)
    439                     return self.data.pop(key.upper(), *args)
    440             def has_key(self, key):
    441                 return key.upper() in self.data
    442             def __contains__(self, key):
    443                 return key.upper() in self.data
    444             def get(self, key, failobj=None):
    445                 return self.data.get(key.upper(), failobj)
    446             def update(self, dict=None, **kwargs):
    447                 if dict:
    448                     try:
    449                         keys = dict.keys()
    450                     except AttributeError:
    451                         # List of (key, value)
    452                         for k, v in dict:
    453                             self[k] = v
    454                     else:
    455                         # got keys
    456                         # cannot use items(), since mappings
    457                         # may not have them.
    458                         for k in keys:
    459                             self[k] = dict[k]
    460                 if kwargs:
    461                     self.update(kwargs)
    462             def copy(self):
    463                 return dict(self)
    464 
    465     else:  # Where Env Var Names Can Be Mixed Case
    466         class _Environ(UserDict.IterableUserDict):
    467             def __init__(self, environ):
    468                 UserDict.UserDict.__init__(self)
    469                 self.data = environ
    470             def __setitem__(self, key, item):
    471                 putenv(key, item)
    472                 self.data[key] = item
    473             def update(self,  dict=None, **kwargs):
    474                 if dict:
    475                     try:
    476                         keys = dict.keys()
    477                     except AttributeError:
    478                         # List of (key, value)
    479                         for k, v in dict:
    480                             self[k] = v
    481                     else:
    482                         # got keys
    483                         # cannot use items(), since mappings
    484                         # may not have them.
    485                         for k in keys:
    486                             self[k] = dict[k]
    487                 if kwargs:
    488                     self.update(kwargs)
    489             try:
    490                 unsetenv
    491             except NameError:
    492                 pass
    493             else:
    494                 def __delitem__(self, key):
    495                     unsetenv(key)
    496                     del self.data[key]
    497                 def clear(self):
    498                     for key in self.data.keys():
    499                         unsetenv(key)
    500                         del self.data[key]
    501                 def pop(self, key, *args):
    502                     unsetenv(key)
    503                     return self.data.pop(key, *args)
    504             def copy(self):
    505                 return dict(self)
    506 
    507 
    508     environ = _Environ(environ)
    509 
    510 def getenv(key, default=None):
    511     """Get an environment variable, return None if it doesn't exist.
    512     The optional second argument can specify an alternate default."""
    513     return environ.get(key, default)
    514 __all__.append("getenv")
    515 
    516 def _exists(name):
    517     return name in globals()
    518 
    519 # Supply spawn*() (probably only for Unix)
    520 if _exists("fork") and not _exists("spawnv") and _exists("execv"):
    521 
    522     P_WAIT = 0
    523     P_NOWAIT = P_NOWAITO = 1
    524 
    525     # XXX Should we support P_DETACH?  I suppose it could fork()**2
    526     # and close the std I/O streams.  Also, P_OVERLAY is the same
    527     # as execv*()?
    528 
    529     def _spawnvef(mode, file, args, env, func):
    530         # Internal helper; func is the exec*() function to use
    531         pid = fork()
    532         if not pid:
    533             # Child
    534             try:
    535                 if env is None:
    536                     func(file, args)
    537                 else:
    538                     func(file, args, env)
    539             except:
    540                 _exit(127)
    541         else:
    542             # Parent
    543             if mode == P_NOWAIT:
    544                 return pid # Caller is responsible for waiting!
    545             while 1:
    546                 wpid, sts = waitpid(pid, 0)
    547                 if WIFSTOPPED(sts):
    548                     continue
    549                 elif WIFSIGNALED(sts):
    550                     return -WTERMSIG(sts)
    551                 elif WIFEXITED(sts):
    552                     return WEXITSTATUS(sts)
    553                 else:
    554                     raise error, "Not stopped, signaled or exited???"
    555 
    556     def spawnv(mode, file, args):
    557         """spawnv(mode, file, args) -> integer
    558 
    559 Execute file with arguments from args in a subprocess.
    560 If mode == P_NOWAIT return the pid of the process.
    561 If mode == P_WAIT return the process's exit code if it exits normally;
    562 otherwise return -SIG, where SIG is the signal that killed it. """
    563         return _spawnvef(mode, file, args, None, execv)
    564 
    565     def spawnve(mode, file, args, env):
    566         """spawnve(mode, file, args, env) -> integer
    567 
    568 Execute file with arguments from args in a subprocess with the
    569 specified environment.
    570 If mode == P_NOWAIT return the pid of the process.
    571 If mode == P_WAIT return the process's exit code if it exits normally;
    572 otherwise return -SIG, where SIG is the signal that killed it. """
    573         return _spawnvef(mode, file, args, env, execve)
    574 
    575     # Note: spawnvp[e] is't currently supported on Windows
    576 
    577     def spawnvp(mode, file, args):
    578         """spawnvp(mode, file, args) -> integer
    579 
    580 Execute file (which is looked for along $PATH) with arguments from
    581 args in a subprocess.
    582 If mode == P_NOWAIT return the pid of the process.
    583 If mode == P_WAIT return the process's exit code if it exits normally;
    584 otherwise return -SIG, where SIG is the signal that killed it. """
    585         return _spawnvef(mode, file, args, None, execvp)
    586 
    587     def spawnvpe(mode, file, args, env):
    588         """spawnvpe(mode, file, args, env) -> integer
    589 
    590 Execute file (which is looked for along $PATH) with arguments from
    591 args in a subprocess with the supplied environment.
    592 If mode == P_NOWAIT return the pid of the process.
    593 If mode == P_WAIT return the process's exit code if it exits normally;
    594 otherwise return -SIG, where SIG is the signal that killed it. """
    595         return _spawnvef(mode, file, args, env, execvpe)
    596 
    597 if _exists("spawnv"):
    598     # These aren't supplied by the basic Windows code
    599     # but can be easily implemented in Python
    600 
    601     def spawnl(mode, file, *args):
    602         """spawnl(mode, file, *args) -> integer
    603 
    604 Execute file with arguments from args in a subprocess.
    605 If mode == P_NOWAIT return the pid of the process.
    606 If mode == P_WAIT return the process's exit code if it exits normally;
    607 otherwise return -SIG, where SIG is the signal that killed it. """
    608         return spawnv(mode, file, args)
    609 
    610     def spawnle(mode, file, *args):
    611         """spawnle(mode, file, *args, env) -> integer
    612 
    613 Execute file with arguments from args in a subprocess with the
    614 supplied environment.
    615 If mode == P_NOWAIT return the pid of the process.
    616 If mode == P_WAIT return the process's exit code if it exits normally;
    617 otherwise return -SIG, where SIG is the signal that killed it. """
    618         env = args[-1]
    619         return spawnve(mode, file, args[:-1], env)
    620 
    621 
    622     __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",])
    623 
    624 
    625 if _exists("spawnvp"):
    626     # At the moment, Windows doesn't implement spawnvp[e],
    627     # so it won't have spawnlp[e] either.
    628     def spawnlp(mode, file, *args):
    629         """spawnlp(mode, file, *args) -> integer
    630 
    631 Execute file (which is looked for along $PATH) with arguments from
    632 args in a subprocess with the supplied environment.
    633 If mode == P_NOWAIT return the pid of the process.
    634 If mode == P_WAIT return the process's exit code if it exits normally;
    635 otherwise return -SIG, where SIG is the signal that killed it. """
    636         return spawnvp(mode, file, args)
    637 
    638     def spawnlpe(mode, file, *args):
    639         """spawnlpe(mode, file, *args, env) -> integer
    640 
    641 Execute file (which is looked for along $PATH) with arguments from
    642 args in a subprocess with the supplied environment.
    643 If mode == P_NOWAIT return the pid of the process.
    644 If mode == P_WAIT return the process's exit code if it exits normally;
    645 otherwise return -SIG, where SIG is the signal that killed it. """
    646         env = args[-1]
    647         return spawnvpe(mode, file, args[:-1], env)
    648 
    649 
    650     __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",])
    651 
    652 
    653 # Supply popen2 etc. (for Unix)
    654 if _exists("fork"):
    655     if not _exists("popen2"):
    656         def popen2(cmd, mode="t", bufsize=-1):
    657             """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
    658             may be a sequence, in which case arguments will be passed directly to
    659             the program without shell intervention (as with os.spawnv()).  If 'cmd'
    660             is a string it will be passed to the shell (as with os.system()). If
    661             'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
    662             file objects (child_stdin, child_stdout) are returned."""
    663             import warnings
    664             msg = "os.popen2 is deprecated.  Use the subprocess module."
    665             warnings.warn(msg, DeprecationWarning, stacklevel=2)
    666 
    667             import subprocess
    668             PIPE = subprocess.PIPE
    669             p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
    670                                  bufsize=bufsize, stdin=PIPE, stdout=PIPE,
    671                                  close_fds=True)
    672             return p.stdin, p.stdout
    673         __all__.append("popen2")
    674 
    675     if not _exists("popen3"):
    676         def popen3(cmd, mode="t", bufsize=-1):
    677             """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
    678             may be a sequence, in which case arguments will be passed directly to
    679             the program without shell intervention (as with os.spawnv()).  If 'cmd'
    680             is a string it will be passed to the shell (as with os.system()). If
    681             'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
    682             file objects (child_stdin, child_stdout, child_stderr) are returned."""
    683             import warnings
    684             msg = "os.popen3 is deprecated.  Use the subprocess module."
    685             warnings.warn(msg, DeprecationWarning, stacklevel=2)
    686 
    687             import subprocess
    688             PIPE = subprocess.PIPE
    689             p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
    690                                  bufsize=bufsize, stdin=PIPE, stdout=PIPE,
    691                                  stderr=PIPE, close_fds=True)
    692             return p.stdin, p.stdout, p.stderr
    693         __all__.append("popen3")
    694 
    695     if not _exists("popen4"):
    696         def popen4(cmd, mode="t", bufsize=-1):
    697             """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
    698             may be a sequence, in which case arguments will be passed directly to
    699             the program without shell intervention (as with os.spawnv()).  If 'cmd'
    700             is a string it will be passed to the shell (as with os.system()). If
    701             'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
    702             file objects (child_stdin, child_stdout_stderr) are returned."""
    703             import warnings
    704             msg = "os.popen4 is deprecated.  Use the subprocess module."
    705             warnings.warn(msg, DeprecationWarning, stacklevel=2)
    706 
    707             import subprocess
    708             PIPE = subprocess.PIPE
    709             p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
    710                                  bufsize=bufsize, stdin=PIPE, stdout=PIPE,
    711                                  stderr=subprocess.STDOUT, close_fds=True)
    712             return p.stdin, p.stdout
    713         __all__.append("popen4")
    714 
    715 import copy_reg as _copy_reg
    716 
    717 def _make_stat_result(tup, dict):
    718     return stat_result(tup, dict)
    719 
    720 def _pickle_stat_result(sr):
    721     (type, args) = sr.__reduce__()
    722     return (_make_stat_result, args)
    723 
    724 try:
    725     _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
    726 except NameError: # stat_result may not exist
    727     pass
    728 
    729 def _make_statvfs_result(tup, dict):
    730     return statvfs_result(tup, dict)
    731 
    732 def _pickle_statvfs_result(sr):
    733     (type, args) = sr.__reduce__()
    734     return (_make_statvfs_result, args)
    735 
    736 try:
    737     _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
    738                      _make_statvfs_result)
    739 except NameError: # statvfs_result may not exist
    740     pass
    741