Hvordan å rømme os.system () samtaler?

stemmer
100

Ved bruk av os.system () er det ofte nødvendig å unnslippe filnavn og andre argumenter som sendes som parametre til kommandoer. Hvordan kan jeg gjøre dette? Helst noe som ville fungere på flere operativsystemer / skjell, men særlig for bash.

Jeg er for tiden gjør følgende, men er sikker på at det må være et bibliotek funksjon for dette, eller i det minste en mer elegant / robust / effektiv alternativ:

def sh_escape(s):
   return s.replace((,\\().replace(),\\)).replace( ,\\ )

os.system(cat %s | grep something | sort > %s 
          % (sh_escape(in_filename), 
             sh_escape(out_filename)))

Edit: Jeg har akseptert det enkle svaret for å bruke anførselstegn, vet ikke hvorfor jeg ikke tenke på det; Jeg antar fordi jeg kom fra Windows hvor og oppfører seg litt annerledes.

Når det gjelder sikkerhet, jeg forstår bekymringen, men i dette tilfellet, er jeg interessert i en rask og enkel løsning som os.system () gir, og kilden til strengene er heller ikke brukergenerert eller i det minste lagt inn av en klarert bruker (meg).

Publisert på 30/08/2008 klokken 09:27
kilden bruker
På andre språk...                            


10 svar

stemmer
136

shlex.quote() gjør hva du vil siden python 3.

(Bruk pipes.quoteå støtte både python 2 og python 3)

Svarte 11/05/2009 kl. 12:06
kilden bruker

stemmer
70

Dette er hva jeg bruker:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

Skallet vil alltid godta en sitert filnavn og fjerne anførselstegn rundt før den sendes til det aktuelle programmet. Spesielt unngår en problemer med filnavn som inneholder mellomrom eller noen annen form for ekkel skall metategn.

Oppdatering : Hvis du bruker Python 3.3 eller senere, bruker shlex.quote stedet for å rulle din egen.

Svarte 30/08/2008 kl. 10:13
kilden bruker

stemmer
54

Kanskje du har en spesiell grunn til å bruke os.system(). Men hvis ikke bør du nok være å bruke subprocessmodulen . Du kan angi rørene direkte og unngå å bruke skallet.

Følgende er fra PEP324 :

Replacing shell pipe line
-------------------------

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]
Svarte 30/08/2008 kl. 10:15
kilden bruker

stemmer
8

Kanskje subprocess.list2cmdlineer en bedre sjanse?

Svarte 25/05/2012 kl. 07:54
kilden bruker

stemmer
4

Merk at pipes.quote er faktisk brutt i Python 2.5 og Python 3.1 og ikke trygt å bruke - Det trenger ikke håndtere null-lengde argumenter.

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

Se Python problemet 7476 ; det har blitt fikset i Python 2.6 og 3.2 og nyere.

Svarte 10/12/2009 kl. 23:03
kilden bruker

stemmer
3

Merknad : Dette er et svar på Python 2.7.x.

Ifølge kilden , pipes.quote()er en måte å " Pålitelig sitere en streng som et enkelt argument for / bin / sh ". (Selv om det er foreldet siden versjon 2.7 , og til slutt utsettes offentlig i Python 3.3 som shelx.quote()funksjon).

den annen side , subprocess.list2cmdline()er en måte å " Trans en sekvens av argumenter i en kommandolinje snor, ved hjelp av de samme regler som MS C-kjøretids ".

Her er vi, plattformuavhengig måte å sitere strenger for kommandolinjer.

import sys
mswindows = (sys.platform == "win32")

if mswindows:
    from subprocess import list2cmdline
    quote_args = list2cmdline
else:
    # POSIX
    from pipes import quote

    def quote_args(seq):
        return ' '.join(quote(arg) for arg in seq)

bruk:

# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)
Svarte 13/04/2015 kl. 03:26
kilden bruker

stemmer
3

Jeg tror at os.system bare påkaller den kommando shell er konfigurert for brukeren, så jeg tror ikke du kan gjøre det i en plattformuavhengig måte. Min kommandoskall kan være alt fra bash, emacs, rubin, eller til og med Quake3. Noen av disse programmene er ikke ventet den slags argumenter du passerer dem, og selv om de gjorde det ingen garanti for at de gjør sitt rømmer på samme måte.

Svarte 30/08/2008 kl. 09:43
kilden bruker

stemmer
1

Funksjonen jeg bruker er:

def quote_argument(argument):
    return '"%s"' % (
        argument
        .replace('\\', '\\\\')
        .replace('"', '\\"')
        .replace('$', '\\$')
        .replace('`', '\\`')
    )

det er: Jeg har alltid omslutte argument i anførselstegn, og deretter backslash-sitere de eneste tegnene spesielle inni anførselstegn.

Svarte 03/10/2010 kl. 21:21
kilden bruker

stemmer
-2

Det virkelige svaret er: Ikke bruk os.system()i første omgang. Bruk subprocess.calli stedet og levere oppdagede argumenter.

Svarte 25/04/2013 kl. 08:44
kilden bruker

stemmer
-2

Hvis du bruker systemet kommandoen, ville jeg prøve og godkjenne hva som går inn i os.system () call .. For eksempel ..

clean_user_input re.sub("[^a-zA-Z]", "", user_input)
os.system("ls %s" % (clean_user_input))

Den delprosess modulen er et bedre alternativ, og jeg vil anbefale å prøve å unngå å bruke noe lignende os.system / delprosess der det er mulig.

Svarte 30/08/2008 kl. 11:43
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more