Sys.argv [x] 'in tanımlı olup olmadığını kontrol etme


Yanıtlar:


64

Sonuç olarak, try, exceptve test arasındaki fark len(sys.argv)o kadar da önemli değil. İkisi de biraz hilekar argparse.

Yine de bu benim aklıma geliyor - bir tür düşük bütçeli argüman olarak:

arg_names = ['command', 'x', 'y', 'operation', 'option']
args = dict(zip(arg_names, sys.argv))

namedtupleVarsayılan değerlere sahip bir oluşturmak için bile kullanabilirsiniz None- hepsi dört satırda!

Arg_list = collections.namedtuple('Arg_list', arg_names)
args = Arg_list(*(args.get(arg, None) for arg in arg_names))

Aşina değilseniz namedtuple, bu sadece bir nesne gibi davranan ve değerlerine tup.attributesözdizimi yerine tup[0]sözdizimi kullanarak erişmenize izin veren bir demettir .

Dolayısıyla, ilk satır namedtuple, içindeki değerlerin her biri için değerler içeren yeni bir tür oluşturur arg_names. İkinci satır , verilen bağımsız değişken adı sözlükte ilişkili bir değere sahip olmadığında varsayılan bir değer döndürmek için argskullanarak sözlükten değerleri getiletir.


Python'u giderek daha çok seviyorum, hepsi bunun gibi cevaplar ve tabii ki Stack Overflow sayesinde! Ne yazık ki son iki satırla ilgili bir açıklamamız yok. Yeni başlayanlar için harika olacağına inanıyorum.
Goujon

2
Sevdim! Bu problemde gördüğüm en iyi çözüm kolayca. Diğerleri için: Benim için hemen açık değildi (newb): 1) 'komut' her seferinde ilk argüman olarak geçecek ve 2) sonuçları argümanlar [0] vb. İle çağırabilirsiniz
Mat D

Bu kesinlikle harika, ancak uzunluğu test etmenin nesi acayip?
colorlace

1
@timwiz Ben sadece argparse kullanmaya kıyasla konuşuyordum. Yine de bu günlerde, eski bir senaryoya her döndüğümde kendimi tekmeliyorum ve argparse kullanmadığımı görüyorum.
gönderen

117

Uzunluğunu kontrol edin sys.argv:

if len(sys.argv) > 1:
    blah = sys.argv[1]
else:
    blah = 'blah'

Bazı insanlar önerdiğiniz istisna temelli yaklaşımı tercih ederler (örneğin try: blah = sys.argv[1]; except IndexError: blah = 'blah'), ancak bu kadar hoşuma gitmiyor çünkü bu kadar hoş bir şekilde "ölçeklenmiyor" (örneğin, iki veya üç argümanı kabul etmek istediğinizde) ve potansiyel olarak (eğer kullanılırsa, örneğin hataları gizleyebilir blah = foo(sys.argv[1]), ancak foo(...)bir kaldırdı IndexErrorki IndexErrorgöz ardı olurdu).


1
Yine de atomik olduğunuz sürece endişelenecek bir şey yok try, except. fooMaddeye kadar argümanınızı bekleyin else.
gönderenle

3
Ayrıca, ölçeklendirmeyi düşündüğünüzde, geçiş yapma zamanı argparse.
gönderenle

1
Argparse üzerinde +1. argparse.pyTüm komut satırı projelerime girdim .
David Wolever

2
@senderle: tabii, gayretliysen, sorun değil. Ancak deneyimlerime göre çoğu programcı gayretli değil ve tüm mantığı trymaddeye koyuyor ... Bu yüzden, daha zor olmadığı (ve IMO, biraz daha güzel) göz önüne alındığında, sadece uzunluğu kontrol etmeyi tercih ederim (ayrıca, akış kontrolü için istisnalar kullandığınız için size bağırırsınız).
David Wolever

