Come implementare idiomi bash comuni in Python? [chiuso]


242

Attualmente faccio la mia manipolazione del file di testo attraverso un mucchio di AWK, sed, Bash e un po 'di Perl mal ricordati.

Ho visto alcuni posti in cui Python è buono per questo genere di cose. Come posso usare Python per sostituire shell scripting, AWK, sed e amici?


3
pythonpy è un buon concorrente per awk e sed usando la sintassi di python: github.com/Russell91/pythonpy
RussellStewart

4
puoi usare la shellpy progettata pensando a un'idea per sostituire bash / sh con python github.com/lamerman/shellpy
Alexander Ponomarev

Questa è la mia domanda, non capisco perché sia ​​basato sull'opinione. La risposta principale elenca ciascuna delle cose principali che una shell fa e ti spiega come eseguirle in Python. Che secondo me risponde alla domanda in modo non opinione.
Chris Jefferson,

Questa domanda, ed è la sua chiusura, sono in discussione qui
Erik il

Risposte:


144

Ogni shell ha diversi set di funzionalità.

  • I comandi essenziali Linux / Unix. Tutti questi sono disponibili attraverso la libreria dei sottoprocessi . Questa non è sempre la prima scelta migliore per eseguire tutti i comandi esterni. Guarda anche shutil per alcuni comandi che sono comandi Linux separati, ma probabilmente potresti implementarli direttamente nei tuoi script Python. Un altro enorme batch di comandi Linux è nella libreria os ; puoi farlo più semplicemente in Python.

    E - bonus! -- più velocemente. Ogni comando Linux separato nella shell (con poche eccezioni) prevede un sottoprocesso. Usando Python shutile i osmoduli, non si effettua il fork di un sottoprocesso.

  • Le caratteristiche dell'ambiente shell. Ciò include elementi che impostano l'ambiente di un comando (directory corrente e variabili di ambiente e quant'altro). Puoi gestirlo facilmente da Python direttamente.

  • Le funzionalità di programmazione della shell. Questo è tutto il controllo del codice dello stato del processo, i vari comandi logici (se, mentre, per, ecc.) Il comando test e tutti i suoi parenti. La definizione delle funzioni. Questo è molto, molto più semplice in Python. Questa è una delle enormi vittorie nel sbarazzarsi di bash e farlo in Python.

  • Funzionalità di interazione. Ciò include la cronologia dei comandi e cosa no. Non è necessario per scrivere script di shell. Questo è solo per l'interazione umana e non per la sceneggiatura.

  • Le funzionalità di gestione dei file shell. Ciò include il reindirizzamento e le pipeline. Questo è più complicato. Gran parte di questo può essere fatto con sottoprocesso. Ma alcune cose che sono facili nella shell sono spiacevoli in Python. In particolare cose come (a | b; c ) | something >result. Ciò esegue due processi in parallelo (con output di acome input per b), seguito da un terzo processo. L'output di quella sequenza viene eseguito in parallelo con somethinge l'output viene raccolto in un file denominato result. È complesso da esprimere in qualsiasi altra lingua.

Programmi specifici (awk, sed, grep, ecc.) Possono spesso essere riscritti come moduli Python. Non esagerare. Sostituisci ciò di cui hai bisogno ed evolvi il tuo modulo "grep". Non iniziare a scrivere un modulo Python che sostituisce "grep".

La cosa migliore è che puoi farlo in pochi passaggi.

  1. Sostituisci AWK e PERL con Python. Lascia tutto il resto da solo.
  2. Cerca di sostituire GREP con Python. Questo può essere un po 'più complesso, ma la tua versione di GREP può essere adattata alle tue esigenze di elaborazione.
  3. Cerca di sostituire FIND con i loop Python che usano os.walk. Questa è una grande vittoria perché non si generano tanti processi.
  4. Cerca di sostituire la logica comune della shell (loop, decisioni, ecc.) Con script Python.

6
ha scritto: "Funzionalità di interazione. Ciò include la cronologia dei comandi e cosa no. Non è necessario." Temo che nessuno possa dire ciò di cui una persona ha davvero bisogno o meno. Forse lo fa. Inoltre, queste strutture hanno molto senso in una shell interattiva, prendendo ad esempio la differenza tra Idle e IPython.
Heltonbiker,

47
Vorrei sinceramente che le persone abbandonassero completamente gli script di shell. Capisco che l'hacking è praticamente una religione nel mondo * nix, ma mi sono davvero stancato di provare a interpretare tutte le soluzioni alternative hackerate nel sistema operativo. La novità dei microtools (awk, sed, top, base, ecc.) È svanita il giorno in cui tutti hanno deciso di realizzare la propria versione. Mi arrabbio quando immagino la quantità di ore-uomo sprecate in piccoli strumenti schifosi che potrebbero essere facilmente sostituiti da un paio di moduli Python ben progettati. :: sospiro ::
Evan Plaice,

40
Non sono d'accordo @EvanPlaice perché la versione di Python di diversi findscript che ho è brutta, lunga e non mantenibile in confronto. Molte cose dovrebbero essere script di shell, molte altre no . Non tutto deve essere solo uno di Python o BASH (o qualsiasi altra cosa).
mikebabcock,

8
@mikebabcock Idealmente ci sarebbe una libreria completa che implementa tutti i micro-strumenti resi disponibili dallo stack di base * nix. Funzioni come find () e last () verrebbero incluse e al posto dei pipe, una combinazione di curry e caricamento lento gestirà l'incollaggio insieme. Non sarebbe bello avere un ambiente di scripting POSIX che funzioni in modo standard in tutte le distro? Non esiste ancora nulla del genere ...
Evan Plaice,

2
Il punto sulle pipeline di shell (come (a | b; c ) | something >result) è in qualche modo mitigato dal fatto che è banalmente facile passare le pipeline di shell ai subprocessmetodi usandoshell=True
iruvar

103

Sì, naturalmente :)

