Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2017-08-05T19:32:48+02:00Les derniers messages parus sur le forum de Zeste de Savoir.Des arguments positionnels avancés avec argsparse, message #1588702017-08-05T19:32:48+02:00motet-a/@motet-ahttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158870<blockquote>
<p>Ah par contre docopt ne semble plus maintenu : dernier commit datant de août 2016, 172 tickets et 28 PR en attente.</p>
</blockquote>
<p>Les versions d’argparse (spécialement celles de Python 2.7) ne sont pas plus maintenues que docopt : elles sont figées avec les versions de Python. Un projet comme ça <a href="https://github.com/docopt/docopt/issues/371#issuecomment-295928562">n’a pas spécialement besoin de maintenance</a> — et si des programmes connus comme docker-compose l’utilisent, c’est que c’est quand-même une valeur sûre <img alt=":D" src="/static/smileys/heureux.png"></p>Des arguments positionnels avancés avec argsparse, message #1588532017-08-05T15:53:47+02:00Roipoussiere/@Roipoussierehttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158853<p>Ah par contre docopt ne semble plus maintenu : dernier commit datant de août 2016, 172 tickets et 28 PR en attente.</p>
<p>Et comme je viens de tomber sur des erreurs super chelou (qui ne seront pas corrigées) et que j’ai pas envie de m’arracher les cheveux plus longtemps, je vais prendre la solution d’Entwane : back to argparse <img alt=":)" src="/static/smileys/smile.png"></p>
<p>C’est dommage ça avait l’air bien pratique, notamment pour la lisibilité du code…</p>Des arguments positionnels avancés avec argsparse, message #1587752017-08-04T20:14:41+02:00entwanne/@entwannehttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158775<p>Salut,</p>
<p>Il m’est arrivé récemment de réaliser un programme du genre, donc je vais pouvoir te renseigner.
J’ai fait cela avec <code>argparse</code>, parce que c’est intégré de base, et parce que je ne suis pas fan des autres solutions (notamment celles comme <code>docopt</code> qui parsent des <em>docstrings</em>)</p>
<p>Premièrement, <code>argparse</code> <a href="https://docs.python.org/3/library/argparse.html#sub-commands">contient aussi des <em>subparsers</em></a>, qui sont tout indiqués pour cela.</p>
<p>Tu crées un ensemble de <em>subparsers</em> avec la méthode <code>add_subparsers</code>. L’objet retourné possède ensuite une méthode <code>add_parser</code> que tu peux appeler à plusieurs reprises pour ajouter tes <em>subparsers</em>.</p>
<p><code>add_parser</code> retourne un objet <code>ArgumentParser</code>, identique à l’objet initial donc, que tu peux manipuler pour ajouter des options et autres.</p>
<p>Pour te donner un exemple, voici un squelette de gestion d’arguments qui serait destiné à récupérer/modifier des entrées de dictionnaire dans un fichier <em>JSON</em>.</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="kn">import</span> <span class="nn">argparse</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="k">def</span> <span class="nf">cmd_list</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">args</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">cmd_get</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'GET'</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">cmd_set</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'SET'</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
<span class="o">...</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s1">'Store'</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'--db'</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s1">'db.json'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">'database file'</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s1">'db_file'</span><span class="p">)</span>
<span class="n">subparsers</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_subparsers</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s1">'commands'</span><span class="p">,</span>
<span class="n">description</span><span class="o">=</span><span class="s1">'Command to execute'</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s1">'<command>'</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s1">'command_name'</span><span class="p">)</span>
<span class="n">subparsers</span><span class="o">.</span><span class="n">required</span> <span class="o">=</span> <span class="bp">True</span>
<span class="n">parser_list</span> <span class="o">=</span> <span class="n">subparsers</span><span class="o">.</span><span class="n">add_parser</span><span class="p">(</span><span class="s1">'list'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">'list all entries'</span><span class="p">)</span>
<span class="n">parser_list</span><span class="o">.</span><span class="n">set_defaults</span><span class="p">(</span><span class="n">command</span><span class="o">=</span><span class="n">cmd_list</span><span class="p">)</span>
<span class="n">parser_get</span> <span class="o">=</span> <span class="n">subparsers</span><span class="o">.</span><span class="n">add_parser</span><span class="p">(</span><span class="s1">'get'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">'get value for an entry'</span><span class="p">)</span>
<span class="n">parser_get</span><span class="o">.</span><span class="n">set_defaults</span><span class="p">(</span><span class="n">command</span><span class="o">=</span><span class="n">cmd_get</span><span class="p">)</span>
<span class="n">parser_get</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'key'</span><span class="p">)</span>
<span class="n">parser_set</span> <span class="o">=</span> <span class="n">subparsers</span><span class="o">.</span><span class="n">add_parser</span><span class="p">(</span><span class="s1">'set'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">'set a new value'</span><span class="p">)</span>
<span class="n">parser_set</span><span class="o">.</span><span class="n">set_defaults</span><span class="p">(</span><span class="n">command</span><span class="o">=</span><span class="n">cmd_set</span><span class="p">)</span>
<span class="n">parser_set</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'key'</span><span class="p">)</span>
<span class="n">parser_set</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'value'</span><span class="p">,</span> <span class="n">nargs</span><span class="o">=</span><span class="s1">'?'</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">db_file</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">args</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">except</span> <span class="n">FileNotFoundError</span><span class="p">:</span>
<span class="n">args</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">args</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<p>Et un aperçu de l’aide produite :</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16</pre></div></td><td class="code"><div class="codehilite"><pre><span></span>% ./args.py -h
usage: args.py [-h] [--db DB_FILE] <command> ...
Store
optional arguments:
-h, --help show this help message and exit
--db DB_FILE database file
commands:
Command to execute
<command>
list list all entries
get get value for an entry
set set a new value
</pre></div>
</td></tr></table></div>Des arguments positionnels avancés avec argsparse, message #1587682017-08-04T18:09:00+02:00Roipoussiere/@Roipoussierehttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158768<p>Merci à vous 2 !</p>
<p>Rezemika ton code semble super chouette, mais du coup je vais plutôt partir sur docopt qui m’a l’air franchement bien sympa.</p>
<p>Et lol : <a href="https://github.com/docopt/docopt/blob/master/examples/git/git.py">git</a>, <a href="https://github.com/docopt/docopt/blob/master/examples/git/git_add.py">git add</a> et <a href="https://github.com/docopt/docopt/blob/master/examples/git/git_commit.py">git commit</a> sont justement proposé en exemple pour les "subparser" ! <img alt=":D" src="/static/smileys/heureux.png"></p>
<p>Et puis j’aime bien la façon dont ça fonctionne, en parsant les docstrings.</p>Des arguments positionnels avancés avec argsparse, message #1587672017-08-04T17:47:34+02:00motet-a/@motet-ahttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158767<p>Salut,</p>
<p>Je pense que si tu peux utiliser une dépendance externe, il vaut mieux que tu regardes du côté de <a href="https://pypi.python.org/pypi/docopt">docopt</a> ou d’une alternative à argparse. Pour moi, argparse est idéal pour les petits scripts légers (vu que c’est intégré de base à Python 2 et 3), mais pour les choses avancées je trouve ça assez limité.</p>
<p>Un bon exemple assez complet utilisant docopt est <a href="https://github.com/docker/compose/blob/master/compose/cli/main.py">docker-compose</a>.</p>
<p>EDIT :</p>
<p>Après, si tu fais ça pour le fun, tu peux utiliser du fait maison comme l’a proposé rezemika.</p>Des arguments positionnels avancés avec argsparse, message #1587662017-08-04T17:27:43+02:00rezemika/@rezemikahttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158766<p>Salut !</p>
<p>J’ai justement ébauché il y a peu un parser dans ce genre (mais sans argparse) pour un gestionnaire de contacts. Voilà le gros du code, si tu veux t’en inspirer. <img alt=":)" src="/static/smileys/smile.png"></p>
<h3>Fichier "main.py"</h3>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">cmd_ls</span>
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">cmd_add</span>
<span class="n">available_commands</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"ls"</span><span class="p">:</span> <span class="n">cmd_ls</span><span class="p">,</span>
<span class="s2">"add"</span><span class="p">:</span> <span class="n">cmd_add</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">def</span> <span class="nf">command_parser</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="n">parsed_args</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"commands"</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">"options"</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">"var_options"</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">"sysargv"</span><span class="p">:</span> <span class="n">args</span><span class="p">}</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
<span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="k">if</span> <span class="n">arg</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'--'</span><span class="p">):</span>
<span class="k">if</span> <span class="s1">'='</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">:</span>
<span class="n">parsed_args</span><span class="p">[</span><span class="s2">"options"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="mi">2</span><span class="p">:])</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">option</span><span class="p">,</span> <span class="n">var</span> <span class="o">=</span> <span class="n">arg</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'='</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">parsed_args</span><span class="p">[</span><span class="s2">"var_options"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">option</span><span class="p">[</span><span class="mi">2</span><span class="p">:],</span> <span class="n">var</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">parsed_args</span><span class="p">[</span><span class="s2">"commands"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
<span class="k">return</span> <span class="n">parsed_args</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">command_parser</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span>
<span class="c1"># Prints the main help if there is no command.</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="s2">"commands"</span><span class="p">])</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="s2">"help"</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="s2">"options"</span><span class="p">]:</span>
<span class="k">print</span><span class="p">(</span><span class="n">main_help</span><span class="p">)</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># Prints the script's version.</span>
<span class="k">if</span> <span class="s2">"version"</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="s2">"options"</span><span class="p">]:</span>
<span class="k">print</span><span class="p">(</span><span class="s2">"PyContacts: v{}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">__version__</span><span class="p">))</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">command</span> <span class="o">=</span> <span class="n">available_commands</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="s2">"commands"</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
<span class="n">command</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<h3>Fichier "commands.py"</h3>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="k">def</span> <span class="nf">get_var_option</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">arg</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s1">''</span><span class="p">):</span>
<span class="n">output</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">if</span> <span class="n">args</span><span class="p">[</span><span class="s2">"var_options"</span><span class="p">]:</span>
<span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="n">couple</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">couple</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="s2">"var_options"</span><span class="p">]</span> <span class="k">if</span> <span class="n">couple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">arg</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">output</span><span class="p">:</span>
<span class="k">return</span> <span class="n">default</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">output</span>
<span class="k">class</span> <span class="nc">Command</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">if</span> <span class="s2">"help"</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="s2">"options"</span><span class="p">]:</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__doc__</span><span class="p">)</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">handle</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">Cancelling."</span><span class="p">))</span>
<span class="k">return</span>
<span class="k">return</span>
<span class="k">def</span> <span class="nf">error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">message</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">"Error: {}"</span><span class="p">)</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">message</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">"Error: invalid command."</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">"Type 'PRGM CMD --help' to get the help for this command."</span><span class="p">))</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">cmd_ls</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Prints the list of all contacts.</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">if</span> <span class="s2">"all"</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="s2">"options"</span><span class="p">]:</span>
<span class="n">print_all</span> <span class="o">=</span> <span class="bp">True</span>
<span class="c1"># Traitement de la commande.</span>
<span class="k">class</span> <span class="nc">cmd_add</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Allows to add a contact or a category of contacts.</span>
<span class="sd"> add contact</span>
<span class="sd"> Prompts some questions to add a contact.</span>
<span class="sd"> add category</span>
<span class="sd"> Use an option --name=NAME or ask for a category name</span>
<span class="sd"> and creates it.</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="s2">"commands"</span><span class="p">])</span> <span class="o"><</span> <span class="mi">2</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">"You must specify what to add (contact / category)."</span><span class="p">))</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">x</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="s2">"commands"</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"contact"</span><span class="p">,</span> <span class="s2">"category"</span><span class="p">]):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">()</span>
<span class="k">if</span> <span class="n">args</span><span class="p">[</span><span class="s2">"commands"</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"contact"</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_contact</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_category</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></div>
<p>Voilà en gros comment ça marche :</p>
<ul>
<li>Quand tu appelles le programme, la fonction "command_parser()" renvoie un dictionnaire avec toutes les options de ta commande. Par exemple, si tu fait "git commit –ammend –verbose=1", le dictionnaire sera : <em>{"commands": [’commit’], "options": [’ammend’], "var_options": [(’verbose’, 1)], "sysargv": (la variable sys.argv)}</em>.</li>
<li>Ensuite, il voit si tu appelles juste "–help" (sans rien d’autre) ou "–version" et il affiche sa variable <strong>doc</strong> ou sa variable <strong>version</strong> et il quitte.</li>
<li>Sinon, il récupère la première commande et va la chercher dans le dictionnaire des commandes possibles (<em>available_commands</em>) puis l’exécute.</li>
<li>Chaque commande est une classe qui hérite de la classe "Command", qui gère les erreurs et les appels à l’option "–help". Sa fonction <strong>init</strong> appelle la fonction handle() de la classe de la commande, qui elle, fait tout le boulot. Si tu appelles "–help", c’est la variable <strong>doc</strong> de la classe de la commande qui est affichée.</li>
</ul>
<p>Si ça peut t’être utile… <img alt=";)" src="/static/smileys/clin.png"></p>Des arguments positionnels avancés avec argsparse, message #1587642017-08-04T17:07:08+02:00Roipoussiere/@Roipoussierehttps://zestedesavoir.com/forums/sujet/9082/des-arguments-positionnels-avances-avec-argsparse/?page=1#p158764<p>Bonjour !</p>
<p>Je viens de sortir de ma grotte et en face de moi j’ai trouvé un clavier, du coup j’ai attaqué un petit projet histoire de me dérouiller les mains. <img alt=":)" src="/static/smileys/smile.png"> Je souhaite faire un programme en ligne de commande qui fonctionne avec des <em>actions</em> : c’est à dire comme le programme Git :</p>
<ul>
<li><code>git add</code> est une action ;</li>
<li><code>git commit</code> est une autre action ;</li>
<li><code>git commit --amend</code> est la même action avec un paramètre ;</li>
<li><code>git add --amend</code> n’a pas de sens et renvoie une erreur.</li>
</ul>
<p>Le seul truc que j’ai trouvé qui se rapprocherait de ce que j’aimerais faire est (pour reprendre l’exemple de git) :</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="kn">import</span> <span class="nn">argparse</span>
<span class="k">def</span> <span class="nf">commit</span><span class="p">(</span><span class="n">is_amend</span><span class="p">):</span>
<span class="p">[</span><span class="o">...</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">():</span>
<span class="p">[</span><span class="o">...</span><span class="p">]</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
<span class="n">p</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'command'</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="p">[</span><span class="s1">'commit'</span><span class="p">,</span> <span class="s1">'add'</span><span class="p">],</span> <span class="n">help</span><span class="o">=</span><span class="s1">'The action to execute'</span><span class="p">)</span>
<span class="n">p</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'--amend'</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s1">'store_true'</span><span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">command</span> <span class="o">==</span> <span class="s1">'commit'</span><span class="p">:</span>
<span class="n">commit</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">amend</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">args</span><span class="o">.</span><span class="n">command</span> <span class="o">==</span> <span class="s1">'add'</span><span class="p">:</span>
<span class="n">add</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
<p>Mais en fait ça ne me convient pas du tout :</p>
<ul>
<li>L’aide du programme Git affiche en détail toutes les actions possible avec leur signification, tandis que mon programme affiche juste: *positional arguments: <code>{commit,add} The action to execute</code>, ce qui est un peu succint ;</li>
<li>on ne peut pas avoir une aide dédiée à <em>une</em> action, du style <code>git.py commit -h</code>) ;</li>
<li><code>git.py add --amend</code> (ou même <code>git.py --amend</code>) est valide ici, alors qu’il ne devrait l’être qu’avec l’action <code>commit</code>.</li>
</ul>
<p><strong>Bref, l’idée serait d’avoir un parseur général et un parseur pour chaque action.</strong></p>
<p>J’ai farfouillé dans <a href="https://docs.python.org/3.6/library/argparse.html">la doc de argparse</a> et je n’ai rien trouvé qui correspondait vraiment à ce fonctionnement…</p>
<p>Il faut que je recode un truc pour ça où il y a un truc qui existe déjà, voir c’est possible avec argparse ?</p>
<p>Merci <img alt=":)" src="/static/smileys/smile.png"></p>