2
@David, evet, ne demek istediğini anlıyorum. Ben biraz tryözür diliyorum, itiraf etmeliyim. Bazen niyetimi bir ififadeden daha açık bir şekilde ifade ettiğini hissediyorum .
gönderenle

22

Henüz listelendiğini görmediğim bir başka yol da, koruyucu değerinizi vaktinden önce ayarlamaktır. Bu yöntem, her zaman bir elseifade sunmak zorunda olmadığınız Python'un tembel değerlendirmesinden yararlanır . Misal:

startingpoint = 'blah'
if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]

Veya CRAZY sözdizimine gidiyorsanız, Python'un üçlü operatörünü kullanabilirsiniz :

startingpoint = sys.argv[1] if len(sys.argv) >= 2 else 'blah'

1
Üçlü operatör cevabı benim gözümde en güzel olanı. Burada oturup, bakımını yaptığım bazı yazılımların Python 2.4'e bağlı olduğu gerçeğini küfrederek sessizce küfrediyorum.
Richard Barrell

12

Bunu kullanıyorum - asla başarısız olmaz:

startingpoint = 'blah'
if sys.argv[1:]:
   startingpoint = sys.argv[1]

Bu, tanımlanıp tanımlanmadığını kontrol etmek değildir. Daha çok var olup olmadığını tanımlamak gibidir, aynı şey değildir. Geri dönüş değişkenlerini değerlendirmek için de bu yolu kullandım, ancak mevcut sorunun cevabı değil.
m3nda

@ erm3nda startingpointDeğişkeni örnekten kaldırabilirim , ancak soru bir geri dönüş değişkeni atamak, bu yüzden ben de aynısını yaptım.
anatoly techtonik

1
Kaldırırsanız, tanımlanmamış değişkenle ilgili bir hata alırsınız. Soruyu tekrar okudum ve onun beklediği şey, değişken bir değişim :) yani sorun değil. Bu kısa yol tavsiyesi için teşekkür ederim sys.argv[1:]:. Bu konumsal argümanlarla çalışır, count çalışmaz.
m3nda

10

Sıradan bir Python listesi. Bunun için yakalayacağınız istisna IndexError'dır, ancak bunun yerine uzunluğu kontrol etmeniz daha iyidir.

if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]
else:
  startingpoint = 'blah'

2

Yerleşik harita işleviyle çalışan bir çözüm!

arg_names = ['command' ,'operation', 'parameter']
args = map(None, arg_names, sys.argv)
args = {k:v for (k,v) in args}

O zaman parametrelerinizi şu şekilde çağırmalısınız:

if args['operation'] == "division":
    if not args['parameter']:
        ...
    if args['parameter'] == "euclidian":
        ...

1

Argv [1] değerini argv'ye ekleyebilir ve ardından argv [1] 'in girdiğiniz dizgeye eşit olup olmadığını kontrol edebilirsiniz Örnek:

from sys import argv
argv.append('SomeString')
if argv[1]!="SomeString":
            print(argv[1])

Bana oy verenler için, yanlışı açıklığa kavuşturmadığınız için size yazık.
Hassan Abdul-Kareem

Sanırım bunun sebebi hileli olmasıdır. Ya birisi argüman olarak SomeString'i geçerse? Kabul edebiliyorsanız, 1'den 5'e kadar argüman diyelim.
pbogut

Kullanıcının bağımsız değişkeni sağlamaması durumunda varsayılan bir değer ayarlamak için harika (ancak yine de hile). Sadece ekleyin ve ardından argv [1] kullanın.
Felizett

1

Oluşturanın yapmaya çalıştığı şeye oldukça yakın. İşte kullandığım bir işlev:

def get_arg(index):
    try:
        sys.argv[index]
    except IndexError:
        return ''
    else:
        return sys.argv[index]

Dolayısıyla, kullanım şöyle bir şey olacaktır:

if __name__ == "__main__":
    banner(get_arg(1),get_arg(2))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.