Shell-opdracht uitvoeren en de uitvoer vastleggen

Ik wil een functie schrijven die een shell-opdracht uitvoert en de uitvoer als een tekenreeksretourneert, ongeacht of het een fout- of succesbericht is. Ik wil gewoon hetzelfde resultaat krijgen als met de opdrachtregel.

Wat zou een codevoorbeeld zijn dat zoiets zou doen?

Bijvoorbeeld:

def run_command(cmd):
    # ??????
print run_command('mysqladmin create test -uroot -pmysqladmin12')
# Should output something like:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'

Antwoord 1, autoriteit 100%

In alle officieel onderhouden versies van Python is de eenvoudigste benadering het gebruik van de subprocess.check_outputfunctie:

>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

check_outputvoert een enkel programma uit dat alleen argumenten als invoer gebruikt.1Het retourneert het resultaat precies zoals afgedrukt in stdout. Als u invoer naar stdinmoet schrijven, gaat u verder met de secties runof Popen. Als je complexe shell-commando’s wilt uitvoeren, zie dan de opmerking over shell=Trueaan het einde van dit antwoord.

De functie check_outputwerkt in alle officieel onderhouden versies van Python. Maar voor recentere versies is een flexibelere aanpak beschikbaar.

Moderne versies van Python (3.5 of hoger): run

Als u Python 3,5 + gebruikt, en Not Achterwaartse compatibiliteit , de Nieuwe runfunctie wordt aanbevolen door de officiële documentatie voor de meeste taken. Het biedt een zeer algemene, hoogwaardige API voor de subprocessModule. Om de uitvoer van een programma vast te leggen, passeert u de subprocess.PIPEvlag naar de stdouttrefwoord argument. Open vervolgens de stdoutAttribuut van de geretourneerde CompletedProcessobject:

>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

De retourwaarde is een bytesobject, dus als u een goede reeks wilt, moet u decodehet. Uitgaande van het genoemde proces retourneert een UTF-8-gecodeerde reeks:

>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

Dit kan allemaal worden gecomprimeerd op een een-voering indien gewenst:

>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

Als u input wilt doorgeven aan de stdin, kunt u een bytesobject geven aan de inputtrefwoordargument:

>>> cmd = ['awk', 'length($0) > 5']
>>> ip = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=ip)
>>> result.stdout.decode('utf-8')
'foofoo\n'

U kunt fouten vastleggen door stderr=subprocess.PIPE(vastleggen naar result.stderr) of stderr=subprocess.STDOUT(vastleggen naar result.stdoutsamen met reguliere uitvoer). Als u wilt dat runeen uitzondering genereert wanneer het proces een afsluitcode die niet nul is retourneert, kunt u check=Truedoorgeven. (Of u kunt het returncodeattribuut van resulthierboven controleren.) Als beveiliging geen probleem is, kunt u ook complexere shell-commando’s uitvoeren door shell=Truezoals beschreven aan het einde van dit antwoord.

Latere versies van Python stroomlijnen het bovenstaande verder. In Python 3.7+ kan de bovenstaande one-liner als volgt worden gespeld:

>>> subprocess.run(['ls', '-l'], capture_output=True, text=True).stdout
'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

Het gebruik van runop deze manier voegt een beetje complexiteit toe, vergeleken met de oude manier om dingen te doen. Maar nu kun je bijna alles doen wat je moet doen met alleen de functie run.

Oudere versies van Python (3-3.4): meer over check_output

Als je een oudere versie van Python gebruikt, of een bescheiden achterwaartse compatibiliteit nodig hebt, kun je de functie check_outputgebruiken zoals hierboven kort beschreven. Het is beschikbaar sinds Python 2.7.

subprocess.check_output(*popenargs, **kwargs)  

Het duurt dezelfde argumenten als Popen(zie hieronder), en retourneert een tekenreeks die de uitvoer van het programma bevat. Het begin van dit antwoord heeft een meer gedetailleerd gebruiksvoorbeeld. In Python 3.5+ is check_outputgelijk aan het uitvoeren van runmet check=Trueen stdout=PIPE, en terugkeren alleen het kenmerk stdout.

