Python Kommandolinjeargumenter: sys, getopt & argparse Guide

Ønsker du å utføre Python-skripter med kommando-linjeargumenter? Oppdag hvordan du analyserer kommando-linjeargumenter ved hjelp av modulene sys, getopt og argparse i Python.

I Python, når du trenger å hente inn brukerinput, benytter du input()-funksjonen. Men for visse applikasjoner kan det være nødvendig å sende inn spesifikke argumenter når skriptet kjøres fra kommandolinjen.

I denne veiledningen vil vi utforske hvordan man kjører et Python-skript med opsjoner og argumenter via kommandolinjen. Vi vil deretter lære å anvende Pythons innebygde moduler for å prosessere disse opsjonene og argumentene.

La oss begynne!

Forståelsen av sys.argv i Python

Hvis du har erfaring med C-programmering, vet du at en av de enkleste metodene for å sende argumenter til et program er via kommandolinjen. Dette oppnås ved å strukturere hovedfunksjonen slik:

  #include<stdio.h>

  int main(int argc, char **argv){
    //argc: argumentantall
    //argv: argumentvektor

    //utføre handlinger med argumentene

    return 0;
  }
  

Her representerer argc antall argumenter, mens argv representerer en vektor av argumenter.

Kjøring av Python-skript med kommandolinjeargumenter

I Python kan du aktivere et Python-skript fra kommandolinjen ved å bruke kommandoen `python3 filnavn.py`. I tillegg kan du også legge til et valgfritt antall kommandolinjeargumenter:

  $ python3 filnavn.py arg1 arg2 ... argn
  

Sys-modulen tilbyr innebygd funksjonalitet for å få tilgang til og behandle disse kommandolinjeargumentene. `sys.argv` fungerer som en liste over alle kommandolinjeargumenter som sendes inn når Python-skriptet kjøres.

Her er et eksempel der vi kjører `main.py` med kommandolinjeargumenter:

  $ python3 main.py hei verden python skript
  

Vi kan iterere gjennom argumentvektoren ved å bruke en enkel `for`-løkke og `enumerate`-funksjonen:

  # main.py

  import sys

  for idx, arg in enumerate(sys.argv):
      print(f"arg{idx}: {arg}")
  
  # Output
  arg0:main.py
  arg1:hei
  arg2:verden
  arg3:python
  arg4:skript
  

Vi ser at det første argumentet (med indeks 0) er navnet på Python-filen. De påfølgende argumentene starter fra indeks 1.

Dette er et grunnleggende program som aksepterer og behandler kommandolinjeargumenter. Vi ser imidlertid noen utfordringer:

  • Hvordan vet brukerne av programmet hvilke argumenter de skal sende inn?
  • Og hva betyr egentlig disse argumentene?

Dette er ikke særlig intuitivt. For å løse dette kan du benytte enten `getopt`- eller `argparse`-modulene. Dette vil vi se på i de kommende avsnittene.✅

Parsing av kommandolinjeargumenter med Pythons `getopt`

La oss utforske hvordan man analyserer kommandolinjeargumenter ved å bruke den innebygde `getopt`-modulen.

Etter å ha importert `getopt` fra `getopt`-modulen, kan du spesifisere argumentene som skal analyseres samt de korte og lange alternativene for å kjøre skriptet. Vi må prosessere alle argumenter som starter ved indeks 1 i `sys.argv`. Derfor er det stykket som skal analyseres `sys.argv[1:]`.

Her trenger vi en meldingsstreng og et filnavn. La oss benytte `m` og `f` som korte alternativer og `melding` og `fil` som lange alternativer.

Men hvordan sikrer vi at et bestemt alternativ krever et argument?

  • I korte alternativer kan du kreve et argument ved å legge til et kolon (:) etter det korte alternativets navn.
  • Tilsvarende, i lange alternativer, kan du legge til et =-tegn etter det lange alternativet. Vi kan fange opp disse alternativene og deres respektive argumenter.

Hvis vi legger til dette, får vi følgende kode i `main.py`:

  # main.py

  import sys
  from getopt import getopt

  opts, args = getopt(sys.argv[1:],'m:f:',['message=','file='])

  print(opts)
  print(args)
  

Her lagrer variabelen `opts` alternativene og argumentene som en liste av tupler. Eventuelle posisjonsargumenter som vi sender inn, vil bli lagret i `args`-variabelen.

Vi kan sende inn meldingen og filnavnet for å kjøre skriptet, og vi kan bruke enten de korte eller lange alternativene.

Når vi kjører `main.py` med de lange alternativene, har vi:

  $ python3 main.py --message hei --file noenfil.txt
  

Vi har alternativene og argumentene som tupler i `opts`-variabelen. Ettersom vi ikke har sendt inn noen posisjonsargumenter, er `args` en tom liste.

  # Output
  [('--message', 'hei'), ('--file', 'noenfil.txt')]
  []
  

Tilsvarende kan vi også bruke de korte alternativene som vist:

  $ python3 main.py -m hei -f noenfil.txt
  
  # Output
  [('-m', 'hei'), ('-f', 'noenfil.txt')]
  []
  

