web-dev-qa-db-fra.com

subprocess.call utilisant une chaîne vs utilisant une liste

J'essaie d'utiliser rsync avec subprocess.call. Curieusement, cela fonctionne si je passe subprocess.call une chaîne, mais cela ne fonctionnera pas avec une liste (ala, doc de Python).

appeler sp.call avec une chaîne:

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

appeler sp.call avec une liste:

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

Quel est le problème avec la façon dont j'utilise la liste? Comment le résoudriez-vous? J'ai besoin de la liste, car je voudrais utiliser des variables. Bien sûr, je pourrais utiliser:

  sp.call("rsync -av "+Orig+" "+Dest, Shell=True)    

Mais je voudrais comprendre comment subprocess comprend les listes par rapport aux chaînes.

définissant Shell = False et une liste:

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

définissant Shell = False et une chaîne

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
30
Oz123

Les règles de subprocess pour gérer l'argument de commande sont en fait un peu complexes.

De les docs :

args doit être une séquence d'arguments de programme ou bien une seule chaîne. Par défaut, le programme à exécuter est le premier élément de args si args est une séquence. Si args est une chaîne, l'interprétation est dépendante de la plateforme et décrite ci-dessous. Voir les arguments Shell et executable pour des différences supplémentaires par rapport au comportement par défaut. Sauf indication contraire, il est recommandé de passer args comme une séquence .... Si Shell est Vrai, il est recommandé de passer args sous forme de chaîne plutôt que de séquence.

Avec Shell=False:

Sous Unix, si args est une chaîne, la chaîne est interprétée comme le nom ou le chemin du programme à exécuter. Cependant, cela ne peut être fait que si vous ne passez pas d'arguments au programme.

Sous Windows, si args est une séquence, elle sera convertie en chaîne de la manière décrite dans Conversion d'une séquence d'arguments en chaîne sous Windows . Cela est dû au fait que la CreateProcess() sous-jacente fonctionne sur les chaînes.

Avec Shell=True:

Sous Unix avec Shell=True, Le shell par défaut est /bin/sh. Si args est une chaîne, la chaîne spécifie la commande à exécuter via le shell. Cela signifie que la chaîne doit être formatée exactement comme elle le serait lors de la frappe à l'invite du shell. Cela inclut, par exemple, la citation ou la barre oblique inversée des noms de fichiers d'échappement contenant des espaces. Si args est une séquence, le premier élément spécifie la chaîne de commande et tous les éléments supplémentaires seront traités comme des arguments supplémentaires pour le shell lui-même.

Sous Windows avec Shell=True, La variable d'environnement COMSPEC spécifie le shell par défaut. La seule fois où vous devez spécifier Shell=True Sous Windows est lorsque la commande que vous souhaitez exécuter est intégrée au shell (par exemple dir ou copy). Vous n'avez pas besoin de Shell=True Pour exécuter un fichier de commandes ou un exécutable basé sur la console.

(tout l'accent est sur moi)

34
nneonneo