Dai un'occhiata a queste librerie che ti aiutano a non scrivere mai più script di shell (il motto di Plumbum).

Inoltre, se vuoi sostituire awk, sed e grep con qualcosa basato su Python, allora consiglio pyp -

"The Pyed Piper", o pyp, è uno strumento di manipolazione del testo da riga di comando di Linux simile a awk o sed, ma che utilizza stringhe di pitone standard e metodi di elenco nonché funzioni personalizzate evolute per generare risultati rapidi in un intenso ambiente di produzione.


Dai

57

Ho appena scoperto come combinare le parti migliori di bash e ipython. Fino ad ora questo mi sembra più comodo rispetto all'utilizzo di sottoprocessi e così via. Puoi facilmente copiare grandi parti degli script bash esistenti e ad esempio aggiungere la gestione degli errori in modo Python :) Ed ecco il mio risultato:

#!/usr/bin/env ipython3

# *** How to have the most comfort scripting experience of your life ***
# ######################################################################
#
# … by using ipython for scripting combined with subcommands from bash!
#
# 1. echo "#!/usr/bin/env ipython3" > scriptname.ipy    # creates new ipy-file
#
# 2. chmod +x scriptname.ipy                            # make in executable
#
# 3. starting with line 2, write normal python or do some of
#    the ! magic of ipython, so that you can use unix commands
#    within python and even assign their output to a variable via
#    var = !cmd1 | cmd2 | cmd3                          # enjoy ;)
#
# 4. run via ./scriptname.ipy - if it fails with recognizing % and !
#    but parses raw python fine, please check again for the .ipy suffix

# ugly example, please go and find more in the wild
files = !ls *.* | grep "y"
for file in files:
  !echo $file | grep "p"
# sorry for this nonsense example ;)

Consulta i documenti IPython sui comandi della shell di sistema e utilizzalo come shell di sistema .


