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"
.. nextslide::
- 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)
.. code-block:: python
## 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.
.. nextslide::
- 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.
.. code-block:: 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)
.. nextslide::
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:
.. code-block:: python
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
.. nextslide::
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.
.. nextslide::
.. code-block:: python
## 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.
.. code-block:: python
## 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.
.. nextslide::
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:
.. code-block:: shell
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"
.. nextslide::
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: :download:`logpuzzle.zip <../code/logpuzzle/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.
.. code-block:: shell
$ ./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:
.. code-block:: html
...
Aqui está o que você vai obter quando você pode baixar o quebra-cabeça animal:
.. code-block:: shell
$ ./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?