簡體   English   中英

在Python中包裝bash腳本

[英]Wrapping bash scripts in python

我剛剛找到了這個很棒的wget包裝器,我想使用subprocess模塊​​將其重寫為python腳本。 但是事實證明,給我各種各樣的錯誤是非常棘手的。

download()
{
    local url=$1
    echo -n "    "
    wget --progress=dot $url 2>&1 | grep --line-buffered "%" | \
    sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'

    echo -ne "\b\b\b\b"
    echo " DONE"
}

然后可以這樣稱呼它:

file="patch-2.6.37.gz"
echo -n "Downloading $file:"
download "http://www.kernel.org/pub/linux/kernel/v2.6/$file"

有任何想法嗎?

來源: http//fitnr.com/showing-file-download-progress-using-wget.html

我想你離你不遠了。 我主要想知道的是,當您可以在Python內部進行所有操作時,為什么還要麻煩地將管道運行到grep以及sedawk中?

#! /usr/bin/env python

import re
import subprocess

TARGET_FILE = "linux-2.6.0.tar.xz"
TARGET_LINK = "http://www.kernel.org/pub/linux/kernel/v2.6/%s" % TARGET_FILE

wgetExecutable = '/usr/bin/wget'
wgetParameters = ['--progress=dot', TARGET_LINK]

wgetPopen = subprocess.Popen([wgetExecutable] + wgetParameters,
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

for line in iter(wgetPopen.stdout.readline, b''):
    match = re.search(r'\d+%', line)
    if match:
        print '\b\b\b\b' + match.group(0),

wgetPopen.stdout.close()
wgetPopen.wait()

如果要用Python重寫腳本,請執行以下操作: 在這種情況下,您可以用urllib.urlretrieve()替換wget

#!/usr/bin/env python
import os
import posixpath
import sys
import urllib
import urlparse

def url2filename(url):
    """Return basename corresponding to url.

    >>> url2filename('http://example.com/path/to/file?opt=1')
    'file'
    """
    urlpath = urlparse.urlsplit(url).path  # pylint: disable=E1103
    basename = posixpath.basename(urllib.unquote(urlpath))
    if os.path.basename(basename) != basename:
        raise ValueError  # refuse 'dir%5Cbasename.ext' on Windows
    return basename

def reporthook(blocknum, blocksize, totalsize):
    """Report download progress on stderr."""
    readsofar = blocknum * blocksize
    if totalsize > 0:
        percent = readsofar * 1e2 / totalsize
        s = "\r%5.1f%% %*d / %d" % (
            percent, len(str(totalsize)), readsofar, totalsize)
        sys.stderr.write(s)
        if readsofar >= totalsize: # near the end
            sys.stderr.write("\n")
    else: # total size is unknown
        sys.stderr.write("read %d\n" % (readsofar,))

url = sys.argv[1]
filename = sys.argv[2] if len(sys.argv) > 2 else url2filename(url)
urllib.urlretrieve(url, filename, reporthook)

例:

$ python download-file.py http://example.com/path/to/file 

它將URL下載到文件中。 如果未提供文件,則它將使用URL中的基本名稱。

如果需要,也可以運行wget

#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE, STDOUT

def urlretrieve(url, filename=None, width=4):
    destination = ["-O", filename] if filename is not None else []
    p = Popen(["wget"] + destination + ["--progress=dot", url],
              stdout=PIPE, stderr=STDOUT, bufsize=1) # line-buffered (out side)
    for line in iter(p.stdout.readline, b''):
        if b'%' in line: # grep "%"
            line = line.replace(b'.', b'') # sed -u -e "s,\.,,g"
            percents = line.split(None, 2)[1].decode() # awk $2
            sys.stderr.write("\b"*width + percents.rjust(width))
    p.communicate() # close stdout, wait for child's exit
    print("\b"*width + "DONE")

url = sys.argv[1]
filename = sys.argv[2] if len(sys.argv) > 2 else None
urlretrieve(url, filename)

我沒有注意到此代碼有任何緩沖問題。

我以前做過這樣的事情。 我很想與您分享我的代碼:)

#!/usr/bin/python2.7
# encoding=utf-8

import sys
import os
import datetime

SHEBANG = "#!/bin/bash\n\n"

def get_cmd(editor='vim', initial_cmd=""):
    from subprocess import call
    from tempfile import NamedTemporaryFile
    # Create the initial temporary file.
    with NamedTemporaryFile(delete=False) as tf:
        tfName = tf.name
        tf.write(initial_cmd)
    # Fire up the editor.
    if call([editor, tfName], shell=False) != 0:
        return None
        # Editor died or was killed.
        # Get the modified content.
    fd = open(tfName)
    res = fd.read()
    fd.close()
    os.remove(tfName)
    return res

def main():
    initial_cmd = "wget " + sys.argv[1]
    cmd  = get_cmd(editor='vim', initial_cmd=initial_cmd)
    if len(sys.argv) > 1 and sys.argv[1] == 's':
        #keep the download infomation.
        t = datetime.datetime.now()
        filename = "swget_%02d%02d%02d%02d%02d" %\
                (t.month, t.day, t.hour, t.minute, t.second)
        with open(filename, 'w') as f:
            f.write(SHEBANG)
            f.write(cmd)
            f.close()
            os.chmod(filename, 0777)
    os.system(cmd)

main()


# run this script with the optional argument 's'
# copy the command to the editor, then save and quit. it will 
# begin to download. if you have use the argument 's'.
# then this script will create another executable script, you 
# can use that script to resume you interrupt download.( if server support)

因此,基本上,您只需要修改initial_cmd的值,就您而言,

wget --progress=dot $url 2>&1 | grep --line-buffered "%" | \
    sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'

該腳本將首先創建一個臨時文件,然后將shell命令放入其中,並為其賦予執行權限。 最后運行其中包含命令的臨時文件。

vim download.py

#!/usr/bin/env python

import subprocess
import os

sh_cmd = r"""
download()
{
    local url=$1
    echo -n "    "
    wget --progress=dot $url 2>&1 |
        grep --line-buffered "%"  |
        sed -u -e "s,\.,,g"       |
        awk '{printf("\b\b\b\b%4s", $2)}'

    echo -ne "\b\b\b\b"
    echo " DONE"
}
download "http://www.kernel.org/pub/linux/kernel/v2.6/$file"
"""

cmd = 'sh'
p = subprocess.Popen(cmd, 
    shell=True,
    stdin=subprocess.PIPE,
    env=os.environ
)
p.communicate(input=sh_cmd)

# or:
# p = subprocess.Popen(cmd,
#    shell=True,
#    stdin=subprocess.PIPE,
#    env={'file':'xx'})
# 
# p.communicate(input=sh_cmd)

# or:
# p = subprocess.Popen(cmd, shell=True,
#    stdin=subprocess.PIPE,
#    stdout=subprocess.PIPE,
#    stderr=subprocess.PIPE,
#    env=os.environ)
# stdout, stderr = p.communicate(input=sh_cmd)

那么您可以致電:

file="xxx" python dowload.py

簡而言之,考慮到您擁有script.sh文件,可以執行它並打印其返回值(如果有):

import subprocess
process = subprocess.Popen('/path/to/script.sh', shell=True, stdout=subprocess.PIPE)
process.wait()
print process.returncode

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM