2012-01-26 15 views
23

Mam mały problem z argparse. Mam opcję xlim, która jest xrange z działki. Chcę móc przekazywać numery takie jak -2e-5. Jednak to nie działa - argparse interpretuje to jako argument pozycyjny. Jeśli wykonam -0.00002 działa: argparse odczytuje go jako liczbę ujemną. Czy możliwe jest odczytanie w -2e-3?Python Argparse: Problem z opcjonalnymi argumentami, które są liczbami ujemnymi

Kod jest poniżej, a przykładem na to, jak bym go uruchomić to:

./blaa.py --xlim -2.e-3 1e4 

Gdybym wykonaj następujące działania:

./blaa.py --xlim -0.002 1e4 

Kod:

parser.add_argument('--xlim', nargs = 2, 
        help = 'X axis limits', 
        action = 'store', type = float, 
        default = [-1.e-3, 1.e-3]) 

Chociaż mogę sprawić, że będzie działał w ten sposób, naprawdę wolałbym używać notacji naukowej. Ktoś ma jakieś pomysły?

Cheers

+0

Czy cytowanie "-2e-5" pomaga? – nmichaels

+0

Zgodnie z http://code.google.com/p/argparse/issues/detail?id=37 powinno ono zostać naprawione. Sprawdź, czy wersja argparse jest nowsza czy ta sama. – favoretti

+0

@nmichaels Witam, masz na myśli "-2e-5"? To nie działa niestety, myślę, że nadal interpretuje to jako argument. Dokładny błąd z './blah.py -xlim" -.2e-5 "1e5' jest --xlim: oczekiwano 2 argumentów. Jeśli użyję \ - myśli, że jest ciągiem znaków, a następnie narzeka, ponieważ powinno być zmienne – Ger

Odpowiedz

11

Jak już wskazano w uwagach, problemem jest to, że - prefiks jest analizowany jako opcja, a nie jako argument. Jednym ze sposobów obejścia tego jest zmienić prefiks używany dla opcji z prefix_chars argumentu:

#!/usr/bin/python 
import argparse 

parser = argparse.ArgumentParser(prefix_chars='@') 
parser.add_argument('@@xlim', nargs = 2, 
        help = 'X axis limits', 
        action = 'store', type = float, 
        default = [-1.e-3, 1.e-3]) 
print parser.parse_args() 

Przykâadowa:

$ ./blaa.py @@xlim -2.e-3 1e4 
Namespace(xlim=[-0.002, 10000.0]) 

Edit: Alternatywnie, można nadal korzystać - jako separatora, przechodzą xlim jako pojedyncza wartość i użyć funkcji w type aby zaimplementować własną parsowania:

#!/usr/bin/python 
import argparse 

def two_floats(value): 
    values = value.split() 
    if len(values) != 2: 
     raise argparse.ArgumentError 
    values = map(float, values) 
    return values 

parser = argparse.ArgumentParser() 
parser.add_argument('--xlim', 
        help = 'X axis limits', 
        action = 'store', type=two_floats, 
        default = [-1.e-3, 1.e-3]) 
print parser.parse_args() 

Przykład OUTP UT:

$ ./blaa.py --xlim "-2e-3 1e4" 
Namespace(xlim=[-0.002, 10000.0]) 
+0

Naprawdę chciałem zachować' -' jako separator, więc zrobiłem proste parsowanie sys .argv zanim zadzwoniłem do parse_args(). Sposób, w jaki to zrobiłem, jest w komentarzu powyżej, ale twoja droga jest znacznie lepsza. Dzięki! – Ger

3

Jeśli do modyfikowania argparse.py się, można zmienić negatywny numer dopasowywania do obsługi notacja naukowa:

W class _ActionsContainer.__init__()

self._negative_number_matcher = _re.compile(r'^-(\d+\.?|\d*\.\d+)([eE][+\-]?\d+)?$') 

Albo po utworzeniu parser, ty może ustawić parser._negative_number_matcher na tę wartość. Takie podejście może mieć problemy, jeśli tworzysz grupy lub akapity, ale powinno działać z prostym parserem.

19

Jednym z rozwiązań, które znalazłem, jest cytowanie wartości, ale dodanie spacji. Oznacza to, że

./blaa.py --xlim " -2.e-3" 1e4 

ten sposób argparse nie pomyśli -2.e-3 jest nazwa opcji, ponieważ pierwszy znak nie jest myślnik, myślnik, ale nadal będzie ona być przekształcone odpowiednio do pływaka, ponieważ pływak (string) ignoruje spacje po lewej stronie.

+1

fajnie! Pracował dla mnie w zupełnie innym języku/środowisku również –

+0

Zrobiłem mały preprocesor, który skanuje sys.argv dla "xlim" i dodaje spację na początku (poprzez twoją odpowiedź). Umieszczam to przed wywołaniem argparse i wygląda na to, że działa dobrze ... 'dla indx w zakresie (len (sys.argv) - 1): jeśli 'xlim' w sys.argv [indx]: sys.argv [indx + 1] = '{0}'. format (sys.argv [indx + 1]) ' – jeremiahbuddha

+0

Działa to również w module argparse latarki –

3

Oto kod, którego używam. (Jest podobny do jeremiahbuddha, ale odpowiada na to pytanie bardziej bezpośrednio, ponieważ dotyczy liczb ujemnych.)

Umieścić to przed wywołaniem argparse.ArgumentParser()

for i, arg in enumerate(sys.argv): 
    if (arg[0] == '-') and arg[1].isdigit(): sys.argv[i] = ' ' + arg 
+0

najlepsza i najłatwiejsza odpowiedź dla tego długiego błędu – mxmlnkn

2

Innym rozwiązaniem jest przechodzą w argumencie dzięki '=' symbol oprócz powołując się na argument - tzn --xlim="-2.3e14"

1

Zainspirowany podejścia andrewfn, w ja utworzono oddzielną funkcję pomocniczą, aby wykonać skrzypce sys.argv: regex szuka:

  • -: znak ujemny
  • \\d*: zero lub więcej cyfr (na dziwnie sformatowanych wartości jak -.5e-2 lub -4354.5e-6)
  • \\.?: fakultatywny okres (np -2e-5 jest rozsądna)
  • \\d*: kolejny zestaw zero lub więcej cyfr (na takie rzeczy jak -2e-5 i -7.e-3)
  • e: dopasować znacznik wykładnik

re.I sprawia, że ​​pasuje zarówno -2e-5 i -2E-5. Używanie p.match oznacza, że ​​przeszukuje tylko od początku każdego ciągu.

0

Jeśli określenie wartości dla opcji ze znakiem równości, argparse nie będą traktować go jako osobna opcja, nawet jeśli zaczyna się -:

./blaa.py --xlim='-0.002 1e4' 
# As opposed to --xlim '-0.002 1e4' 

a jeżeli wartość nie ma spacji to można upuścić cytaty:

./blaa.py --xlim=-0.002 

zobacz: https://www.gnu.org/software/guile/manual/html_node/Command-Line-Format.html

z tym, nie ma potrzeby, aby napisać do ciebie r posiadać parser type= lub przedefiniować znak prefiksu z - na @, zgodnie z sugestią zaakceptowanej odpowiedzi.

+0

To nie działa w tym konkretnym przypadku, ponieważ --- xlim oczekuje dwóch argumentów (nargs = 2). Oznacza to, że chyba że chcesz zmienić konwencję, aby twój program żądał, aby wywoływacz zakodował dwie wartości jako pojedynczy ciąg, a twój program dokonuje podziału. – itub

+0

Ah, dobry punkt @itub. Jeśli 'nargs = 2' jest wymaganiem ORAZ jedna z dwóch wartości opcji zaczyna się od kreski, wtedy nie ma ominięcia tego. – mksios

Powiązane problemy