U kunt stderr=subprocess.STDOUTdoorgeven om ervoor te zorgen dat foutmeldingen worden opgenomen in de geretourneerde uitvoer. Als beveiliging geen probleem is, kunt u ook complexere shell-opdrachten uitvoeren door shell=Truedoor te geven, zoals beschreven aan het einde van dit antwoord.

Als u stderrmoet pipen of invoer aan het proces moet doorgeven, is check_outputniet geschikt voor deze taak. Zie in dat geval de Popenvoorbeelden hieronder.

Complexe applicaties en oudere versies van Python (2.6 en lager): Popen

Als je diepe achterwaartse compatibiliteit nodig hebt, of als je meer geavanceerde functionaliteit nodig hebt dan check_outputof runbieden, moet je rechtstreeks met Popenobjecten, die de low-level API inkapselen voor subprocessen.

De Popen-constructor accepteert ofwel een enkele opdrachtzonder argumenten, of een lijstmet een opdracht als eerste item, gevolgd door een willekeurig nummer argumenten, elk als een afzonderlijk item in de lijst. shlex.splitkan helpen bij het ontleden van tekenreeksen in de juiste opmaak lijsten. Popen-objecten accepteren ook een groot aantal verschillende argumentenvoor proces-IO-beheer en configuratie op laag niveau.

Om invoer te verzenden en uitvoer vast te leggen, is communicatebijna altijd de voorkeursmethode. Zoals in:

output = subprocess.Popen(["mycmd", "myarg"], 
                          stdout=subprocess.PIPE).communicate()[0]

Of

>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, 
...                                    stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo

Als u stdin=PIPEinstelt, kunt u met communicateook gegevens doorgeven aan het proces via stdin:

>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
...                           stderr=subprocess.PIPE,
...                           stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo

Let op Het antwoord van Aaron Hall, wat aangeeft dat je op sommige systemen mogelijk stdout, stderren stdinallemaal naar PIPE(of DEVNULL) om communicateom helemaal te werken.

In sommige zeldzame gevallen heeft u mogelijk complexe, realtime uitvoerregistratie nodig. Vartec‘s antwoord suggereert een weg vooruit, maar andere methoden dan communicatezijn vatbaar voor impasses als niet zorgvuldig gebruikt.

Zoals bij alle bovenstaande functies, wanneer beveiliging geen probleem is, kunt u meer complexe schaalopdrachten uitvoeren door shell=Truete passeren.

Opmerkingen

1. Running Shell-opdrachten: de shell=Trueargument

Normaal gesproken, elke oproep naar run, check_outputof de Popenconstructor voert een enkel programma uit. Dat betekent geen mooie book-stijlpijpen. Als u complexe Shell-opdrachten wilt uitvoeren, kunt u doorgeven shell=True, die alle drie de acties ondersteunen. Bijvoorbeeld:

>>> subprocess.check_output('cat books/* | wc', shell=True, text=True)
' 1299377 17005208 101299376\n'

Doe dit echter echter verhoogt beveiligingsproblemen . Als u iets meer doet dan lichte scripting, bent u misschien beter af, belt u elk proces afzonderlijk en passeert u de uitvoer van elk als een invoer naar de volgende, via

run(cmd, [stdout=etc...], input=other_output)

of

Popen(cmd, [stdout=etc...]).communicate(other_output)

De verleiding om direct aan te sluiten buizen is sterk; Weersta het. Anders ziet u waarschijnlijk deadlocks of moet u hacky dingen doen zoals dit .


Antwoord 2, Autoriteit 14%

Dit is veel eenvoudiger, maar werkt alleen op Unix (inclusief Cygwin) en Python2.7.

import commands
print commands.getstatusoutput('wc -l file')

Het retourneert een tuple met de (return_value, output).

Gebruik in plaats daarvan de module subprocessvoor een oplossing die zowel in Python2 als Python3 werkt:

from subprocess import Popen, PIPE
output = Popen(["date"],stdout=PIPE)
response = output.communicate()
print response

Antwoord 3, autoriteit 8%