11
Eseguito l'upgrade perché per qualche bizzarra ragione, nessun altro ha menzionato! -Comandi in IPython, che sono assolutamente fondamentali; soprattutto perché puoi anche assegnare il loro output a una variabile (elenco di righe) come infilelines = ! cat myfile
kampu,

E puoi usare le variabili Python come $varin un comando shell? Wow. Questa dovrebbe essere la risposta accettata.
Chiel ten Brinke,

E puoi anche usarlo dai quaderni di Giove
Yuval Atzmon

44

A partire dal 2015 e dalla versione di Python 3.4, ora è disponibile una shell interattiva per l'utente ragionevolmente completa disponibile su: http://xon.sh/ o https://github.com/scopatz/xonsh

Il video dimostrativo non mostra le pipe utilizzate, ma SONO supportate quando si è in modalità shell predefinita.

Xonsh ('conch') si sforza molto di emulare bash, quindi cose per cui hai già guadagnato memoria muscolare

env | uniq | sort -r | grep PATH

o

my-web-server 2>&1 | my-log-sorter

funzionerà ancora bene.

Il tutorial è piuttosto lungo e sembra coprire una notevole quantità di funzionalità che qualcuno si aspetterebbe in genere al prompt ash o bash:

  • Compila, valuta ed esegue!
  • Cronologia dei comandi e completamento della scheda
  • Aiuto e super aiuto con ?&??
  • Alias ​​e prompt personalizzati
  • Esegue comandi e / o *.xshscript che possono anche essere importati
  • Variabili d'ambiente compresa la ricerca con ${}
  • Reindirizzamento e combinazione input / output
  • Lavori in background e controllo dei lavori
  • Sottoprocessi, tubi e coprocessi di nidificazione
  • Modalità sottoprocesso quando esiste un comando, modalità Python altrimenti
  • $()Sottoprocesso acquisito con , Sottoprocesso non acquisito con $[], Valutazione Python con@()
  • Nome file Globbing con *o espressione regolare Nome file Globbing con Backtick

Ma perché sembra che tutte queste risposte stiano solo reinventando la ruota per le persone che non conoscono bash ? Mi sono trovato moderatamente a mio agio con bash e ognuna di queste risposte sembra che finirà per essere più lavoro per pochi benefici. Queste risposte sono tutte rivolte a persone pitone che hanno paura (o non vogliono passare il tempo ad imparare) bash, ho ragione?
Buttle Butkus,

Sembra avere alcuni svantaggi come il requisito di utilizzare l' .xshestensione per i file con il codice xonsh: github.com/xonsh/xonsh/issues/2478 . Altrimenti devi usare evalxper chiamarlo direttamente dai .pyfile.
Andry,

31
  • Se vuoi usare Python come shell, perché non dare un'occhiata a IPython ? È anche utile imparare in modo interattivo la lingua.
  • Se fai molta manipolazione del testo e se usi Vim come editor di testo, puoi anche scrivere direttamente plug-in per Vim in Python. basta digitare ": help python" in Vim e seguire le istruzioni o dare un'occhiata a questa presentazione . È così facile e potente scrivere funzioni che utilizzerai direttamente nel tuo editor!

8
c'è un profilo ipython chiamato 'sh' che rende l'interprete molto simile a una shell.
Autoplectic,

3
Il profilo "sh" di ipython è stato rimosso da qualche tempo.
gdw2

>>> risultato =! dmesg | grep -i 'usb' #the! operatore fa tutto
Permafacture

16

All'inizio c'erano sh, sed e awk (e trova, grep e ...). È stato bello. Ma Awk può essere una piccola bestia strana e difficile da ricordare se non la usi spesso. Quindi il grande cammello ha creato Perl. Perl era il sogno di un amministratore di sistema. Era come script di shell sugli steroidi. L'elaborazione del testo, comprese le espressioni regolari, era solo una parte della lingua. Poi è diventato brutto ... La gente ha provato a fare grandi applicazioni con Perl. Ora, non fraintendetemi, Perl può essere un'applicazione, ma può (può!) Sembrare un disastro se non state davvero attenti. Poi c'è tutto questo business dei dati flat. È abbastanza per far impazzire un programmatore.

