python 3.1 optparse nargs>1 Fehler

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 18:06

Hallo,

habe hier: http://docs.python.org/release/3.0.1/li ... e-optparse unter "Standard option actions" gelesen:
"If nargs > 1, multiple arguments will be consumed from the command line"
Und wenn ich das mache, bekomme ich einen Fehler:

Code: Alles auswählen

    parser.add_option("-l", "--log", dest="log_file", nargs>1, help="Log file")


./neu.py -c lala -l foo bar
  File "./neu.py", line 16
    parser.add_option("-l", "--log", dest="log_file", nargs>1,
SyntaxError: non-keyword arg after keyword arg
(es gibt einen aehnlichen Faden: http://www.python-forum.de/viewtopic.ph ... se#p176134, der mir allerdings nicht hilft. Das dort beschriebene nargs='*' funktioniert nicht und argparse hab ich fuer python 3.1 nicht gesehen.

Wuerde ich ueber einen hilfreichen Hinweis sehr freuen.

Viele Gruesse,
Torres
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dienstag 18. Oktober 2011, 18:19

Du benutzt `optparse` schlicht falsch. `nargs` muss ein Wert zugewiesen werden. `nargs >1` ist aber ein Ausdruck der nur Sinn macht wenn tatsaechlich ausserhalb ein an `nargs` gebunden ist. Das sind aber Python Grundkenntnisse: `add_option` ist eine ganz normale Methode fuer die die normalen Regeln gelten.

Beispiele fuer die richtige Verwendung gibts auf der von dir verlinkten Seite.
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 18:43

Hallo Cofi,

mit Deiner Antwort hab ich mich jetzt schwer getan, sorry.

aber ich hab es jetzt so:

Code: Alles auswählen

    parser.add_option("-c", "--cfg", dest="config_file",nargs=1,
                      help="config file")
    parser.add_option("-l", "--log", dest="log_file",nargs=0,
                      help="Log file")

    (options, args) = parser.parse_args()
    print(args)
Aufruf:

Code: Alles auswählen

./neu.py -c mytest.cfg -l asd asd asd
['asd', 'asd', 'asd']
dann habe ich alles was "noch uebrig ist" in args versammelt.

Schaut mir aber nicht zufriedenstellend aus.

Gruss,
Torres
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 18:51

torres hat geschrieben:Hallo Cofi,

mit Deiner Antwort hab ich mich jetzt schwer getan, sorry.
Was war denn an der Antwort schwer zu verstehen?
torres hat geschrieben: dann habe ich alles was "noch uebrig ist" in args versammelt.

Schaut mir aber nicht zufriedenstellend aus.
Inwiefern? Genau das war doch zu erwarten! Was hast Du denn selber für ein Ergebnis erwartet? Und was willst Du denn erreichen?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 19:02

Hyperion hat geschrieben:
torres hat geschrieben:Hallo Cofi,

mit Deiner Antwort hab ich mich jetzt schwer getan, sorry.
Was war denn an der Antwort schwer zu verstehen?
wie Du Dich ausgedrueckt hast, das hab ich nicht so richtig hm naja :-)
Hyperion hat geschrieben:
torres hat geschrieben: dann habe ich alles was "noch uebrig ist" in args versammelt.

Schaut mir aber nicht zufriedenstellend aus.
Inwiefern? Genau das war doch zu erwarten! Was hast Du denn selber für ein Ergebnis erwartet? Und was willst Du denn erreichen?
ich hatte mir nicht erwartet, dass ich die Argumente selbst zusammenzaehlen muesste (im Sinne von
festlegen, dass -c nargs=1 und -l nargs=0)

Falls ich folgende Optionen haette, wuerde ich mich schwer tun:
-c <file> -l <log1 log2 ...> -f <f1 f2 ...>
Dann haette ich log1 log2 und 1 f2 anonym in der arg liste
und der einzige Umweg waere dann der, dass die einzelnen argumente kommasepariert geschrieben werden muessten:
-c <file> -l <log1,log2,...> -f <f1,f2,...>

Viele Gruesse,
Torres
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 19:08

Also erst einmal ist `argparse` seit Python 2.6 (oder erst 2.7?) Bestandteil der Standardlib. So auch im 3.xer Zweig: Link. Du hast also nicht genau geguckt ;-)