Zoiets:

def runProcess(exe):    
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while(True):
        # returns None while subprocess is running
        retcode = p.poll() 
        line = p.stdout.readline()
        yield line
        if retcode is not None:
            break

Merk op, dat ik stderr omleid naar stdout, het is misschien niet precies wat je wilt, maar ik wil ook foutmeldingen.

Deze functie levert regel voor regel op wanneer ze binnenkomen(normaal zou je moeten wachten tot het subproces is voltooid om de uitvoer als geheel te krijgen).

Voor jouw geval zou het gebruik zijn:

for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()):
    print line,

Antwoord 4, autoriteit 6%

Ik had hetzelfde probleem, maar bedacht een heel eenvoudige manier om dit te doen:

import subprocess
output = subprocess.getoutput("ls -l")
print(output)

Hopelijk helpt het

Opmerking: deze oplossing is specifiek voor Python3 omdat subprocess.getoutput()niet werkt in Python2


Antwoord 5, autoriteit 5%

Het antwoord van Vartecleest niet alle regels, dus heb ik een versie gemaakt die dat wel deed:

def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')

Gebruik is hetzelfde als het geaccepteerde antwoord:

command = 'mysqladmin create test -uroot -pmysqladmin12'.split()
for line in run_command(command):
    print(line)

Antwoord 6, autoriteit 5%

Dit is een lastigemaar supereenvoudigeoplossing die in veel situaties werkt:

import os
os.system('sample_cmd > tmp')
print(open('tmp', 'r').read())

Een tijdelijk bestand (hier is tmp) wordt gemaakt met de uitvoer van de opdracht en u kunt daaruit uw gewenste uitvoer lezen.

Extra opmerking bij de opmerkingen:
U kunt het tmp-bestand verwijderen in het geval van een eenmalige taak. Als u dit meerdere keren moet doen, hoeft u de tmp niet te verwijderen.

os.remove('tmp')

Antwoord 7, autoriteit 2%

U kunt de volgende commando’s gebruiken om elk shell-commando uit te voeren. Ik heb ze op ubuntu gebruikt.

import os
os.popen('your command here').read()

Opmerking:dit is verouderd sinds python 2.6. Nu moet je subprocess.Popengebruiken. Hieronder is het voorbeeld

import subprocess
p = subprocess.Popen("Your command", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")

Antwoord 8

Uw kilometerstand kan variëren, ik probeerde @senderle’s draai aan Vartec’s oplossing in Windows op Python 2.6.5, maar ik kreeg fouten en geen enkele andere oplossing werkte. Mijn fout was: WindowsError: [Error 6] The handle is invalid.

Ik ontdekte dat ik PIPE aan elke handle moest toewijzen om de output te krijgen die ik verwachtte – het volgende werkte voor mij.

import subprocess
def run_command(cmd):
    """given shell command, returns communication tuple of stdout and stderr"""
    return subprocess.Popen(cmd, 
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE, 
                            stdin=subprocess.PIPE).communicate()

en bel zo, ([0]krijgt het eerste element van de tuple, stdout):

run_command('tracert 11.1.0.1')[0]

Na meer te hebben geleerd, geloof ik dat ik deze pijpargumenten nodig heb omdat ik aan een aangepast systeem werk dat verschillende handvatten gebruikt, dus ik moest alle std’s rechtstreeks besturen.

Als u console-pop-ups wilt stoppen (met Windows), doet u dit:

def run_command(cmd):
    """given shell command, returns communication tuple of stdout and stderr"""
    # instantiate a startupinfo obj:
    startupinfo = subprocess.STARTUPINFO()
    # set the use show window flag, might make conditional on being in Windows:
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    # pass as the startupinfo keyword argument:
    return subprocess.Popen(cmd,
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE, 
                            stdin=subprocess.PIPE, 
                            startupinfo=startupinfo).communicate()
run_command('tracert 11.1.0.1')

Antwoord 9

Ik had een iets andere smaak van hetzelfde probleem met de volgende vereisten:

  1. Vastleggen en retourneren staald-berichten terwijl ze zich ophopen in de stdout-buffer (d.w.z. in realtime).
    • @vartec opgelost deze pythonisch met zijn gebruik van generatoren en de ‘opbrengst’
      hierboven
  2. Druk alle stDout-lijnen (, zelfs als het procesuitgangen vóór de stdout-buffer volledig kan worden gelezen )
  3. Verspil geen CPU-cycli die het proces op hoge frequentie polderen
  4. Controleer de retourcode van het subprocess
  5. Afdrukken Stderr (gescheiden van stdout) als we een non-zero fout retourcode krijgen.

Ik heb gecombineerd en aangepreend eerdere antwoorden om met het volgende te komen:

import subprocess
from time import sleep
def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         shell=True)
    # Read stdout from subprocess until the buffer is empty !
    for line in iter(p.stdout.readline, b''):
        if line: # Don't print blank lines
            yield line
    # This ensures the process has completed, AND sets the 'returncode' attr
    while p.poll() is None:                                                                                                                                        
        sleep(.1) #Don't waste CPU-cycles
    # Empty STDERR buffer
    err = p.stderr.read()
    if p.returncode != 0:
       # The run_command() function is responsible for logging STDERR 
       print("Error: " + str(err))