⚠️ Det korte alternativet `-m` i dette eksemplet må ikke forveksles med kommandolinjeflagget `-m` som brukes for å kjøre en modul som hovedmodul når du kjører et Python-skript.

For eksempel vil du bruke `python3 -m unittest main.py` for å kjøre `unittest` som hovedmodul når du kjører `main.py`.

Vi nevnte at alle andre posisjonsargumenter som vi sender inn, vil bli lagret i `args`-variabelen. Her er et eksempel:

  $ python3 main.py -m hei -f noenfil.txt et_annet_argument
  

Argumentlisten inneholder posisjonsargumentet `et_annet_argument`.

  # Output
  [('-m', 'hei'), ('-f', 'noenfil.txt')]
  ['et_annet_argument']
  

Her er `opts` en liste av tupler. Vi kan derfor iterere gjennom den, pakke ut tuplene og hente ut argumentene som hører til de spesifikke alternativene.

Men hva gjør vi med filnavnet og meldingen etter at vi har behandlet disse argumentene? Vi åpner filen i skrivemodus og skriver meldingsstrengen konvertert til store bokstaver til filen.

  # main.py
  import sys
  from getopt import getopt

  opts, args = getopt(sys.argv[1:],'m:f:',['message=','file='])

  print(opts)
  print(args)

  for option, argument in opts:
      if option == '-m':
          message = argument
      if option == '-f':
          file = argument

  with open(file,'w') as f:
      f.write(message.upper())
  

La oss kjøre `main.py` med de korte alternativene og kommandolinjeargumentene.

  $ python main.py -m hei -f dennefilen.txt
  [('-m', 'hei'), ('-f', 'dennefilen.txt')]
  []
  

Etter å ha kjørt `main.py`, kan vi se `dennefilen.txt` i arbeidsmappen vår. Den inneholder strengen `hei` konvertert til store bokstaver (`HEI`).

  $ ls
  main.py  dennefilen.txt
  
  $ cat dennefilen.txt
  HEI
  

Hvordan analysere kommandolinjeargumenter med `argparse`

`argparse`-modulen, også inkludert i Pythons standardbibliotek, tilbyr funksjonalitet for å analysere kommandolinjeargumenter og bygge kommandolinjegrensesnitt.

For å analysere kommandolinjeargumenter, importerer vi klassen `ArgumentParser` fra `argparse`-modulen. Her har vi instansiert `arg_parser`, et `ArgumentParser`-objekt:

  from argparse import ArgumentParser

  arg_parser = ArgumentParser()
  

Deretter legger vi til to kommandolinjeargumenter:

  • `melding`: meldingsstrengen, og
  • `fil`: navnet på filen vi ønsker å arbeide med.

Nå kaller vi metoden `add_argument()` på `arg_parser` for å legge til begge disse argumentene. I metodekallet `add_argument()` kan du sette `help` til en streng (en beskrivelse av argumentet).

  arg_parser.add_argument('message',help='meldingsstreng')
  arg_parser.add_argument('file',help='filnavn')
  

Hittil har vi instansiert `arg_parser` og lagt til kommandolinjeargumentene. Når programmet kjøres på kommandolinjen, kan du bruke metoden `parse_args()` på `arg_parser` for å hente verdiene til argumentene.

Her lagrer vi argumentnavnet i variabelen `args`. Du kan da bruke `args.argument_navn` for å få verdiene til argumentene.

Etter å ha fått verdiene til argumentene, skriver vi meldingsstrengen med endret bokstavform (ved hjelp av strengmetoden `swapcase()`) til filen.

  args = arg_parser.parse_args()

  message = args.message
  file = args.file

  with open(file,'w') as f:
      f.write(message.swapcase())
  

Setter vi alt sammen, ser vår `main.py`-fil slik ut:

  # main.py

  from argparse import ArgumentParser

  arg_parser = ArgumentParser()
  arg_parser.add_argument('message',help='meldingsstreng')
  arg_parser.add_argument('file',help='filnavn')

  args = arg_parser.parse_args()
  print(args)

  message = args.message
  file = args.file

  with open(file,'w') as f:
       f.write(message.swapcase())
  

Forstå bruk av kommandolinjeargumenter

For å forstå hvordan argumentene brukes når du kjører `main.py`, kan du benytte alternativet `–help` som vist:

  $ python3 main.py --help
  bruk: main.py [-h] melding fil

  posisjonsargumenter:
    melding     meldingsstreng
    fil        filnavn

  valgfrie argumenter:
    -h, --help  vis denne hjelpemeldingen og avslutt
  

Det finnes ingen valgfrie argumenter, og både `melding` og `fil` er obligatoriske posisjonsargumenter. Alternativt kan du også bruke det korte alternativet `-h`:

  $ python3 main.py -h
  bruk: main.py [-h] melding fil

  posisjonsargumenter:
    melding     meldingsstreng
    fil        filnavn

  valgfrie argumenter:
    -h, --help  vis denne hjelpemeldingen og avslutt
  