Inserisci Python, Ruby, et al. Queste sono davvero ottime lingue per scopi generici. Supportano l'elaborazione del testo e lo fanno bene (anche se forse non sono strettamente intrecciati nel nucleo di base della lingua). Ma si ingrandiscono molto bene e alla fine hanno ancora un bell'aspetto. Hanno anche sviluppato comunità piuttosto pesanti con molte librerie per quasi tutto.

Ora, gran parte della negatività nei confronti del Perl è una questione di opinione, e certamente alcune persone possono scrivere Perl molto pulito, ma con così tante persone che si lamentano del fatto che è troppo facile creare codice offuscato, sai che c'è un po 'di verità. La domanda diventa davvero allora, hai mai intenzione di usare questo linguaggio per qualcosa di più che semplici sostituzioni di script bash. In caso contrario, impara un po 'di più Perl .. è assolutamente fantastico per quello. Se, d'altra parte, vuoi una lingua che crescerà con te mentre vuoi fare di più, posso suggerire Python o Ruby.

Ad ogni modo, buona fortuna!




7

Uno dei motivi per cui amo Python è che è molto meglio standardizzato rispetto agli strumenti POSIX. Devo ricontrollare e triplicare che ogni bit sia compatibile con altri sistemi operativi. Un programma scritto su un sistema Linux potrebbe non funzionare allo stesso modo su un sistema BSD di OSX. Con Python, devo solo verificare che il sistema di destinazione abbia una versione sufficientemente moderna di Python.

Ancora meglio, un programma scritto in Python standard funzionerà anche su Windows!


1
"un programma scritto in Python standard funzionerà anche su Windows": niente scherzi?
Jean-François Fabre

6

Darò qui la mia opinione basata sull'esperienza:

Per shell:

  • shell può generare facilmente codice di sola lettura. Scrivilo e quando torni ad esso, non riuscirai mai a capire cosa hai fatto di nuovo. È molto facile farlo.
  • shell può fare MOLTE elaborazioni di testo, divisioni, ecc. in una riga con pipe.
  • è il miglior linguaggio di colla quando si tratta di integrare la chiamata di programmi in diversi linguaggi di programmazione.

Per Python:

  • se vuoi che la portabilità sia inclusa in Windows, usa Python.
  • python può essere migliore quando devi manipolare solo più del testo, come raccolte di numeri. Per questo, consiglio Python.

Di solito scelgo bash per la maggior parte delle cose, ma quando ho qualcosa che deve attraversare i confini di Windows, uso semplicemente Python.


4

pythonpy è uno strumento che fornisce un facile accesso a molte delle funzionalità di awk e sed, ma usando la sintassi di python:

$ echo me2 | py -x 're.sub("me", "you", x)'
you2

3

Ho costruito script shell semi-lunghi (300-500 righe) e codice Python che ha funzionalità simili. Quando vengono eseguiti molti comandi esterni, trovo che la shell sia più facile da usare. Perl è anche una buona opzione quando c'è molta manipolazione del testo.


3

