I am trying to use rsync with subprocess.call. Oddly, it works if I pass subprocess.call a string, but it won't work with a list (ala, Python's doc).
In [23]: sp.call("rsync -av content/ writings_raw/", shell=True) sending incremental file list  sent 6236 bytes  received 22 bytes  12516.00 bytes/sec total size is 324710  speedup is 51.89 Out[23]: 0   In [24]: sp.call(["rsync", "-av", "content/", "writings_raw/"], shell=True) rsync  version 3.0.9  protocol version 30 Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others. Web site: http://rsync.samba.org/ Capabilities:     64-bit files, 64-bit inums, 32-bit timestamps, 64-bit long ints,     socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace,     append, ACLs, xattrs, iconv, symtimes  rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are welcome to redistribute it under certain conditions.  See the GNU General Public Licence for details.  rsync is a file transfer program capable of efficient remote update via a fast differencing algorithm.  Usage: rsync [OPTION]... SRC [SRC]... DEST   or   rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST   or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST   or   rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST   or   rsync [OPTION]... [USER@]HOST:SRC [DEST]   or   rsync [OPTION]... [USER@]HOST::SRC [DEST]   or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST] The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect to an rsync daemon, and require SRC or DEST to start with a module name.  Options  -v, --verbose               increase verbosity  -q, --quiet                 suppress non-error messages      --no-motd               suppress daemon-mode MOTD (see manpage caveat) ... snipped....                              repeated: --filter='- .rsync-filter'      --exclude=PATTERN       exclude files matching PATTERN      --blocking-io           use blocking I/O for the remote shell  -4, --ipv4                  prefer IPv4  -6, --ipv6                  prefer IPv6      --version               print version number (-h) --help                  show this help (-h is --help only if used alone) ...snipped ... rsync error: syntax or usage error (code 1) at main.c(1438) [client=3.0.9] Out[24]: 1   What is wrong with how I use the list? How would you fix it? I need the list, because I would like to use variables. Of course I could use:
  sp.call("rsync -av "+Orig+" "+Dest, shell=True)       But I would like to understand how subprocess understands lists vs. strings.
In [36]: sp.call(['rsync', '-av', ORIG, DEST], shell=False) sending incremental file list  sent 6253 bytes  received 23 bytes  12552.00 bytes/sec total size is 324710  speedup is 51.74 Out[36]: 0   In [38]: sp.call("rsync -av"+" "+ORIG+" "+DEST, shell=False) --------------------------------------------------------------------------- OSError                                   Traceback (most recent call last) <ipython-input-38-0d366d3ef8ce> in <module>() ----> 1 sp.call("rsync -av"+" "+ORIG+" "+DEST, shell=False)  /usr/lib/python2.7/subprocess.pyc in call(*popenargs, **kwargs)     491     retcode = call(["ls", "-l"])     492     """ --> 493     return Popen(*popenargs, **kwargs).wait()     494      495   /usr/lib/python2.7/subprocess.pyc in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)     677                             p2cread, p2cwrite,     678                             c2pread, c2pwrite, --> 679                             errread, errwrite)     680      681         if mswindows:  /usr/lib/python2.7/subprocess.pyc in _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)    1257                     if fd is not None:    1258                         os.close(fd) -> 1259                 raise child_exception    1260     1261   OSError: [Errno 2] No such file or directory 
                Popen is more general than subprocess. call . Popen doesn't block, allowing you to interact with the process while it's running, or continue with other things in your Python program. The call to Popen returns a Popen object.
The Python subprocess call() function returns the executed code of the program. If there is no program output, the function will return the code that it executed successfully. It may also raise a CalledProcessError exception.
The subprocess module provides a function named call. This function allows you to call another program, wait for the command to complete and then return the return code.
Popen is nonblocking. call and check_call are blocking. You can make the Popen instance block by calling its wait or communicate method.
subprocess's rules for handling the command argument are actually a bit complex.
From the docs:
argsshould be a sequence of program arguments or else a single string. By default, the program to execute is the first item inargsifargsis a sequence. Ifargsis a string, the interpretation is platform-dependent and described below. See theshellandexecutablearguments for additional differences from the default behavior. Unless otherwise stated, it is recommended to passargsas a sequence.... Ifshellis True, it is recommended to passargsas a string rather than as a sequence.
With shell=False:
On Unix, if
argsis a string, the string is interpreted as the name or path of the program to execute. However, this can only be done if not passing arguments to the program.On Windows, if
argsis a sequence, it will be converted to a string in a manner described in Converting an argument sequence to a string on Windows. This is because the underlyingCreateProcess()operates on strings.
With shell=True:
On Unix with
shell=True, the shell defaults to/bin/sh. Ifargsis a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself.On Windows with
shell=True, theCOMSPECenvironment variable specifies the default shell. The only time you need to specifyshell=Trueon Windows is when the command you wish to execute is built into the shell (e.g.dirorcopy). You do not needshell=Trueto run a batch file or console-based executable.
(all emphasis mine)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With