Python Utilities

Python Utilities

Nesta sessão, vamos dar uma olhada em algumas das muitas funções da biblioteca padrão do Python, visando resolver problemas comuns.

File System – os, os.path, shutil

Os modulos os e os.path contêm muitas funcionalidades para interagir com o sistema operacional.

O módulo shutil pode copiar arquivos

  • os module docs
  • filenames = os.listdir(dir) - lista o nome dos arquivos no diretório (não incluindo path atual . e path pai ..). Os nomes dos arquivos são apenas os nomes dos arquivos e não os seus caminhos absolutos.
  • os.path.join(dir, filename) - recupera o nome de arquivo da lista acima, usar isso para colocar o diretório (path) e nome do arquivo em conjunto para fazer um caminho completo
  • os.path.abspath(path) - recupera um caminho, retorna a forma absoluta, por exemplo, /home/nick/foo/bar.html
  • os.path.dirname(caminho), os.path.basename (path) - recupera o caminho completo dir/foo/bar.html, retorna o diretório “dir/foo” e nome do arquivo “bar.html”
  • os.path.exists(path) – true if it exists
  • os.mkdir(dir_path) – makes one dir, os.makedirs(dir_path) makes all the needed dirs in this path
  • shutil.copy(source-path, dest-path) – copy a file (dest path directories should exist)
## 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

Explorar um módulo funciona muito bem com as funções da biblioteca padrão: help() e dir().

No interpretador execute um import os e use os comandos para avaliar os módulos: dir(os), help(os.listdir), dir(os.path), help(os.path.dirname).

Running External Processes – commands

O modulo commands é uma forma simples de executar um comando externo e capturar sua saída.

  • commands module docs
  • (status, output) = commands.getstatusoutput(cmd) – executa o comando, aguarda a execução para sair e retorna status int e texto de saída como uma tupla. O comando é executado com sua saída padrão e erro padrão combinado em uma única saída de texto. O status será diferente de zero se o comando falhou. Desde que o standar-err do comando seja capturado, se ele falhar, é preciso imprimir alguma indicação sobre o que aconteceu.
  • output = commands.getoutput(cmd) – como o comando acima, mas sem o status int.
  • Há o commands.getstatus(), mas ele faz outra coisa, por isso não utilize.
  • Se você gostaria de ter mais controle dos sub-processos que estão rodando, veja o módulo “popen2” http://docs.python.org/lib/module-popen2.html
  • Há também o simples os.system(cmd), que executa o comando e retorna sua saída e retorna seu código de erro. Isso funciona se você deseja executar o comando, mas não precisa capturar a sua saída em suas estruturas de dados python.
## 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) = commands.getstatusoutput(cmd)
  if status:    ## Error case, print the command's output to stderr and exit
    sys.stderr.write(output)
    sys.exit(1)
  print output  ## Otherwise do something with the command's output

Excessões

Uma exceção representa um erro de tempo de execução que suspende a execução normal em uma linha particular e transfere o controle para manipulação de erros de código. Esta seção apenas introduz os usos mais básicos de exceções. Por exemplo, num erro de tempo de execução pode ser que uma variável utilizada no programa não tenha um valor (ValueError... você provavelmente já viu este erro algumas vezes), ou um erro de operação de abertura de arquivo por causa do arquivo não existir ( IOError). (Veja docs http://docs.python.org/tut/node10.html][exception~~number=plural)

Sem qualquer código de manipulação de erro (como temos feito até agora), uma exceção de tempo de execução apenas interrompe o programa com uma mensagem de erro. Isso é um bom comportamento padrão, e você já viu isso muitas vezes. Você pode adicionar uma estrutura “try/except” no 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, 'rU')
  text = 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 tentativa: seção inclui o código que pode lançar uma exceção. A exceção: seção contém o código para ser executado se houver uma exceção. Se não houver nenhuma exceção, a exceção: a seção é ignorada (isto é, que o código é para a manipulação de erro somente, não é o caso “normal” para o código).

Você pode obter um ponteiro para a exceção do próprio objeto com a sintaxe except IOError, e: (e aponta para o objeto de exceção).

HTTP – urllib and urlparse

O módulo urllib permite acessar servidores HTTP por meios de requests GET e POST de maneira direta – Tornando as urls acessíveis como um arquivo que possa ser lido. O urlparse permite a você trabalhar com partes de url e unir urls.

  • urllib module docs
  • ufile = urllib.urlopen(url) – returns a file like object for that url
  • text = ufile.read() – can read from it, like a file (readlines() etc. also work)
  • info = ufile.info() – the meta info for that request. info.gettype() is the mime time, e.g. ‘text/html’
  • baseurl = ufile.geturl() – gets the “base” url for the request, which may be different from the original because of redirects
  • urllib.urlretrieve(url, filename) – downloads the url data to the given file path
  • urlparse.urljoin(baseurl, url) – given a url that may or may not be full, and the baseurl of the page it comes from, return a full url. Use geturl() above to provide the base url.
## Given a url, try to retrieve it. If it's text/html,
## print its base url and its text.
def wget(url):
  ufile = urllib.urlopen(url)  ## get file-like object for url
  info = ufile.info()   ## meta-info about the url content
  if info.gettype() == '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 caso a url não exista. Segue uma versão de uma função que adiciona a lógica try/except exibindo uma mensagem em caso de erro.

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

