Behöver du köra dina Python-program med inmatningsparametrar direkt från kommandoraden? Upptäck hur du tolkar dessa argument effektivt med hjälp av modulerna `sys`, `getopt` och `argparse` i Python.
När du behöver hantera användarinmatning i Python använder du vanligtvis funktionen `input()`. Men ibland kan det vara nödvändigt att skicka in specifika argument samtidigt som du startar programmet från kommandoraden.
I denna guide kommer vi att undersöka hur du startar ett Python-skript med olika alternativ och argument via kommandoraden. Därefter går vi igenom hur du utnyttjar Pythons inbyggda moduler för att analysera dessa parametrar på ett effektivt sätt.
Låt oss börja direkt!
Grunderna i `sys.argv` i Python
Om du har erfarenhet av C, vet du att ett vanligt sätt att skicka information till ett program är via kommandoraden. Detta åstadkoms genom att definiera `main`-funktionen på följande sätt:
#include<stdio.h> int main(int argc, char **argv){ //argc: antal argument //argv: vektor av argument //hantera argumenten här return 0; }
Här representerar `argc` antalet argument, och `argv` är en vektor som innehåller argumenten.
Starta Python-skript med kommandoradsargument
I Python startar du ett skript genom att använda `python3 filnamn.py` i terminalen. När du gör det kan du lägga till ett godtyckligt antal argument:
$ python3 filename.py arg1 arg2 ... argn
Modulen `sys` tillhandahåller verktyg för att komma åt och bearbeta dessa argument. `sys.argv` är en lista som innehåller alla argument som ges till skriptet via kommandoraden.
Här är ett konkret exempel där `main.py` startas med diverse argument:
$ python3 main.py hej världen python skript
Vi kan enkelt iterera genom argumentlistan med en `for`-loop och `enumerate`-funktionen:
# main.py import sys for index, argument in enumerate(sys.argv): print(f"arg{index}: {argument}")
# Output arg0:main.py arg1:hej arg2:världen arg3:python arg4:skript
Vi ser att det första elementet (vid index 0) alltid är namnet på Python-filen, och de efterföljande argumenten börjar från index 1.
Detta är ett enkelt program som hanterar kommandoradsargument. Det finns dock ett par problem:
- Hur ska användarna veta vilka argument som ska anges?
- Och vad betyder dessa argument i programmet?
För att lösa detta kan du använda `getopt`- eller `argparse`-modulerna, vilket vi kommer att utforska i detalj.
Hantera kommandoradsargument med Pythons `getopt`
Låt oss se hur vi kan analysera kommandoradsargument med den inbyggda modulen `getopt`.
Efter att ha importerat `getopt` från `getopt`-modulen, kan du definiera de argument som ska tolkas, tillsammans med de korta och långa alternativen för att styra skriptet. Vi behöver analysera argumenten med start från index 1 i `sys.argv`. Så, den relevanta delen att analysera är `sys.argv[1:]`.
Låt oss anta att vi behöver ett meddelande och ett filnamn. Vi använder `m` och `f` som korta alternativ och `meddelande` och `fil` som långa alternativ.
Men hur säkerställer vi att ett specifikt alternativ kräver ett argument?
- För korta alternativ kan du ange att ett alternativ kräver ett argument genom att lägga till ett kolon (`:`) efter alternativets namn.
- På samma sätt, för långa alternativ kan du lägga till ett lika med-tecken (`=`) efter alternativets namn. Dessa alternativ och deras motsvarande argument kan sedan extraheras.
Om vi tillämpar detta har vi följande kod i `main.py`:
# main.py import sys from getopt import getopt options, other_args = getopt(sys.argv[1:], 'm:f:', ['meddelande=', 'fil=']) print(options) print(other_args)
Variabeln `options` kommer nu att innehålla en lista av tupler med alternativen och deras tillhörande argument. Alla övriga positionsargument kommer att sparas i `other_args`.
Vi kan nu skicka in meddelandet och filnamnet för att styra skriptet, antingen med de korta eller långa alternativen.
Om vi kör `main.py` med långa alternativ ser det ut så här:
$ python3 main.py --meddelande hej --fil minfil.txt
Vi ser att alternativen och argumenten är sparade som tupler i `options`-variabeln. Eftersom inga andra positionsargument angavs är `other_args` en tom lista.
# Output [('--meddelande', 'hej'), ('--fil', 'minfil.txt')] []
På samma sätt kan vi använda de korta alternativen:
$ python3 main.py -m hej -f minfil.txt
# Output [('-m', 'hej'), ('-f', 'minfil.txt')] []
⚠️ Obs: Det korta alternativet `-m` i detta exempel ska inte förväxlas med kommandoradsflaggan `-m` som används för att köra en modul som huvudmodul i Python.
Till exempel, du använder `python3 -m unittest main.py` för att köra `unittest`-modulen som huvudmodul när du kör `main.py`.
Som sagt, alla övriga positionsargument som vi anger sparas i `other_args`. Här är ett exempel:
$ python3 main.py -m hej -f minfil.txt extra_argument
Listan med extra argument kommer nu att innehålla strängen `extra_argument`.
# Output [('-m', 'hej'), ('-f', 'minfil.txt')] ['extra_argument']
Eftersom `options` är en lista av tupler kan vi gå igenom den, packa upp varje tupel och extrahera de argument som hör till ett visst alternativ.
Men vad gör vi med filnamnet och meddelandet efter att vi har tolkat dem? Vi öppnar filen i skrivläge och skriver meddelandet, omvandlat till versaler.
# main.py import sys from getopt import getopt options, other_args = getopt(sys.argv[1:], 'm:f:', ['meddelande=', 'fil=']) print(options) print(other_args) for option, argument in options: if option == '-m': message = argument if option == '-f': file_name = argument with open(file_name, 'w') as file: file.write(message.upper())
Låt oss köra `main.py` med de korta alternativen och kommandoradsargumenten.
$ python main.py -m hej -f testfil.txt [('-m', 'hej'), ('-f', 'testfil.txt')] []
Efter att ha kört `main.py` ser vi att `testfil.txt` har skapats i vår arbetsmapp. Filen kommer att innehålla strängen ’hej’ omvandlad till versaler (’HEJ’).
$ ls main.py testfil.txt
$ cat testfil.txt HEJ
Hantera kommandoradsargument med `argparse`
`argparse`-modulen, som också är inbyggd i Pythons standardbibliotek, ger avancerade verktyg för att hantera kommandoradsargument och bygga fullständiga kommandoradsgränssnitt.
För att tolka kommandoradsargument, importera `ArgumentParser` klassen från modulen `argparse`. Vi skapar en instans av `ArgumentParser` som `arg_parser`:
from argparse import ArgumentParser arg_parser = ArgumentParser()
Vi behöver nu lägga till de två kommandoradsargumenten:
- `meddelande`: meddelandet vi vill skriva
- `fil`: namnet på filen vi ska skriva till
Vi använder `add_argument()`-metoden på `arg_parser` för att lägga till dessa. I `add_argument()` kan vi lägga till ett `help`-argument, som fungerar som en beskrivning av parametern.
arg_parser.add_argument('meddelande', help='meddelande att skriva') arg_parser.add_argument('fil', help='namn på filen')
Nu har vi skapat en `arg_parser`-instans och lagt till argumenten. När programmet körs från kommandoraden kan `parse_args()` användas för att hämta argumentens värden.
Här sparar vi `Namespace`-objektet i variabeln `args`. Argumenten kan sedan kommas åt via `args.argument_name`.
Efter att vi har tagit emot argumenten skriver vi nu meddelandet, med bokstäverna omvänt till filen (med `swapcase()`).
args = arg_parser.parse_args() message = args.meddelande file_name = args.fil with open(file_name, 'w') as file: file.write(message.swapcase())
Här är den fullständiga koden för `main.py`:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('meddelande', help='meddelande att skriva') arg_parser.add_argument('fil', help='namn på filen') args = arg_parser.parse_args() print(args) message = args.meddelande file_name = args.fil with open(file_name, 'w') as file: file.write(message.swapcase())
Förstå användningen av kommandoradsargument
För att förstå hur man använder argumenten i `main.py` kan vi använda `–help`-alternativet:
$ python3 main.py --help användning: main.py [-h] meddelande fil positionsargument: meddelande meddelande att skriva fil namn på filen valfria argument: -h, --help visa detta hjälpmeddelande och avsluta
Vi ser att inga argument är valfria. Både `meddelande` och `fil` är obligatoriska positionsargument. Vi kan också använda det korta alternativet `-h`:
$ python3 main.py -h användning: main.py [-h] meddelande fil positionsargument: meddelande meddelande att skriva fil namn på filen valfria argument: -h, --help visa detta hjälpmeddelande och avsluta
Som standard är båda argumenten positionsargument. Om du inte anger dem får du ett fel.
Här har vi angett ett positionsargument (`Hej`) för meddelandet, men inte filnamnet.
Och vi ser att vi får ett felmeddelande om att filargumentet är obligatoriskt.
$ python3 main.py Hej användning: main.py [-h] meddelande fil main.py: error: följande argument krävs: fil
När vi kör `main.py` med båda argumenten ser vi att `args`-objektet innehåller värdena för argumenten.
$ python3 main.py Hej testfil.txt
# Output Namespace(fil='testfil.txt', meddelande='Hej')
Om vi kontrollerar den aktuella arbetsmappen ser vi att skriptet skapade filen `testfil.txt`:
$ ls main.py testfil.txt
Meddelandet är ursprungligen `Hej`, så med växlande gemener och versaler så är innehållet i `testfil.txt` nu `hEJ`.
$ cat testfil.txt hEJ
Göra kommandoradsargument valfria
För att göra argumenten valfria kan du prefixa argumentens namn med `–`.
Låt oss ändra `main.py` så att både meddelandet och filnamnet blir valfria.
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('--meddelande', help='meddelande att skriva') arg_parser.add_argument('--fil', help='namn på filen')
Eftersom argumenten nu är valfria kan vi ange standardvärden om inga argument anges.
if args.meddelande and args.fil: message = args.meddelande file_name = args.fil else: message="Python3" file_name="minfil.txt"
Nu ser den kompletta `main.py` filen ut så här:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('--meddelande', help='meddelande att skriva') arg_parser.add_argument('--fil', help='namn på filen') args = arg_parser.parse_args() print(args) if args.meddelande and args.fil: message = args.meddelande file_name = args.fil else: message="Python3" file_name="minfil.txt" with open(file_name, 'w') as file: file.write(message.swapcase())
Om vi kontrollerar användningen ser vi att `meddelande` och `fil` nu är valfria argument. Det betyder att vi kan köra `main.py` utan att ange några argument.
$ python3 main.py --help användning: main.py [-h] [--meddelande MEDDELANDE] [--fil FIL] valfria argument: -h, --help visa detta hjälpmeddelande och avsluta --meddelande MEDDELANDE meddelande att skriva --fil FIL namn på filen
$ python3 main.py
I objektet `args` kommer både `fil` och `meddelande` vara `None`.
# Output Namespace(fil=None, meddelande=None)
Vi ser att standardfilnamnet och meddelandet (`minfil.txt` respektive `Python3`) har använts. Filen `minfil.txt` har nu skapats i arbetsmappen:
$ ls main.py minfil.txt testfil.txt
Och den innehåller nu strängen `Python3`, med versaler och gemener omväxlat:
$ cat minfil.txt pYTHON3
Du kan också använda `–meddelande` och `–fil` för att göra kommandot mer lättläst.
$ python3 main.py --meddelande Kodning --fil fil2.txt
# Output Namespace(fil='fil2.txt', meddelande='Kodning')
Vi ser `fil2.txt` i arbetsmappen:
$ ls fil2.txt main.py minfil.txt testfil.txt
Och filen innehåller strängen `kODNING` som förväntat.
$ cat fil2.txt kODNING
Sammanfattning
Här följer en sammanfattning av det vi gått igenom i denna handledning:
- Liknande som i C kan vi i Python få tillgång till kommandoradsargumenten genom `sys.argv`. `sys.argv[0]` är namnet på skriptet, så vi är intresserade av att bearbeta argumenten i `sys.argv[1:]`.
- För att öka läsbarheten och hantera olika alternativ kan du använda modulerna `getopt` och `argparse`.
- `getopt` kan användas för att bearbeta argumenten från index 1 och framåt. Du kan ange både korta och långa alternativ.
- När ett alternativ tar ett argument, kan du använda ett kolon (`:`) efter korta alternativ och (`=`) efter långa alternativ.
- Med `argparse` kan du skapa en `ArgumentParser`-instans och lägga till obligatoriska positionsargument med `add_argument()`. Använd `–` för att göra ett argument valfritt.
- För att hämta värdena på kommandoradsargument, använd metoden `parse_args()` på `ArgumentParser`-instansen.
Utforska sedan hur du skapar säkra hash-funktioner i Python.