Zum anderen:
Du musst nargs eine feste Anzahl an Parametern übergeben! Du hast einmal festgelegt, dass Du keinen und einmal, dass Du exakt einen wünscht - wenn Du zwei willst, musst Du eben auch zwei angeben ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 19:20

Hyperion hat geschrieben:Also erst einmal ist `argparse` seit Python 2.6 (oder erst 2.7?) Bestandteil der Standardlib. So auch im 3.xer Zweig: Link. Du hast also nicht genau geguckt ;-)
Also ich habe hier geschaut und dort steht es nicht drin:
http://docs.python.org/release/3.1/library/
(hatte mich auch gewundert, weil ich von 2.6 weiss, dass bei optparse steht, man solle argparse verwenden)
ja, und im argparse gibt es nargs='*'

Was mich dann jetzt wundert ist das:

Code: Alles auswählen

python3.1
Python 3.1.2 (r312:79147, Feb 11 2011, 21:32:43) 
[GCC 4.2.1 20070719  [FreeBSD]] on freebsd8
Type "help", "copyright", "credits" or "license" for more information.
>>> import argparse
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named argparse
>>> 
Hyperion hat geschrieben: Zum anderen:
Du musst nargs eine feste Anzahl an Parametern übergeben! Du hast einmal festgelegt, dass Du keinen und einmal, dass Du exakt einen wünscht - wenn Du zwei willst, musst Du eben auch zwei angeben ;-)
Wobei ich ja nicht zwei sondern >1 wollte, was auch unendlich sein kann.
Das nicht zufriedenstellende an meiner obigen Loesung ist naemlich, dass ich auch
./neu.py -c mytest.cfg -l angeben kann und keinen Fehler bekomme,
den muss ich dann selber abfangen.

Viele Gruesse,
Torres
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 19:28

Oops, sorry, war mein Fehler. Laut Doku ist `argparse` erst seit Python 3.2 dabei; das hängt offenbar mit der parallelen Entwicklung der beiden Stränge zusammen. Da 3.2 aber bereits stable ist, würde ich Dir einfach raten auf 3.2 zu upgraden; dann hätte sich das Problem erledigt.

@Rest: Wieso zum Teufel noch mal schreibst Du nicht einfach mal explizit in Deine Frage rein, dass Du beliebig viele Argumente nach einer Option haben willst? Damit wäre auf Anhieb klar gewesen, dass Du das ohne `argparse` nicht umsetzen kannst.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 19:32

Hyperion hat geschrieben: @Rest: Wieso zum Teufel noch mal schreibst Du nicht einfach mal explizit in Deine Frage rein, dass Du beliebig viele Argumente nach einer Option haben willst? Damit wäre auf Anhieb klar gewesen, dass Du das ohne `argparse` nicht umsetzen kannst.
weil ich meinte, dass das mit >1 schon sehr hinreichend deutlich ausgedrueckt war.

Na wie auch immer, dann werd ich mal 3.2 installieren :-)

Viele Gruesse und vielen Dank Dir!
Torres
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 19:40

torres hat geschrieben: weil ich meinte, dass das mit >1 schon sehr hinreichend deutlich ausgedrueckt war.
Du schriebst das aber ja nicht einfach so, sondern bereits verquickt mit dem Auszug aus einer Doku. zur Erinnerung:
torres hat geschrieben: Hallo,

habe hier: http://docs.python.org/release/3.0.1/li ... e-optparse unter "Standard option actions" gelesen:
"If nargs > 1, multiple arguments will be consumed from the command line"
Und wenn ich das mache, bekomme ich einen Fehler:
Der Bezug hier ist eindeutig; es ging um die Doku! Und dort geht man durchaus von einem fixen Wert aus.

Generell startest Du Deine Frage unglücklich. Wie wäre es denn mal mit einem einleitenden Satz zum Umfeld und welches Problem Du lösen willst? Danach kannst Du dann ja mit Details a la Doku und anderen Threads kommen (letzteres ist übrigens sehr löblich!)