Som vi ser, er begge argumentene posisjonsargumenter som standard. Hvis du ikke sender inn ett eller flere av disse argumentene, vil du få en feilmelding.

Her har vi sendt inn ett posisjonsargument (`Hei`) for meldingsstrengen, men vi har ikke spesifisert noen verdi for filargumentet.

Og vi får en feilmelding om at filargumentet er påkrevd.

  $ python3 main.py Hei
  bruk: main.py [-h] melding fil
  main.py: feil: følgende argumenter er nødvendige: fil
  

Når vi kjører `main.py` med begge posisjonsargumentene, ser vi at navnerommet `args` inneholder verdiene til argumentene.

  $ python3 main.py Hei fil1.txt
  
  # Output
  Namespace(file="fil1.txt", message="Hei")
  

Hvis vi nå undersøker innholdet i den aktuelle arbeidsmappen, ser vi at skriptet oppretter filen `fil1.txt`:

  $ ls
  fil1.txt  main.py
  

Den opprinnelige meldingsstrengen er `Hei`; etter å ha byttet bokstavform er meldingsstrengen i filen `fil1.txt` `hEI`.

  $ cat fil1.txt
  hEI
  

Hvordan gjøre kommandolinjeargumenter valgfrie

For å gjøre disse kommandolinjeargumentene valgfrie, kan du sette argumentnavnet med `–`.

La oss endre `main.py` for å gjøre både meldings- og filargumentene valgfrie.

  # main.py

  from argparse import ArgumentParser

  arg_parser = ArgumentParser()
  arg_parser.add_argument('--message',help='meldingsstreng')
  arg_parser.add_argument('--file',help='filnavn')
  

Siden kommandolinjeargumentene nå er valgfrie, kan vi angi standardverdier for disse argumentene.

  if args.message and args.file:
      message = args.message
      file = args.file
  else:
      message="Python3"
      file="minfil.txt"
  

På dette tidspunktet inneholder `main.py`-filen følgende kode:

  # main.py

  from argparse import ArgumentParser

  arg_parser = ArgumentParser()
  arg_parser.add_argument('--message',help='meldingsstreng')
  arg_parser.add_argument('--file',help='filnavn')

  args = arg_parser.parse_args()
  print(args)

  if args.message and args.file:
      message = args.message
      file = args.file
  else:
      message="Python3"
      file="minfil.txt"

  with open(file,'w') as f:
      f.write(message.swapcase())
  

Hvis vi sjekker bruken, ser vi at både `melding` og `fil` er valgfrie argumenter. Dette betyr at du nå kan kjøre `main.py` uten begge disse argumentene.

  $ python3 main.py --help
  bruk: main.py [-h] [--message MELDING] [--file FIL]

  valgfrie argumenter:
    -h, --help         vis denne hjelpemeldingen og avslutt
    --message MELDING  meldingsstreng
    --file FIL        filnavn
  
  $ python3 main.py
  

I argumentnavnerommet er både `fil` og `melding` `None`.

  # Output
  Namespace(file=None, message=None)
  

Vi ser at standard filnavn og melding `minfil.txt` og `Python3` blir brukt. Filen `minfil.txt` finnes nå i arbeidsmappen:

  $ ls
  fil1.txt  main.py  minfil.txt
  

Og den inneholder strengen `Python3` med store og små bokstaver byttet:

  $ cat minfil.txt
  pYTHON3
  

Du kan også bruke både `–message` og `–file`-argumentene for å gjøre kommandoen mer oversiktlig.

  $ python3 main.py --message Koding --file fil2.txt
  
  # Output
  Namespace(file="fil2.txt", message="Koding")
  

Vi ser `fil2.txt` i arbeidsmappen:

  $ ls
  fil1.txt  fil2.txt  main.py  minfil.txt
  

Og den inneholder strengen `kODING` som forventet.

  $ cat fil2.txt
  kODING
  

Konklusjon

Her er et sammendrag av hva vi har lært i denne veiledningen:

  • I likhet med C-programmeringsspråket, kan du i Python få tilgang til kommandolinjeargumentene ved å iterere gjennom argumentvektoren `sys.argv`. `sys.argv[0]` er navnet på Python-skriptet. Vi er derfor interessert i å analysere argumentene `sys.argv[1:]`.
  • Men for å forbedre lesbarheten og legge til alternativer, kan du benytte modulene `getopt` og `argparse`.
  • Du kan bruke `getopt`-modulen til å analysere listen over kommandolinjeargumenter fra indeks 1 til slutten av listen. Du kan spesifisere både korte og lange alternativer.
  • Når et alternativ krever et argument, kan du spesifisere et kolon (:) og = etter henholdsvis det korte og lange alternativet.
  • Med Pythons `argparse`-modul kan du instansiere et `ArgumentParser`-objekt og bruke `add_argument()`-metoden for å legge til et påkrevd posisjonsargument. Sett `–` foran argumentnavnet for å gjøre det valgfritt.
  • For å hente verdiene til kommandolinjeargumentene, kall opp `parse_args()`-metoden på `ArgumentParser`-objektet.

Neste skritt er å lære hvordan du utfører sikker hashing i Python.