Exercício logpuzzle

Você usuará o python para resolver dois enigmas!!!

Utilizando o módulo urllib, os arquivos para este exercício estão no diretório “logpuzzle”. Uma imagem de um animal foi quebrada em muitas imagens de franjas verticais estreitas. As imagens da faixa estão na internet em algum lugar, cada uma com sua própria url. As URLs estão ocultas em um arquivo de log do servidor web. Sua missão é encontrar as URLs e baixar todas as listras de imagens para recriar a imagem original.

Os URLs das fatias estão ocultos dentro dos arquivos de log apache. Cada arquivo de log é de algum servidor e os URLs de fatia desejados estão ocultos dentro dos logs. O arquivo de log codifica de qual servidor ele vem:

  • O arquivo de log animal_code.google.com é do servidor code.google.com.
  • O arquivo de registro animial_code.google.com contém os dados para a imagem do puzzle “animal”.

Aqui está o que uma única linha do arquivo de log se parece:

10.254.254.28 - - [06/Aug/2007:00:14:08 -0700] "GET /foo/talks/ HTTP/1.1"
200 5910 "-" "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4"

Os primeiros números são o endereço do navegador solicitante. A parte mais interessante é o ” caminho HTTP GET” que mostra o caminho de uma solicitação web recebida pelo servidor.

O caminho em si nunca contém espaços e é separado do GET e HTTP por espaços (sugestão de regex: \S (maiúsculas e minúsculas) coincide com qualquer caractere não espacial). Encontre as linhas no log onde a string “puzzle” aparece dentro do caminho, ignorando as muitas outras linhas no log.

Download do Arquivo: logpuzzle.zip

Exercício Parte A:

Arquivo de registro para urls

Complete a função read_urls (filename) que extrai as URLs do enigma dentro de um arquivo de log. Encontre todos os URL do caminho do “enigma” no arquivo de registro. Combine o caminho de cada url com o nome do servidor do nome do arquivo para formar uma URL completa, por exemplo, “http://www.example.com/path/puzzle/from/inside/file”.

Exiba as URLs que aparecem mais de uma vez. A função read_urls () deve retornar a lista de URLs completos, ordenados em ordem alfabética e sem duplicatas. Tomar as urnas em ordem alfabética renderá as fatias de imagem na ordem correta da esquerda para a direita para recriar a imagem animal original. No caso mais simples, main () deve apenas imprimir as urls, uma por linha.

$ ./logpuzzle.py animal_code.google.com
http://code.google.com/something/puzzle-animal-baaa.jpg
http://code.google.com/something/puzzle-animal-baab.jpg

Exercicio Parte B:

Baixe Imagens de Puzzle

Complete a função download_images () que leva uma lista ordenada de urls e um diretório. Baixe a imagem de cada url para o diretório fornecido, criando o primeiro diretório se necessário (consulte o módulo “os” para criar um diretório e “urllib.urlretrieve ()” para fazer o download de uma URL). Nomeie os arquivos de imagem locais com um esquema simples como “img0”, “img1”, “img2” e assim por diante. Você pode imprimir uma pequena linha de saída de status “Recuperando ...” enquanto baixa cada imagem, pois pode ser lento e é bom ter alguma indicação de que o programa está funcionando. Cada imagem é uma pequena fatia vertical do original. Como colocar as fatias juntas para recriar o original? Pode ser resolvido com um pequeno html (o conhecimento de HTML não é necessário).

A função download_images () também deve criar um arquivo index.html no diretório com uma tag * img * para mostrar cada arquivo de imagem local. As etiquetas img devem estar em uma linha juntas sem separação. Desta forma, o navegador exibe todas as fatias em conjunto de forma transparente. Você não precisa de conhecimento de HTML para fazer isso; basta criar um arquivo index.html que se pareça com isto:

<html>
<html>
<body>
    <img src = "/ edu / python / exercícios / img0">
    <img src = "/ edu / python / exercícios / img1">
    <img src = "/ edu / python / exercises / img2">
     ...
</body>
</html>

Aqui está o que você vai obter quando você pode baixar o quebra-cabeça animal:

$ ./logpuzzle.py --todir animaldir animal_code.google.com
$ ls animaldir
img0 img1 img2 img3 img4 img5 img6 img7 img8 img9 index.html

Quando tudo está funcionando, abrir o index.html em um navegador deve revelar a imagem animal original. O que é o animal na imagem?

Parte C - Descodificação da fatia de imagem

O segundo quebra-cabeça envolve uma imagem de um lugar muito famoso, mas depende de algumas classificações personalizadas. Para o primeiro quebra-cabeça, as URLs podem ser ordenadas alfabeticamente para ordenar as imagens corretamente.

No tipo, o URL inteiro é usado. No entanto, diremos que se a url terminar no padrão “- wordchars - wordchars .jpg”, por exemplo, “http://example.com/foo/puzzle/bar-abab-baaa.jpg”, então a url deve ser representado pela segunda palavra do tipo (por exemplo, “baaa”). Então, ordenar uma lista de urls, cada uma com o padrão word-word.jpg deve ordenar as urls pela segunda palavra.

Estenda o seu código para ordenar tais URLs corretamente e, em seguida, você poderá decodificar o segundo puzzle do lugar_code.google.com que mostra um lugar famoso. Qual lugar mostra?