Deze code wordt op dezelfde manier uitgevoerd als eerdere antwoorden:

for line in run_command(cmd):
    print(line)

Antwoord 10

Het splitsen van de initiële opdracht voor het subprocesskan lastig en omslachtig zijn.

Gebruik shlex.split()om jezelf te helpen.

Voorbeeldopdracht

git log -n 5 --since "5 years ago" --until "2 year ago"

De code

from subprocess import check_output
from shlex import split
res = check_output(split('git log -n 5 --since "5 years ago" --until "2 year ago"'))
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'

Zonder shlex.split()zou de code er als volgt uitzien

res = check_output([
    'git', 
    'log', 
    '-n', 
    '5', 
    '--since', 
    '5 years ago', 
    '--until', 
    '2 year ago'
])
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'

Antwoord 11

Hier een oplossing die werkt als u output wilt afdrukken terwijl het proces loopt of niet.


Ik heb ook de huidige werkdirectory toegevoegd, het was meer dan eens nuttig voor mij.


In de hoop dat de oplossing iemand zal helpen :).

import subprocess
def run_command(cmd_and_args, print_constantly=False, cwd=None):
"""Runs a system command.
:param cmd_and_args: the command to run with or without a Pipe (|).
:param print_constantly: If True then the output is logged in continuous until the command ended.
:param cwd: the current working directory (the directory from which you will like to execute the command)
:return: - a tuple containing the return code, the stdout and the stderr of the command
"""
output = []
process = subprocess.Popen(cmd_and_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
while True:
    next_line = process.stdout.readline()
    if next_line:
        output.append(str(next_line))
        if print_constantly:
            print(next_line)
    elif not process.poll():
        break
error = process.communicate()[1]
return process.returncode, '\n'.join(output), error

Antwoord 12

Als je een shell-opdracht op meerdere bestanden moet uitvoeren, was dit voor mij de juiste oplossing.

import os
import subprocess
# Define a function for running commands and capturing stdout line by line
# (Modified from Vartec's solution because it wasn't printing all lines)
def runProcess(exe):    
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')
# Get all filenames in working directory
for filename in os.listdir('./'):
    # This command will be run on each file
    cmd = 'nm ' + filename
    # Run the command and capture the output line by line.
    for line in runProcess(cmd.split()):
        # Eliminate leading and trailing whitespace
        line.strip()
        # Split the output 
        output = line.split()
        # Filter the output and print relevant lines
        if len(output) > 2:
            if ((output[2] == 'set_program_name')):
                print filename
                print line

Bewerken: ik zag net de oplossing van Max Persson met de suggestie van J.F. Sebastian. Ging door en nam dat op.


Antwoord 13

Volgens @senderle, als je python3.6 gebruikt zoals ik:

def sh(cmd, input=""):
    rst = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, input=input.encode("utf-8"))
    assert rst.returncode == 0, rst.stderr.decode("utf-8")
    return rst.stdout.decode("utf-8")
