Utilitários do Python

Nesta seção, vamos ver alguns dos diversos módulos utilitários padrão do Python para resolver problemas comuns.

Sistema de arquivos: os, os.path, logil

Os módulos *os* e *os.path* incluem muitas funções para interagir com o sistema de arquivos. O módulo *shutil* pode copiar arquivos.

  • documentos do módulo os
  • files = os.listdir(dir) -- lista de nomes de arquivos no caminho do diretório (não incluindo . e ..). Os nomes dos arquivos são apenas os nomes no diretório, não os caminhos absolutos.
  • os.path.join(dir, filename) -- considerando um nome de arquivo da lista acima, use-o para juntar o diretório e o nome de arquivo para criar um caminho
  • os.path.abspath(path): determinado caminho, retorna uma forma absoluta, por exemplo, /home/nick/foo/bar.html
  • os.path.dirname(path), os.path.basename(path) -- considerando dir/foo/bar.html, retorne o dirname "dir/foo" e basename "bar.html"
  • os.path.exists(path): verdadeiro se existir
  • os.mkdir(dir_path) -- cria um diretório, os.makedirs(dir_path) cria todos os diretórios necessários nesse caminho.
  • launchil.copy(source-path, dest-path) -- copia um arquivo (os diretórios de caminho de destino devem existir)
## Example pulls filenames from a dir, prints their relative and absolute paths
def printdir(dir):
  filenames = os.listdir(dir)
  for filename in filenames:
    print(filename)  ## foo.txt
    print(os.path.join(dir, filename)) ## dir/foo.txt (relative to current dir)
    print(os.path.abspath(os.path.join(dir, filename))) ## /home/nick/dir/foo.txt

A análise de um módulo funciona bem com as funções help() e dir() integradas do Python. No intérprete, execute um comando "import os" e use estes comandos para conferir o que está disponível no módulo: dir(os), help(os.listdir), dir(os.path), help(os.path.dirname).

Execução de processos externos -- subprocesso

O módulo *subprocess* é uma forma simples de executar um comando externo e capturar a saída dele.

  • documentos do módulo subprocess
  • output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) – executa o comando, aguarda a saída dele e retorna o texto de saída. O comando é executado com a saída e o erro padrão combinados em um texto de saída. Em caso de falha, ele lança um CalledProcessError.
  • Se você quiser ter mais controle sobre a execução do subprocesso, consulte a classe subprocess.popen.
  • Existe também um subprocess.call(cmd) simples que executa o comando, despeja a saída na saída e retorna o código de erro. Isso funciona se você quiser executar o comando, mas não precisar capturar a saída nas estruturas de dados do Python.
import subprocess

## Given a dir path, run an external 'ls -l' on it --
## shows how to call an external program
def listdir(dir):
  cmd = 'ls -l ' + dir
  print("Command to run:", cmd)   ## good to debug cmd before actually running it
  (status, output) = subprocess.getstatusoutput(cmd)
  if status:    ## Error case, print the command's output to stderr and exit
    sys.stderr.write(output)
    sys.exit(status)
  print(output)  ## Otherwise do something with the command's output

Exceções

Uma exceção representa um erro de tempo de execução que interrompe a execução normal em uma linha específica e transfere o controle para o código de tratamento de erros. Nesta seção, apresentamos apenas os usos mais básicos das exceções. Por exemplo, um erro de tempo de execução pode ser que uma variável usada no programa não tenha um valor (ValueError .. você provavelmente já viu isso algumas vezes) ou um erro de operação de abertura de arquivo porque um arquivo não existe (IOError). Saiba mais no tutorial de exceções e consulte a lista completa de exceções.

Sem nenhum código de tratamento de erros (como fizemos até agora), uma exceção no ambiente de execução apenas interrompe o programa com uma mensagem de erro. Esse é um bom comportamento padrão, e você já o observou muitas vezes. Você pode adicionar uma opção ao seu código para lidar com exceções, como esta:

  try:
    ## Either of these two lines could throw an IOError, say
    ## if the file does not exist or the read() encounters a low level error.
    f = open(filename, 'rb')
    data = f.read()
    f.close()
  except IOError:
    ## Control jumps directly to here if any of the above lines throws IOError.
    sys.stderr.write('problem reading:' + filename)
  ## In any case, the code then continues with the line after the try/except

A seção try: inclui o código que pode gerar uma exceção. A seção exceto: contém o código a ser executado se houver uma exceção. Se não houver exceção, a seção exceto: será ignorada (ou seja, esse código serve apenas para tratamento de erros, não para o caso "normal" do código). Você pode conseguir um ponteiro para o próprio objeto de exceção com a sintaxe "exceto IOError como e: .." (e aponta para o objeto de exceção).

HTTP -- urllib e urlparse

O módulo *urllib.request* fornece busca de URL, fazendo com que o URL pareça um arquivo que você pode ler. O módulo *urlparse* pode separar e reunir URLs.

  • Documentação do módulo urllib.request
  • ufile = urllib.request.urlopen(url) -- retorna um arquivo como um objeto para esse URL
  • text = ufile.read() -- pode ler a partir dele, como um arquivo (readlines() etc. também funciona)
  • info = ufile.info() -- a metainformação da solicitação. info.gettype() é o tipo MIME, por exemplo, "text/html"
  • baseurl = ufile.geturl() -- obtém a "base" URL para a solicitação, que pode ser diferente do original devido aos redirecionamentos
  • urllib.request.urlretrieve(url, nome de arquivo) -- faz o download dos dados de URL para o caminho de arquivo fornecido
  • urllib.parse.urljoin(baseurl, url): com base em um URL que pode ou não estar completo e o baseurl da página de origem, retorna um URL completo. Use geturl() acima para fornecer o URL base.

Todas as exceções estão em urllib.error.

from urllib.request import urlopen

## Given a url, try to retrieve it. If it's text/html,
## print its base url and its text.
def wget(url):
  ufile = urlopen(url)  ## get file-like object for url
  info = ufile.info()   ## meta-info about the url content
  if info.get_content_type() == 'text/html':
    print('base url:' + ufile.geturl())
    text = ufile.read()  ## read all its text
    print(text)

O código acima funciona bem, mas não inclui tratamento de erros se um URL não funcionar por algum motivo. Aqui está uma versão da função que adiciona a lógica "tente/exceto" para mostrar uma mensagem de erro se a operação do URL falhar.

Se urlopen() parecer estar travando, é possível que seu sistema não permita o acesso direto a alguns endereços HTTP. Para verificar isso, tente buscar o mesmo URL usando wget ou curl. Se esses programas também falharem, você precisará buscar o conteúdo http através de um proxy serviço. A configuração do acesso ao proxy não é abordada por este tutorial.

## Version that uses try/except to print an error message if the
## urlopen() fails.
def wget2(url):
  try:
    ufile = urlopen(url)
    if ufile.info().get_content_type() == 'text/html':
      print(ufile.read())
  except IOError:
    print('problem reading url:', url)

Exercício

Para praticar o sistema de arquivos e o material de comandos externos, consulte o Exercício especial de cópia. Para praticar o material sobre urllib, consulte o Exercício de quebra de registro.