Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Analyse ligne de commandes

0 views
Skip to first unread message

Pierre Maurette

unread,
Sep 21, 2009, 5:41:35 AM9/21/09
to
Bonjour,

Je cherche ᅵ rᅵutiliser l'existant concernant l'analyse primaire de la
ligne de commandes, en fait le dᅵcoupage. J'ai une ligne de commande
sous forme de chaᅵne de caractᅵres:
r'rsync -a "pierre@UBUNTU64-V:/home/pierre maurette/SITES/"'
et je veux en tirer une liste de chaᅵnes. Le problᅵme ᅵvidemment se
situe au niveau des arguments contenant des espaces. C'est encore assez
facile de traiter les '"', mais si on ajoute les ᅵchappements et
peut-ᅵtre d'autres subtilitᅵs, ᅵa risque de se compliquer. D'oᅵ ma
volontᅵ d'utiliser ce qui existe.
Je n'ai pas trouvᅵ dans Python oᅵ est fait ce dᅵcoupage. En fait, je ne
sais pas si c'est fait par Python ou par l'OS. Pour un exᅵcutable
compilᅵ, c'est l'OS.
Pour l'instant, j'utilise une mᅵthode un peu bourri, je lance une
instance de Python avec la ligne de commandes et je rᅵcupᅵre sys.argv.
J4ai survolᅵ optparse (que j'utilise) et getopt (que je n'utilise pas)
mais je n'ai rien vu, il semble que ces modules se situent en aval de
l'analyse primaire.
Y a-t-il une fonction qui me ferait ᅵa simplement ? Je me suis rᅵsolu ᅵ
poser la question parce que j'ai constatᅵ qu'en Python je passais pas
mal de temps ᅵ rᅵinventer la roue, alors qu'il existe beaucoup de
ressources que j'ignore, ou pire que j'ai oubliᅵ aprᅵs les avoir
utilisᅵes une fois grᅵce ᅵ Google.

Pour info mon code de test avec la mᅵthode bourrin (le but de ce petit
outil est de gᅵrer une ruche de commandes chiantes ᅵ mᅵmoriser et ᅵ
saisir):

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys, subprocess