Durante la ricerca di questo argomento, ho trovato questo codice di prova (tramite un commento su http://jlebar.com/2010/2/1/Replacing_Bash.html ) che ti consente di "scrivere pipeline simili a shell in Python usando un sintassi concisa e sfruttando gli strumenti di sistema esistenti dove hanno senso ":

for line in sh("cat /tmp/junk2") | cut(d=',',f=1) | 'sort' | uniq:
    sys.stdout.write(line)

2

La tua scommessa migliore è uno strumento che è specificamente orientato verso il tuo problema. Se sta elaborando file di testo, allora Sed, Awk e Perl sono i contendenti principali. Python è un linguaggio dinamico per tutti gli usi . Come con qualsiasi linguaggio di uso generale, esiste il supporto per la manipolazione dei file, ma non è questo lo scopo principale. Considererei Python o Ruby se avessi un requisito per un linguaggio dinamico in particolare.

In breve, impara Sed e Awk davvero bene, oltre a tutte le altre chicche che derivano dal tuo sapore di * nix (tutti i componenti incorporati di Bash, grep, tr e così via). Se sei interessato all'elaborazione di file di testo, stai già utilizzando le cose giuste.


2

Puoi usare Python invece di bash con la libreria ShellPy .

Ecco un esempio che scarica avatar di Python da Github:

import json
import os
import tempfile

# get the api answer with curl
answer = `curl https://api.github.com/users/python
# syntactic sugar for checking returncode of executed process for zero
if answer:
    answer_json = json.loads(answer.stdout)
    avatar_url = answer_json['avatar_url']

    destination = os.path.join(tempfile.gettempdir(), 'python.png')

    # execute curl once again, this time to get the image
    result = `curl {avatar_url} > {destination}
    if result:
        # if there were no problems show the file
        p`ls -l {destination}
    else:
        print('Failed to download avatar')

    print('Avatar downloaded')
else:
    print('Failed to access github api')

Come puoi vedere, tutte le espressioni all'interno del simbolo di accento grave (`) vengono eseguite in shell. E nel codice Python, puoi acquisire i risultati di questa esecuzione ed eseguire azioni su di essa. Per esempio:

log = `git log --pretty=oneline --grep='Create'

Questa riga verrà prima eseguita git log --pretty=oneline --grep='Create'nella shell e quindi assegnerà il risultato alla variabile di registro. Il risultato ha le seguenti proprietà:

stdout tutto il testo dallo stdout del processo eseguito

stderr l'intero testo da stderr del processo eseguito

codice di ritorno codice di ritorno dell'esecuzione

Questa è una panoramica generale della biblioteca, una descrizione più dettagliata con esempi può essere trovata qui .


1

Se la manipolazione del file di testo è in genere una tantum, possibilmente eseguita sul prompt della shell, non otterrai nulla di meglio da Python.

D'altra parte, se di solito devi fare la stessa (o simile) attività ripetutamente e devi scrivere i tuoi script per farlo, allora Python è fantastico - e puoi facilmente creare le tue librerie (puoi farlo anche con script di shell, ma è più ingombrante).

Un esempio molto semplice per avere una sensazione.

import popen2
stdout_text, stdin_text=popen2.popen2("your-shell-command-here")
for line in stdout_text:
  if line.startswith("#"):
    pass
  else
    jobID=int(line.split(",")[0].split()[1].lstrip("<").rstrip(">"))
    # do something with jobID

Controlla anche i moduli sys e getopt, sono i primi di cui avrai bisogno.


1

Ho pubblicato un pacchetto su PyPI: ez .
Utilizzare pip install ezper installarlo.

Ha impacchettato comandi comuni nella shell e la mia lib usa sostanzialmente la stessa sintassi della shell. ad esempio, cp (sorgente, destinazione) può gestire sia file che cartelle! (wrapper di shutil.copy shutil.copytree e decide quando usare quale). Ancora più bene, può supportare la vettorializzazione come R!

Un altro esempio: no os.walk, usa fls (path, regex) per trovare ricorsivamente file e filtri con espressione regolare e restituisce un elenco di file con o senza percorso completo

Esempio finale: puoi combinarli per scrivere degli script molto semplicemente:
files = fls('.','py$'); cp(files, myDir)

Sicuramente dai un'occhiata! Mi è costato centinaia di ore per scriverlo / migliorarlo!


1
Sembra interessante, ma non riesco a sfogliare i documenti non formattati su pypi.python.org/pypi/ez , scusa ...
Greg Dubicki,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.