sh("ls -a")

Werkt precies zoals u het commando in bash uitvoert


Antwoord 14

Als u de subprocesspython-module gebruikt, kunt u de STDOUT-, STDERR- en retourcode van de opdracht afzonderlijk verwerken. U kunt een voorbeeld zien van de volledige implementatie van de opdrachtaanroeper. Natuurlijk kun je het uitbreiden met try..exceptals je wilt.

De onderstaande functie retourneert de STDOUT-, STDERR- en Return-code zodat u ze in het andere script kunt verwerken.

import subprocess
def command_caller(command=None)
    sp = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
    out, err = sp.communicate()
    if sp.returncode:
        print(
            "Return code: %(ret_code)s Error message: %(err_msg)s"
            % {"ret_code": sp.returncode, "err_msg": err}
            )
    return sp.returncode, out, err

Antwoord 15

Ik wil simpppl als een optie voor overweging voor rekening houden. Het is een module die beschikbaar is via PYPI: pip install simpplen is uitgevoerd op Python3.

simpplstelt de gebruiker toe om Shell-opdrachten uit te voeren en de uitvoer te lezen van het scherm.

De ontwikkelaars suggereren drie soorten gebruikszaken:

  1. Het eenvoudigste gebruik zal er als volgt uitzien:
   from simppl.simple_pipeline import SimplePipeline
    sp = SimplePipeline(start=0, end=100):
    sp.print_and_run('<YOUR_FIRST_OS_COMMAND>')
    sp.print_and_run('<YOUR_SECOND_OS_COMMAND>') ```

  1. Om meerdere opdrachten tegelijkertijd te gebruiken, gebruikt u:
   commands = ['<YOUR_FIRST_OS_COMMAND>', '<YOUR_SECOND_OS_COMMAND>']
    max_number_of_processes = 4
    sp.run_parallel(commands, max_number_of_processes) ```

  1. Ten slotte, als uw project de CLI-module gebruikt, kunt u direct een andere commando_line_tool uitvoeren als onderdeel van een pijplijn. De andere tool zal
    worden uitgevoerd vanuit hetzelfde proces, maar het verschijnt van de logs als
    een ander commando in de pijplijn. Hierdoor kunnen soepeler debuggen en
    Refactoring van tools die andere hulpmiddelen oproepen.
   from example_module import example_tool
    sp.print_and_run_clt(example_tool.run, ['first_number', 'second_nmber'], 
                                 {'-key1': 'val1', '-key2': 'val2'},
                                 {'--flag'}) ```

Houd er rekening mee dat het afdrukken naar STDOUT/STDERR via de logging-module van Python gaat.


Hier is een volledige code om te laten zien hoe simppl werkt:

import logging
from logging.config import dictConfig
logging_config = dict(
    version = 1,
    formatters = {
        'f': {'format':
              '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
        },
    handlers = {
        'h': {'class': 'logging.StreamHandler',
              'formatter': 'f',
              'level': logging.DEBUG}
        },
    root = {
        'handlers': ['h'],
        'level': logging.DEBUG,
        },
)
dictConfig(logging_config)
from simppl.simple_pipeline import SimplePipeline
sp = SimplePipeline(0, 100)
sp.print_and_run('ls')

Antwoord 16

Gebruik op Python 3.7+subprocess.runen geef capture_output=True:

door

import subprocess
result = subprocess.run(['echo', 'hello', 'world'], capture_output=True)
print(repr(result.stdout))

Dit levert bytes op:

b'hello world\n'

Als u wilt dat het de bytes naar een tekenreeks converteert, voegt u text=Truetoe:

result = subprocess.run(['echo', 'hello', 'world'], capture_output=True, text=True)
print(repr(result.stdout))

Hiermee worden de bytes gelezen met uw standaardcodering:

'hello world\n'

Als u een andere codering handmatig moet specificeren, gebruikt u encoding="your encoding"in plaats van text=True:

result = subprocess.run(['echo', 'hello', 'world'], capture_output=True, encoding="utf8")
print(repr(result.stdout))

Antwoord 17

Execute (‘ls -ahl’)
Gedifferentieerde drie / vier mogelijke rendementen en OS-platforms:

  1. Geen uitgang, maar loop met succes
  2. Uitvoer lege regel, loop met succes
  3. RUN FAILED
  4. Output Iets, voer succesvol af

functie hieronder

def execute(cmd, output=True, DEBUG_MODE=False):
"""Executes a bash command.
(cmd, output=True)
output: whether print shell output to screen, only affects screen display, does not affect returned values
return: ...regardless of output=True/False...
        returns shell output as a list with each elment is a line of string (whitespace stripped both sides) from output
        could be 
        [], ie, len()=0 --> no output;    
        [''] --> output empty line;     
        None --> error occured, see below
        if error ocurs, returns None (ie, is None), print out the error message to screen
"""
if not DEBUG_MODE:
    print "Command: " + cmd
    # https://stackoverflow.com/a/40139101/2292993
    def _execute_cmd(cmd):
        if os.name == 'nt' or platform.system() == 'Windows':
            # set stdin, out, err all to PIPE to get results (other than None) after run the Popen() instance
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        else:
            # Use bash; the default is sh
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable="/bin/bash")
        # the Popen() instance starts running once instantiated (??)
        # additionally, communicate(), or poll() and wait process to terminate
        # communicate() accepts optional input as stdin to the pipe (requires setting stdin=subprocess.PIPE above), return out, err as tuple
        # if communicate(), the results are buffered in memory
        # Read stdout from subprocess until the buffer is empty !
        # if error occurs, the stdout is '', which means the below loop is essentially skipped
        # A prefix of 'b' or 'B' is ignored in Python 2; 
        # it indicates that the literal should become a bytes literal in Python 3 
        # (e.g. when code is automatically converted with 2to3).
        # return iter(p.stdout.readline, b'')
        for line in iter(p.stdout.readline, b''):
            # # Windows has \r\n, Unix has \n, Old mac has \r
            # if line not in ['','\n','\r','\r\n']: # Don't print blank lines
                yield line
        while p.poll() is None:                                                                                                                                        
            sleep(.1) #Don't waste CPU-cycles
        # Empty STDERR buffer
        err = p.stderr.read()
        if p.returncode != 0:
            # responsible for logging STDERR 
            print("Error: " + str(err))
            yield None
    out = []
    for line in _execute_cmd(cmd):
        # error did not occur earlier
        if line is not None:
            # trailing comma to avoid a newline (by print itself) being printed
            if output: print line,
            out.append(line.strip())
        else:
            # error occured earlier
            out = None
    return out
else:
    print "Simulation! The command is " + cmd
    print ""

Antwoord 18

De uitvoer kan worden omgeleid naar een tekstbestand en het vervolgens teruglezen.

import subprocess
import os
import tempfile
def execute_to_file(command):
    """
    This function execute the command
    and pass its output to a tempfile then read it back
    It is usefull for process that deploy child process
    """
    temp_file = tempfile.NamedTemporaryFile(delete=False)
    temp_file.close()
    path = temp_file.name
    command = command + " > " + path
    proc = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if proc.stderr:
        # if command failed return
        os.unlink(path)
        return
    with open(path, 'r') as f:
        data = f.read()
    os.unlink(path)
    return data
if __name__ == "__main__":
    path = "Somepath"
    command = 'ecls.exe /files ' + path
    print(execute(command))

Antwoord 19

heeft zojuist een klein bash-script geschreven om dit te doen met curl

https://gist.github.com/harish2704/bfb8abece94893c53ce344548ead8ba5

#!/usr/bin/env bash
# Usage: gdrive_dl.sh <url>
urlBase='https://drive.google.com'
fCookie=tmpcookies
curl="curl -L -b $fCookie -c $fCookie"
confirm(){
    $curl "$1" | grep jfk-button-action | sed -e 's/.*jfk-button-action" href="\(\S*\)".*/\1/' -e 's/\&amp;/\&/g'
}
$curl -O -J "${urlBase}$(confirm $1)"

Other episodes