commandes = [
[ r'Synchroniser D:/SITES vers @UBUNTU64-V'
, r'rsync -a --delete /cygdrive/d/SITES/
pierre@UBUNTU64-V:/home/pierre/SITES/']
, [ r'Synchroniser D:/SITES vers @UBUNTU64-V'
, r'rsync -a --delete /cygdrive/d/SITES/
"pierre@UBUNTU64-V:/home/pierre maurette/SITES/"']
, [ r'Synchroniser D:/SITES vers @UBUNTU64-V'
, r'rsync -a --delete /cygdrive/d/SITES/
"pierre@UBUNTU64-V:/home/pierre/SITES/"']
]

def getShellCommandResult(command=['ls']):
p = subprocess.Popen(args=command
, stdin=subprocess.PIPE
, stdout=subprocess.PIPE
, stderr=subprocess.STDOUT)
pw = p.wait()
return pw, p.stdout.readlines()


basecmd = 'python -c "import sys\nfor _ in sys.argv[1:]: print _" '

for num, item in enumerate(commandes):
print '%i\t%s' % (num, item[0])
pw, result = getShellCommandResult(basecmd + item[1])
for item in result:
print item.strip()

pw, result = getShellCommandResult(commandes[2][1])
if pw != 0:
print '[!!! error %d]' % pw
if len(result) > 0:
print ''.join(result)

--
Pierre Maurette


Alain Ketterlin

unread,
Sep 21, 2009, 7:24:12 AM9/21/09
to
Pierre Maurette <maurett...@wanadoo.fr> writes:

> Je cherche à réutiliser l'existant concernant l'analyse primaire de la
> ligne de commandes, en fait le découpage. J'ai une ligne de commande
> sous forme de chaîne de caractères:


> r'rsync -a "pierre@UBUNTU64-V:/home/pierre maurette/SITES/"'

> et je veux en tirer une liste de chaînes. Le problème évidemment se


> situe au niveau des arguments contenant des espaces. C'est encore

> assez facile de traiter les '"', mais si on ajoute les échappements et
> peut-être d'autres subtilités, ça risque de se compliquer. D'où ma
> volonté d'utiliser ce qui existe.
>
> Je n'ai pas trouvé dans Python où est fait ce découpage. En fait, je
> ne sais pas si c'est fait par Python ou par l'OS. Pour un exécutable
> compilé, c'est l'OS.

Pas tout à fait. C'est le shell qui fait le découpage. Le système ne
voit que les mots fournis aux variantes de execve().

> Pour l'instant, j'utilise une méthode un peu bourri, je lance une
> instance de Python avec la ligne de commandes et je récupère sys.argv.

Ce n'est pas forcément une mauvaise solution. En tout cas elle est
portable.

> Y a-t-il une fonction qui me ferait ça simplement ?

En C/POSIX il y a wordexp(). Je ne sais pas si c'est visible en python,
ça ne semble pas faire partie de la lib (mais je n'ai pas beaucoup
cherché).

-- Alain.

Pierre Maurette

unread,
Sep 21, 2009, 7:58:04 AM9/21/09
to
Alain Ketterlin, le 21/09/2009 a ᅵcrit :
> Pierre Maurette <maurett...@wanadoo.fr> writes:
>
>> Je cherche ᅵ rᅵutiliser l'existant concernant l'analyse primaire de la
>> ligne de commandes, en fait le dᅵcoupage. J'ai une ligne de commande

>> sous forme de chaᅵne de caractᅵres:
>> r'rsync -a "pierre@UBUNTU64-V:/home/pierre maurette/SITES/"'
>> et je veux en tirer une liste de chaᅵnes. Le problᅵme ᅵvidemment se

>> situe au niveau des arguments contenant des espaces. C'est encore
>> assez facile de traiter les '"', mais si on ajoute les ᅵchappements et
>> peut-ᅵtre d'autres subtilitᅵs, ᅵa risque de se compliquer. D'oᅵ ma
>> volontᅵ d'utiliser ce qui existe.
>>
>> Je n'ai pas trouvᅵ dans Python oᅵ est fait ce dᅵcoupage. En fait, je
>> ne sais pas si c'est fait par Python ou par l'OS. Pour un exᅵcutable
>> compilᅵ, c'est l'OS.
>
> Pas tout ᅵ fait. C'est le shell qui fait le dᅵcoupage. Le systᅵme ne

> voit que les mots fournis aux variantes de execve().

Oui, en fait en ᅵcrivant OS, je pensais au shell. Disons d'une faᅵon
gᅵnᅵrale le loader, le chargeur, l'interprᅵteur de commande. Et
maintenant je vois bien que ce n'est pas fondamentalement diffᅵrent
pour un script Python. C'est l'exᅵcutable python ou python.exe qui
reᅵoit la premiᅵre salve dont il retire le premier ᅵlᅵment, etc.

>> Pour l'instant, j'utilise une mᅵthode un peu bourri, je lance une
>> instance de Python avec la ligne de commandes et je rᅵcupᅵre sys.argv.
>
> Ce n'est pas forcᅵment une mauvaise solution. En tout cas elle est
> portable.

La portabilitᅵ est une contrainte. Je vais donc pour le moment
continuer avec cette mᅵthode en attendant d'autres propositions
ᅵventuelles.

>> Y a-t-il une fonction qui me ferait ᅵa simplement ?


>
> En C/POSIX il y a wordexp(). Je ne sais pas si c'est visible en python,

> ᅵa ne semble pas faire partie de la lib (mais je n'ai pas beaucoup
> cherchᅵ).

On doit pouvoir prendre le source de wordexp() peut-ᅵtre plus clair
qu'un document normatif et en dᅵcouler une fonction Python, mais le jeu
n'en vaut pas la chandelle pour l'instant.

Merci et bonne journᅵe...

--
Pierre Maurette


Alain BARTHE

unread,
Sep 21, 2009, 8:41:45 AM9/21/09
to
Pierre Maurette a ᅵcrit :

Il me semble que tu devrais regarder :
- le module getopt pour la dᅵcomposition des divers arguments,
- le module urlparse pour dᅵcomposer les sous-parties de l'arguments de
rsync dᅵcrivant ton url.

Pierre Maurette

unread,
Sep 21, 2009, 8:54:03 AM9/21/09
to
Alain BARTHE, le 21/09/2009 a ᅵcrit :

[...]

> Il me semble que tu devrais regarder :
> - le module getopt pour la dᅵcomposition des divers arguments,
> - le module urlparse pour dᅵcomposer les sous-parties de l'arguments de rsync
> dᅵcrivant ton url.

Merci. Je suis toujours trop verbeux quand je pose une question, je
n'ai pas ᅵtᅵ clair. J'ai survolᅵ getopt, il me semble bien que ᅵa vient
en aval du dᅵcoupage primaire. Je jetterai un oeil ᅵ urlparse. Mais
rsync n'est qu'un exemple, ce que je veux c'est ᅵ partir d'une chaᅵne
par exemple copiᅵe-collᅵe depuis une console, obtenir le dᅵcoupage, le
mᅵme que celui que fait le shell, pour renvoyer cette liste dans
subprocessPopen(). D'ailleurs ᅵa fonctionne correctement avec mon
bidule bourrin.
Je pourrais bien entendu envoyer la chaᅵne complᅵte dans os.system() ou
peut-ᅵtre subprocess.call(), mais ᅵa ne fait pas ce que je veux. Et il
me semble qu'envoyer une chaᅵne unique dans subprocess.Popen() ne
fonctionne pas, ou pas toujours. Mais je me trompe peut-ᅵtre ᅵ ce
niveau.

--
Pierre Maurette


Alain BARTHE

unread,
Sep 21, 2009, 10:08:59 AM9/21/09
to
Pierre Maurette a ᅵcrit :

Dᅵsolᅵ, c'est ma fautre : j'avais lu ton premier mail un peu rapidement,
et surtout sans lire l'exemple.

Il m'est arrivᅵ par contre d'utiliser le os.popen() sans trop de
problᅵmes. Je n'ai pas encore utilisᅵ le module subprocess mais on doit
y retrouver les mᅵmes fonctionnalitᅵs, avec une meilleure portabilitᅵ
que os.popen()

Bonne continuation dans tes recherche.


Pierre Maurette

unread,
Sep 22, 2009, 10:33:56 AM9/22/09
to
Je fais un retour final en remerciant Alain et Alain ;-) pour leurs
rᅵponses.
Je vais en rester au code tel qu'il est et qui fonctionne. D'abord, je
me suis ᅵgarᅵ, je savais trᅵs bien que l'analyse brutale de la ligne de
commandes (c'est ᅵ dire chaine -> liste, ou char*[] en fait) est faite
par le shell / OS / loader / etc. Donc il n'y a pas de raison que cette
analyse fasse l'objet d'une fonction de Python. Ensuite les solutions
alternatives:
- Parser moi-mᅵme. C'est pas si simple, je ne sais pas s'il y a des
diffᅵrences entre Posix et Windows, etc. Donc laisser le parsing ᅵ l'OS
est une solution raisonnable.
- Utiliser la chaine sans la saucissonner. ᅵa ne m'arrange pas, ce
n'est pas le choix initial. J'ai besoin de Popen() pour rᅵcupᅵrer la
sortie, etc.
- Entrer en donnᅵes non pas la chaine mais la liste. ᅵa fonctionne,
mais j'utilise beaucoup la modification directe du code, et je cherche
ᅵ diminuer ce genre de contrainte. En fait je veux pouvoir copier -
coller par exemple une commande vers le source ou un .ini

Puisque l'activitᅵ sur le groupe est absolument frᅵnᅵtique, je soumets
un autre truc du mᅵme genre. Le contexte: c'est dans un fichier
SConstruct pour scons. Le SConstruct est portable, mais ce bout ne
concerne que Windows, par dᅵfinition. Il s'agit de rᅵcupᅵrer
l'environnement issu d'un ?????.bat, qui positionne des variables
d'environnement. Le bout de code qui suit est un peu compact, voire
abscons. C'est pour ᅵviter deux fichiers satellites, un .bat et un .py,
mais ᅵa marche en appelant le .bat qui appelle le .py. Le code:

# -*- coding: utf-8 -*-

import os, pickle, subprocess

batName = r'D:\Program Files (x86)\Microsoft Visual Studio
9.0\VC\vcvarsall.bat'
arch = 'x86_amd64'
subprocess.call("cmd /C @call \"%s\" %s & @call python -c \"import os,
pickle; pickle.dump(os.environ, open('_', 'wb'))\"" %(batName, arch))
env = pickle.load(open('_', 'rb'))
print env['VSINSTALLDIR'] #test
print env['VCINSTALLDIR'] #test
os.system('del _')

La question - non vitale - est de savoir s'il y a mins tordu, et en
particulier si on peut ᅵviter le fichier temporaire.

Bonne fin de journᅵe.

--
Pierre Maurette


Pierre Maurette

unread,
Sep 22, 2009, 10:34:59 AM9/22/09
to
(supersedes <mn.b3e17d99f...@wanadoo.fr>)

# -*- coding: utf-8 -*-
import os, pickle, subprocess

batName = r'D:\Program Files (x86)\Microsoft Visual Studio
9.0\VC\vcvarsall.bat'
arch = 'x86_amd64'
subprocess.call("cmd /C @call \"%s\" %s & @call python -c \"import os,
pickle; pickle.dump(os.environ, open('_', 'wb'))\"" %(batName, arch))
env = pickle.load(open('_', 'rb'))
print env['VSINSTALLDIR'] #test
print env['VCINSTALLDIR'] #test
os.system('del _')

La question - non vitale - est de savoir s'il y a moins tordu, et en

Jogo

unread,
Sep 22, 2009, 10:38:17 AM9/22/09
to
Salut,

Je suis vraiment nouveau en Python, et j'avoue ne pas avoir lu ton
script avec tout l'attention qu'il aurait fallu. Mais pourquoi
n'utilises-tu pas le module shlex et sa fonction split, en standart
depuis la version 2.3 ?

--
Les conflits non rᅵsolus se rᅵglent devant le juge, une personne qui
n'est ni juge ni partie.
-+- B in GNU : Parti de lᅵ, tu ne peux pas juger. -+-

Pierre Maurette

unread,
Sep 22, 2009, 11:10:29 AM9/22/09
to
Jogo, le 22/09/2009 a ᅵcrit :

> Salut,
>
> Je suis vraiment nouveau en Python, et j'avoue ne pas avoir lu ton
> script avec tout l'attention qu'il aurait fallu. Mais pourquoi
> n'utilises-tu pas le module shlex et sa fonction split, en standart
> depuis la version 2.3 ?

Fondamentalement, parce que je ne le connaissais pas ;-) Mais je vous
remercie et vous garantis que sous un ou deux jours j'aurai un petit
test_shlex.py sous mon dossier /Thematique/ pour tester ce truc qui me
semble intᅵressant.
A+

--
Pierre Maurette


chris

unread,
Sep 22, 2009, 12:09:20 PM9/22/09
to
Pierre Maurette a ᅵcrit :

oui il me semble que shlex est bien car il tiens compte des pieges avec
les guillemets

A+
chris

0 new messages