So z.B.:
Hallo,

ich möchte für die Parameterübergabe eines Scriptes beliebig viele Parameter für eine Option definieren können. Ich benutze Python 3.1 und finde mit dem `optparse`-Modul keine Lösung.

In der Doku habe ich folgendes gefunden...
... usw.
Ggf. hätte einfach auch mal eine Demo-Syntax geholfen, die Du erst gegen Ende mal geliefert hast.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 19:53

Okay, versuch ich beim naechsten mal besser zu machen.


Eine kleine Anmerkung hab ich noch, die eigentlich hier nichts mehr verloren hat,
da das Problem ja geloest ist:
Bin in die Ports /usr/ports/lang/python32 und hab dort 3.2 installieren wollen,
was nicht funktionierte:

Code: Alles auswählen

(..)
===>  Installing for python31-3.1.3
===>  Checking if lang/python32 already installed
===>   python31-3.1.3 is already installed
      You may wish to ``make deinstall'' and install this port again
      by ``make reinstall'' to upgrade it properly.
      If you really wish to overwrite the old port of lang/python32
      without deleting it first, set the variable "FORCE_PKG_REGISTER"
      in your environment or the "make install" command line.
*** Error code 1
Stop in /usr/ports/lang/python32.
*** Error code 1
Stop in /usr/ports/lang/python32.
hm? python31-3.1.3? Tja leider enthaelt dieser Port kein Python32, sondern:

Code: Alles auswählen

cat distinfo
SHA256 (python/Python-3.1.3.tgz) = 6311823aeda8be6a7a2b67caaeff48abce6626c9940ba7ed81f9c978666a36bd
SIZE (python/Python-3.1.3.tgz) = 11769584
Schade, jetzt muss ich dann doch mit 3.1 herumöumeln :-/

Viele Gruesse,
Torres
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 20:24

Was benutzt Du denn für ein System?

@Topic: Wieso machst Du es nicht so, wie von lunar im verlinkten Thread vorgeschlagen?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
torres
User
Beiträge: 47
Registriert: Samstag 29. Januar 2011, 13:23

Dienstag 18. Oktober 2011, 20:47

Hyperion hat geschrieben:Was benutzt Du denn für ein System?
FreeBSD
Hyperion hat geschrieben: @Topic: Wieso machst Du es nicht so, wie von lunar im verlinkten Thread vorgeschlagen?
Da steht: von lunar: "Wieso übergibst Du die Eingabedateien nicht einfach ohne Option als "positional arguments" (in optparse also quasi über die args Liste in "opts, args = parser.parse_args()"?"

Na und das hab ich ja so (siehe oben) - oder hab ich da jetzt was ueberlesen?

Viele Gruesse,
Torres
lunar

Mittwoch 19. Oktober 2011, 16:25

@torres: Blödsinn, Du hast den zitierten Satz nicht verstanden.

Dein Quelltext versucht, eine Option mit mehreren Argumenten zu erstellen, was "optparse" schlicht und einfach nicht kann. "nargs > 1" wortwörtlich zu übergeben, ist semantischer Unsinn, und offenbart ein größeres Missverständnis der Semantik von Python. Lies doch bitte noch einmal die Doku, um zu verstehen, was bei der Übergabe von "nargs > 1" an eine Funktion tatsächlich passiert.

Im zitierten Satz geht es dagegen um Argumente. An die kommst Du bei "optparse" über den zweiten Rückgabewert von ".parse_args()" heran:

Code: Alles auswählen

>>> parser = optparse.OptionParser()
>>> parser.add_option('--foo', action='store_true')
<Option at 0x1283c68: --foo>
>>> opts, args = parser.parse_args(['--foo', 'spam', 'with', 'eggs'])
>>> opts.foo
True
>>> args
[u'spam', u'with', u'eggs']
Argumente kann es bei "optparse" beliebig viele geben, Du kannst sie allerdings keiner Option zuordnen.

Davon abgesehen ist die Absicht, einer Option beliebig viele Argumente zuzuordnen, sowieso unsinnig, was ich in der verlinkten Diskussion, aus welcher der zitierte Satz stammt, auch schon gesagt habe.
Antworten