Sunday 20 August 2017

Python Read Text File As Binary Options


Minha tarefa me pede para calcular um hash de um arquivo de vídeo. Então, eu acho que o que eu preciso fazer, é de alguma forma ler o arquivo de vídeo como dados binários e, em seguida, fazer o shenanigans hash com isso. O problema é que eu só sei ler e escrever em arquivos. txt - os arquivos de vídeo são completamente novos para mim. Então, minhas perguntas são: Como faço para pegar um arquivo e lê-lo como dados binários Como faço para lidar com esses dados Quero dizer, devo apenas colá-lo em uma Cadeia de caracteres ou devo usar uma matriz de algum tipo Imagino que a quantidade de números é Vai ser enorme e eu wouldnt como meu computador para falhar porque eu manipulei os dados de alguma forma terrivelmente ineficiente: D. Além disso, não estou totalmente certo do que estou falando quando digo dados binários, como eu tenho experiência limitada com esse tipo de coisa. Quero dizer, não é apenas uma seqüência de 1s e 0s certo. Então eu também gostaria de apreciar um curso intensivo sobre dados binários: D perguntou Jul 16 13 at 20:49 NorsulRonsul Eu não tenho idéia de quão confiável que particular hash está em python desde que você não pode confiar em wrapping comportamento etc - deve dar-lhe uma idéia de Como hashes como que trabalho embora. Uma otimização pode ser ler 64 ou 128 bytes de cada vez, em vez de apenas um, e iterar de cada personagem ndash Justin Meiners Jul 17 13 at 14: 517. Entrada e Saída Existem várias maneiras de apresentar a saída de um programa de dados podem ser impressos em uma forma legível por humanos, ou gravados em um arquivo para uso futuro. Este capítulo discutirá algumas das possibilidades. 7.1. Formatação de saída Fancier Até agora we8217ve encontrou duas maneiras de escrever valores: expressões de expressão e declaração de impressão. (Uma terceira via está usando o método write () de objetos de arquivo o arquivo de saída padrão pode ser referenciado como sys. stdout. Consulte a Referência da Biblioteca para obter mais informações sobre isso.) Muitas vezes você deseja mais controle sobre a formatação de sua saída do que simplesmente Imprimir valores separados por espaços. Existem duas maneiras de formatar sua saída a primeira maneira é fazer toda a manipulação de seqüência de caracteres usando slicing string e operações de concatenação você pode criar qualquer layout que você pode imaginar. Os tipos de cadeia têm alguns métodos que executam operações úteis para cadeias de preenchimento para uma determinada largura de coluna, estes serão discutidos em breve. A segunda maneira é usar o método str. format (). O módulo string contém uma classe Template que oferece ainda outra maneira de substituir valores em strings. Uma pergunta permanece, naturalmente: como você converte valores às cordas Felizmente, Python tem maneiras converter todo o valor a uma corda: passe-o às funções do repr () ou do str (). A função str () destina-se a retornar representações de valores que são bastante legíveis por humanos, enquanto repr () destina-se a gerar representações que podem ser lidas pelo interpretador (ou forçará um SyntaxError se não houver nenhuma sintaxe equivalente). Para objetos que não possuem uma representação particular para consumo humano, str () retornará o mesmo valor que repr (). Muitos valores, como números ou estruturas como listas e dicionários, têm a mesma representação usando qualquer função. As cadeias de caracteres e os números de ponto flutuante, em particular, têm duas representações distintas. Aqui estão duas maneiras de escrever uma tabela de quadrados e cubos: (Observe que no primeiro exemplo, um espaço entre cada coluna foi adicionado pelo modo como a impressão funciona: sempre adiciona espaços entre seus argumentos.) Este exemplo demonstra o str. rjust () De objetos de seqüência de caracteres, que justifica à direita uma seqüência de caracteres em um campo de uma largura dada preenchendo-o com espaços à esquerda. Existem métodos semelhantes str. ljust () e str. center (). Esses métodos não escrevem nada, eles apenas retornam uma nova seqüência de caracteres. Se a seqüência de caracteres de entrada é muito longa, eles não o truncam, mas devolvê-lo inalterado, isso vai arruinar o layout de sua coluna, mas geralmente é melhor do que a alternativa, que estaria mentindo sobre um valor. (Se você realmente quer truncamento você sempre pode adicionar uma operação de fatia, como em x. ljust (n): n.) Existe um outro método, str. zfill (). Que pads uma seqüência numérica à esquerda com zeros. Ele compreende os sinais mais e menos: O uso básico do método str. format () se parece com isto: Os colchetes e caracteres dentro deles (chamados campos de formato) são substituídos pelos objetos passados ​​para o método str. format (). Um número entre colchetes refere-se à posição do objeto passado para o método str. format (). Se argumentos de palavra-chave são usados ​​no método str. format (), seus valores são referidos usando o nome do argumento. Argumentos posicionais e de palavras-chave podem ser arbitrariamente combinados: 7.2. Leitura e gravação de arquivos open () retorna um objeto de arquivo, e é mais comumente usado com dois argumentos: open (nome de arquivo, modo). O primeiro argumento é uma string contendo o nome do arquivo. O segundo argumento é outra seqüência contendo alguns caracteres descrevendo a maneira em que o arquivo será usado. Modo pode ser r quando o arquivo só será lido, w para apenas escrever (um arquivo existente com o mesmo nome será apagado), e a abre o arquivo para acrescentar qualquer dados escritos para o arquivo é automaticamente adicionado ao final. R abre o arquivo para leitura e escrita. O argumento mode é opcional r será assumido se it8217s omitido. No Windows, b anexado ao modo abre o arquivo no modo binário, então também existem modos como rb. Wb. E rb. Python no Windows faz uma distinção entre texto e arquivos binários os caracteres de fim de linha em arquivos de texto são alterados um pouco quando os dados são lidos ou gravados. Esta modificação por trás dos bastidores para arquivos de dados é ótima para arquivos de texto ASCII, mas corrompe dados binários como os arquivos JPEG ou EXE. Tenha muito cuidado para usar o modo binário ao ler e escrever esses arquivos. No Unix, não causa dano ao acrescentar um b ao modo, então você pode usá-lo de forma independente da plataforma para todos os arquivos binários. 7.2.1. Métodos de objetos de arquivo O restante dos exemplos nesta seção assumirá que um objeto de arquivo chamado f já foi criado. Para ler o conteúdo de um arquivo, chame f. read (size). Que lê alguma quantidade de dados e retorna como uma string. Size é um argumento numérico opcional. Quando o tamanho é omitido ou negativo, todo o conteúdo do arquivo será lido e retornado seu problema se o arquivo for duas vezes maior que a memória do seu computador. Caso contrário, no máximo, os bytes de tamanho são lidos e retornados. Se o fim do arquivo for atingido, f. read () retornará uma string vazia (quotquot). F. readline () lê uma única linha do arquivo um caractere de nova linha (n) é deixado no final da seqüência de caracteres, e só é omitido na última linha do arquivo se o arquivo doesn8217t terminar em uma nova linha. Isso torna o valor de retorno inequívoco se f. readline () retorna uma seqüência vazia, o final do arquivo foi atingido, enquanto uma linha em branco é representada por n. Uma string contendo apenas uma nova linha. Para ler linhas de um arquivo, você pode fazer um loop sobre o objeto de arquivo. Esta é a memória eficiente, rápido e leva a código simples: Se você quiser ler todas as linhas de um arquivo em uma lista você também pode usar lista (f) ou f. readlines (). F. write (string) grava o conteúdo da string no arquivo, retornando None. Para escrever algo diferente de uma string, ele precisa ser convertido em uma string primeiro: f. tell () retorna um inteiro que dá ao arquivo object8217s posição atual no arquivo, medido em bytes desde o início do arquivo. Para alterar a posição do arquivo object8217s, use f. seek (offset, fromwhat). A posição é calculada a partir da adição de offset a um ponto de referência, o ponto de referência é selecionado pelo argumento fromwhat. Um valor fromwhat de 0 medidas a partir do início do arquivo, 1 usa a posição atual do arquivo e 2 usa o final do arquivo como o ponto de referência. Fromwhat pode ser omitido e padrão para 0, usando o início do arquivo como o ponto de referência. Quando terminar com um arquivo, chame f. close () para fechá-lo e liberar quaisquer recursos do sistema ocupados pelo arquivo aberto. Depois de chamar f. close (). As tentativas de usar o objeto de arquivo falharão automaticamente. É uma boa prática usar a palavra-chave com quando se lida com objetos de arquivo. Isso tem a vantagem de que o arquivo está devidamente fechado após a conclusão da suíte, mesmo se uma exceção for aumentada no caminho. É também muito mais curto do que escrever equivalente try - finally blocks: Os objetos de arquivo têm alguns métodos adicionais, como isatty () e truncate () que são menos freqüentemente usados ​​consultar a Referência da Biblioteca para um guia completo para objetos de arquivo. 7.2.2. Salvar dados estruturados com json Strings pode ser facilmente gravado e lido em um arquivo. Os números demoram um pouco mais de esforço, uma vez que o método read () só retorna strings, que terão de ser passados ​​para uma função como int (). Que toma uma seqüência de caracteres como 123 e retorna seu valor numérico 123. Quando você deseja salvar tipos de dados mais complexos como listas aninhadas e dicionários, analisar e serializar manualmente torna-se complicado. Ao invés de ter usuários constantemente escrevendo e depurando código para salvar tipos de dados complicados para arquivos, Python permite que você use o popular formato de intercâmbio de dados chamado JSON (JavaScript Object Notation). O módulo padrão chamado json pode ter hierarquias de dados Python, e convertê-los em representações de string, este processo é chamado de serialização. Reconstruindo os dados da representação de seqüência de caracteres é chamado deserializing. Entre serialização e desserialização, a seqüência que representa o objeto pode ter sido armazenada em um arquivo ou dados, ou enviada através de uma conexão de rede para alguma máquina distante. O formato JSON é comumente usado por aplicativos modernos para permitir a troca de dados. Muitos programadores já estão familiarizados com ele, o que torna uma boa opção para a interoperabilidade. Se você tiver um objeto x. Você pode exibir sua representação de seqüência JSON com uma linha simples de código: Outra variante da função dumps (), chamada dump (). Simplesmente serializa o objeto em um arquivo. Portanto, se f é um objeto de arquivo aberto para escrita, podemos fazer isso: Para decodificar o objeto novamente, se f é um objeto de arquivo que foi aberto para leitura: Esta técnica de serialização simples pode lidar com listas e dicionários, mas serializar instâncias de classe arbitrárias Em JSON requer um pouco de esforço extra. A referência para o módulo json contém uma explicação para isso. Pickle - o módulo pickle Contrariamente ao JSON. Pickle é um protocolo que permite a serialização de objetos arbitrariamente complexos Python. Como tal, é específico para Python e não pode ser usado para se comunicar com aplicativos escritos em outros idiomas. Também é inseguro por padrão: dados desserializing pickle provenientes de uma fonte não confiável pode executar código arbitrário, se os dados foram criados por um atacante habilidoso. Processing Text Files in Python 3 Uma discussão recente sobre a lista de discussão python-ideas deixou claro que Nós (ou seja, os principais desenvolvedores Python) precisam fornecer algumas orientações mais claras sobre como lidar com tarefas de processamento de texto que acionam exceções por padrão no Python 3, mas foram previamente varridas sob o tapete pelo Python 28217s blithe suposição de que todos os arquivos são codificados em 8220latin - 18221. Embora tenhamos algo nos documentos oficiais antes de muito tempo. Esta é a minha própria tentativa preliminar de resumir as opções para o processamento de arquivos de texto, e os vários trade-offs entre eles. A pergunta óbvia a fazer é o que mudou em Python 3 para que as abordagens comuns que os desenvolvedores costumavam usar para processamento de texto em Python 2 agora começaram a lançar UnicodeDecodeError e UnicodeEncodeError em Python 3. A principal diferença é que o comportamento de processamento de texto padrão O Python 3 tem como objetivo detectar problemas de codificação de texto o mais cedo possível - tanto ao ler texto codificado incorretamente (indicado por UnicodeDecodeError) quanto ao ser solicitado a escrever uma seqüência de texto que não possa ser corretamente representada na codificação de destino (indicada por UnicodeEncodeError). Isso contrasta com a abordagem Python 2, que permitia a corrupção de dados por padrão e verificações de exatidão estrita precisavam ser solicitadas explicitamente. Isso certamente poderia ser conveniente quando os dados sendo processados ​​eram predominantemente texto ASCII, e o pedaço ocasional de corrupção de dados era improvável de ser detectado, e muito menos causar problemas, mas ele realmente não é uma base sólida para a construção robusta multilíngüe aplicações (como qualquer um que tem Nunca teve que rastrear um errante UnicodeError em Python 2 vai saber). No entanto, o Python 3 fornece uma série de mecanismos para relaxar as verificações rígidas padrão para lidar com vários casos de uso de processamento de texto (em particular, casos de uso em que o processamento de esforço é aceitável e não é necessária uma correção estrita). O objetivo deste artigo é explicar alguns deles, analisando os casos em que seria apropriado utilizá-los. Observe que muitos dos recursos que discutimos abaixo também estão disponíveis no Python 2, mas você precisa acessá-los explicitamente através do tipo unicode e do módulo de codecs. No Python 3, eles fazem parte do comportamento do tipo str e do builtin aberto. Para processar o texto de forma eficaz no Python 3, é necessário aprender pelo menos uma pequena quantidade sobre codificações Unicode e texto: o Python 3 sempre armazena seqüências de texto como seqüências de pontos de código Unicode. Estes são valores no intervalo 0-0x10FFFF. Eles sempre correspondem diretamente aos caracteres que você lê em sua tela, mas essa distinção não é importante para a maioria das tarefas de manipulação de texto. Para armazenar texto como dados binários, você deve especificar uma codificação para esse texto. O processo de conversão de uma sequência de bytes (isto é, dados binários) para uma sequência de pontos de código (isto é, dados de texto) está a descodificar. Enquanto o processo inverso está codificando. Por razões históricas, a codificação mais utilizada é ascii. Que só pode lidar com pontos de código Unicode no intervalo 0-0x7F (ou seja, ASCII é uma codificação de 7 bits). Há uma grande variedade de codificações compatíveis com ASCII, que garantem que qualquer aparência de um valor ASCII válido nos dados binários se refere ao caractere ASCII correspondente. 8220utf-88221 está se tornando a codificação preferida para muitas aplicações, pois é uma codificação compatível com ASCII que pode codificar qualquer ponto de código Unicode válido. 8220latin-18221 é outra codificação significativa compatível com ASCII, pois mapeia valores de byte diretamente para os primeiros 256 pontos de código Unicode. (Observe que o Windows tem a variante 8220latin-18221 própria chamada cp1252, mas, ao contrário do ISO 8220latin-18221 implementado pelo codec Python com esse nome, a variante específica do Windows doesn8217t mapear todos os 256 possíveis valores de byte) Há também muitas codificações incompatíveis ASCII Em uso generalizado, particularmente em países asiáticos (que tiveram que criar suas próprias soluções antes da ascensão do Unicode) e em plataformas como o Windows, Java eo CLR, onde muitas APIs aceitam texto como UTF-16 dados codificados. A chamada locale. getpreferredencoding () relata a codificação que o Python usará por padrão para a maioria das operações que exigem uma codificação (por exemplo, leitura em um arquivo de texto sem uma codificação especificada). Este é projetado para auxiliar a interoperabilidade entre o Python eo sistema operacional host, mas pode causar problemas com a interoperabilidade entre sistemas (se os problemas de codificação não são gerenciados consistentemente). A chamada sys. getfilesystemencoding () relata a codificação que o Python usará por padrão para a maioria das operações que requerem uma codificação e envolvem metadados textuais no sistema de arquivos (por exemplo, determinando os resultados de os. listdir) Se você for um falante nativo de inglês que resida Em um país de língua inglesa (como eu) it8217s tentador pensar 8220but Python 2 funciona bem, por que você está me incomodando com tudo isso Unicode malarkey8221. Vale a pena tentar lembrar que realmente somos uma minoria neste planeta e, para a maioria das pessoas na Terra, ASCII e latin-1 podem mesmo lidar com seu nome. Muito menos qualquer outro texto que eles possam querer escrever ou processar em sua língua nativa. Para ajudar a padronizar várias técnicas para lidar com erros de codificação e decodificação Unicode, o Python inclui um conceito de manipuladores de erros Unicode que são chamados automaticamente sempre que um problema é encontrado no processo de codificação ou descodificação de texto. Eu não vou cobrir todos eles neste artigo, mas três são de particular significado: estrito. Este é o manipulador de erro padrão que gera UnicodeDecodeError para problemas de codificação e UnicodeEncodeError para problemas de codificação. Surrogateescape. Este é o manipulador de erros que o Python usa para a maioria dos sistemas operacionais que enfrentam APIs para lidar graciosamente com problemas de codificação nos dados fornecidos pelo sistema operacional. Ele lida com erros de decodificação por esquirreling os dados afastado em uma parte pouco usada do espaço de ponto de código Unicode (Para aqueles interessados ​​em mais detalhes, consulte PEP 383). Ao codificar, ele converte aqueles valores escondidos de volta para a seqüência de byte original exata que falha ao decodificar corretamente. Assim como isso é útil para as APIs do SO, ele pode tornar mais fácil tratar com graça os problemas de codificação em outros contextos. Backslashreplace. Este é um manipulador de erro de codificação que converte pontos de código que podem ser representados na codificação de destino para a seqüência de escape numérica de seqüência de caracteres Python equivalente. Ele torna mais fácil garantir que UnicodeEncodeError nunca será lançado, mas doesn8217t perder muita informação ao fazê-lo perdendo (desde que don8217t quer problemas de codificação ocultando saída de erro, este manipulador de erro está ativado no sys. stderr por padrão). Uma alternativa que está sempre disponível é abrir arquivos no modo binário e processá-los como bytes em vez de como texto. Isso pode funcionar em muitos casos, especialmente aqueles em que os marcadores ASCII são incorporados em dados binários genuinamente arbitrários. No entanto, para ambos 8220text dados com codificação desconhecida8221 e 8220text dados com codificação conhecida, mas potencialmente contendo codificação errors8221, é muitas vezes preferível obtê-los em um formulário que pode ser tratado como cadeias de texto. Em particular, algumas APIs que aceitam bytes e texto podem ser muito rigorosas quanto à codificação dos bytes que aceitam (por exemplo, o módulo urllib. urlparse aceita apenas dados ASCII puros para processamento como bytes, mas processará com alegria cadeias de texto contendo Pontos de código ASCII). Esta seção explora um número de casos de uso que podem surgir ao processar texto. A codificação de texto é um tópico suficientemente complexo que não corresponde a nenhuma resposta - a resposta correta para uma determinada aplicação dependerá de fatores como: quanto controle você tem sobre as codificações de texto usadas se evitar a falha de programa é mais importante do que evitar a corrupção de dados Ou vice-versa como os erros de codificação comuns são esperados para ser, e se eles precisam ser tratados com graça ou simplesmente pode ser rejeitado como entrada inválida Caso de uso: os arquivos a serem processados ​​estão em uma codificação compatível com ASCII, mas você don8217t saber exatamente qual um. Todos os arquivos devem ser processados ​​sem acionar nenhuma exceção, mas alguns riscos de corrupção de dados são considerados aceitáveis ​​(por exemplo, agrupando arquivos de log de várias fontes onde alguns erros de dados são aceitáveis, contanto que os registros permaneçam amplamente intactos). Abordagem: use a codificação 8220latin-18221 para mapear valores de bytes diretamente para os primeiros 256 pontos de código Unicode. Este é o equivalente mais próximo do Python 3 ao modelo permissivo de manipulação de texto Python 2. Exemplo: f open (fname, codificaçãoquotlatin-1quot) Embora a codificação cp1252 do Windows também seja chamada de 8220latin-18221, ela não mapeia todos os valores de byte possíveis e, portanto, precisa ser usada em combinação com o manipulador de erro surrogateescape para garantir que ele Nunca lança UnicodeDecodeError. A codificação latin-1 em Python implementa ISO8859-1: 1987 que mapeia todos os valores de byte possíveis para os primeiros 256 pontos de código Unicode e, assim, assegura que os erros de descodificação nunca ocorrerão independentemente do manipulador de erro configurado. Os dados não serão corrompidos se ele for simplesmente lido, processado como texto ASCII e gravado novamente. Nunca criará UnicodeDecodeError quando os dados de leitura continuarão a levantar UnicodeEncodeError se os pontos de código acima de 0xFF (por exemplo, aspas inteligentes copiadas de um programa de processamento de texto) são adicionados à seqüência de texto antes de serem codificados de volta para bytes. Para evitar esses erros, use o manipulador de erro backslashreplace (ou um dos outros manipuladores de erro que substitui pontos de código Unicode sem uma representação na codificação de destino com seqüências de pontos de código ASCII). A corrupção de dados pode ocorrer se os dados de origem estiver em uma codificação incompatível ASCII (por exemplo, UTF-16) corrupção pode ocorrer se dados são escritos para fora usando uma codificação diferente latin-1 corrupção pode ocorrer se os elementos não ASCII da seqüência de caracteres são Modificado diretamente (por exemplo, para uma codificação de largura variável como UTF-8 que foi decodificado como latin-1 em vez disso, cortando a seqüência de caracteres em um ponto arbitrário pode dividir um caractere de vários bytes em duas partes) Caso de uso: os arquivos a serem processados ​​são Em uma codificação compatível com ASCII, mas você não sabe exatamente qual deles. Todos os arquivos devem ser processados ​​sem acionar exceções, mas alguns erros relacionados a Unicode são aceitáveis ​​para reduzir o risco de corrupção de dados (por exemplo, agrupando arquivos de log de várias fontes, mas desejando uma notificação mais explícita quando os dados agrupados correm o risco de corrupção devido Para erros de programação que violam a suposição de escrever os dados de volta apenas em sua codificação original) Abordagem: use a codificação ascii com o manipulador de erro surrogateescape. Exemplo: os dados abertos (fname, encodingquotasciiquot, errorsquotsurrogateescapequot) não serão corrompidos se forem simplesmente lidos, processados ​​como texto ASCII e escritos novamente. Nunca criará UnicodeDecodeError quando os dados de leitura continuarão a levantar UnicodeEncodeError se os pontos de código acima de 0xFF (por exemplo, aspas inteligentes copiadas de um programa de processamento de texto) são adicionados à seqüência de texto antes de serem codificados de volta para bytes. Para evitar esses erros, use o manipulador de erro backslashreplace (ou um dos outros manipuladores de erro que substitui pontos de código Unicode sem uma representação na codificação de destino com seqüências de pontos de código ASCII). Também criará UnicodeEncodeError se for feita uma tentativa para codificar uma seqüência de texto contendo valores de bytes escapados sem habilitar o manipulador de erro surrogateescape (ou um manipulador ainda mais tolerante como backslashreplace). Algumas bibliotecas de processamento Unicode que asseguram uma seqüência de ponto de código é texto válido pode reclamar sobre o mecanismo de escape usado (I8217m não vai explicar o que significa aqui, mas a frase 8220lone surrogate8221 é uma dica de que algo ao longo dessas linhas pode estar acontecendo - o fato Que 8220surrogate8221 também aparece no nome do manipulador de erro não é uma coincidência). A corrupção de dados ainda pode ocorrer se os dados de origem estiver em uma codificação incompatível ASCII (por exemplo, UTF-16) corrupção de dados também é possível se as partes de escape da seqüência de caracteres são modificados diretamente Caso de uso: os arquivos a serem processados ​​estão em uma codificação consistente , A codificação pode ser determinada a partir dos detalhes do sistema operacional e configurações de localidade e é aceitável recusar o processamento de arquivos que não estão devidamente codificados. Abordagem: basta abrir o arquivo no modo de texto. Este caso de uso descreve o comportamento padrão em Python 3. UnicodeDecodeError pode ser lançado ao ler esses arquivos (se os dados não estiverem na codificação retornada por locale. getpreferredencoding ()) UnicodeEncodeError pode ser lançado ao gravar esses arquivos (se tentar escrever Out pontos de código que não têm nenhuma representação na codificação de destino). O manipulador de erro surrogateescape pode ser usado para ser mais tolerante de erros de codificação se for necessário fazer uma tentativa de melhor esforço para processar arquivos que contêm esses erros em vez de rejeitá-los abertamente como entrada inválida. Caso de uso: os arquivos a serem processados ​​são nominalmente em uma codificação consistente, você sabe a codificação exata antecipadamente e é aceitável se recusar a processar arquivos que não estão devidamente codificados. Isso está se tornando cada vez mais comum, especialmente com muitos formatos de arquivo de texto começando a padronizar em UTF-8 como a codificação de texto preferida. Abordagem: abrir o arquivo no modo de texto com a codificação apropriada Exemplo: f open (fname, encodingquotutf-8quot) UnicodeDecodeError pode ser lançado ao ler esses arquivos (se os dados não estiverem na codificação especificada) UnicodeEncodeError pode ser lançado ao escrever tal Arquivos (se tentar escrever pontos de código que não têm nenhuma representação na codificação de destino). O manipulador de erro surrogateescape pode ser usado para ser mais tolerante de erros de codificação se for necessário fazer uma tentativa de melhor esforço para processar arquivos que contêm esses erros em vez de rejeitá-los abertamente como entrada inválida. Caso de uso: os arquivos a serem processados ​​incluem marcadores que especificam a codificação nominal (com uma codificação padrão assumida se nenhum marcador estiver presente) e é aceitável recusar processar arquivos que não estão devidamente codificados. Abordagem: primeiro abra o arquivo no modo binário para procurar o marcador de codificação e, em seguida, reabra no modo de texto com a codificação identificada. Exemplo: f tokenize. open (fname) usa marcadores de codificação PEP 263 para detectar a codificação de arquivos de origem Python (padrão para UTF-8 se nenhum marcador de codificação for detectado) pode lidar com arquivos em codificações diferentes ainda pode levantar UnicodeDecodeError se o marcador de codificação é Incorreto deve garantir que marcador está definido corretamente ao gravar esses arquivos, mesmo se não é a codificação padrão, arquivos individuais ainda podem ser definidos para usar UTF-8 como a codificação para suportar a codificação quase todos os pontos de código Unicode o manipulador de erro surrogateescape pode ser Usado para ser mais tolerante de erros de codificação, se é necessário fazer uma tentativa de melhor esforço para processar arquivos que contêm esses erros em vez de rejeitá-los como entrada inválida input. Python Files I / O Este capítulo abrange todas as funções de E / S básicas disponíveis Em Python. Para obter mais funções, consulte a documentação padrão do Python. Imprimir para a tela A maneira mais simples de produzir saída é usar a instrução print onde você pode passar zero ou mais expressões separadas por vírgulas. Esta função converte as expressões que você passa para uma seqüência de caracteres e grava o resultado na saída padrão da seguinte forma menos Isso produz o seguinte resultado na tela padrão menos Entrada de teclado de leitura Python fornece duas funções internas para ler uma linha de texto de entrada padrão, Que por padrão vem do teclado. Estas funções são menos A função rawinput A função rawinput (prompt) lê uma linha da entrada padrão e retorna-a como uma string (removendo a nova linha de saída). Isso solicita que você digite qualquer seqüência de caracteres e exibiria a mesma seqüência na tela. A função input (prompt) é equivalente a rawinput, exceto que assume que a entrada é uma expressão Python válida e retorna o resultado avaliado para você. Isto produziria o seguinte resultado contra a entrada introduzida menos Abrir e fechar ficheiros Até agora, tem estado a ler ea escrever para a entrada e saída padrão. Agora, veremos como usar arquivos de dados reais. O Python fornece funções e métodos básicos necessários para manipular arquivos por padrão. Você pode fazer a maior parte da manipulação de arquivos usando um objeto de arquivo. A Função aberta Antes que você possa ler ou escrever um arquivo, você tem que abri-lo usando Pythons built-in open () função. Esta função cria um objeto de arquivo, que seria utilizado para chamar outros métodos de suporte associados a ele. Sintaxe Aqui estão os detalhes do parâmetro: filename: O argumento filename é um valor de string que contém o nome do arquivo ao qual você deseja acessar. Accessmode: O modo de acesso determina o modo no qual o arquivo deve ser aberto, isto é, ler, escrever, anexar, etc. Uma lista completa de valores possíveis é dada abaixo na tabela. Este parâmetro é opcional eo modo de acesso de arquivo padrão é read (r). Buffering: Se o buffering valor é definido como 0, não buffering ocorre. Se o valor de buffer é 1, o buffer de linha é executado ao acessar um arquivo. Se você especificar o valor de buffer como um inteiro maior que 1, a ação de buffer será executada com o tamanho de buffer indicado. Se negativo, o tamanho do buffer é o padrão do sistema (comportamento padrão). Aqui está uma lista dos diferentes modos de abrir um arquivo minusChapter XXX: Python - analisando arquivos binários de dados Por que aprender sobre arquivos binários O armazenamento binário de dados dentro de arquivos é comumente usado usado sobre ASCII para empacotar dados muito mais densamente e fornecer acesso muito mais rápido. A conversão de ASCII em representações binárias internas de dados que o computador usa leva muito tempo. Além disso, pode ser mais rápido do que esquemas de embalagem mais gerais, como Netcdf e HDF5 por ser mais simples. Há muitos conjuntos de dados críticos disponíveis como dados binários. No entanto, há muitas vezes coisas que estão erradas com o formato binário que impedi-lo de usá-lo no resto de sua pesquisa e trabalho de processamento de dados. Ser capaz de ler dados binários é uma habilidade essencial para as pessoas no campo você vai encontrar um grande número de formatos binários. Ser capaz de ler estas vai lhe dar informações valiosas sobre como esses sistemas funcionam. Por exemplo, se você obter uma nova versão do software em um sonar multi-feixe e suas ferramentas de análise começarem a ter problemas, sua capacidade de decodificar as mensagens binárias do sonar pode economizá-lo de tempo ocioso ou até mesmo ajudá-lo a evitar coletar dados ruins que Caso contrário, assumiria que está bem se você não olhar para dentro das mensagens. Um aviso sobre dados binários Se você estiver criando um novo formato binário para seu trabalho, pare por favor. Há muitos formatos no mundo e formatos como HDF5 e SQLite3 fornecem contêineres muito potentes que as bibliotecas preexistentes entendem e esses formatos são auto-descrevendo em que você pode perguntar-lhes o que eles armazenam. É difícil criar um bom formato de arquivo binário e você provavelmente fará muitos erros que seriam evitados. Fornecer documentação clara de formatos de arquivo binário é extremamente fácil de errar. Como trabalhamos através de vários formatos binários existentes, vou tentar apontar o que é certo e errado (na minha opinião) no design desse formato específico. O que significa ser dados binários SBET - mensagens simples de navegação inercial Um arquivo SBET é um arquivo de log proveniente de um sistema de navegação inercial POSPac da Applanix. Esses dispositivos funcionam em uma freqüência muito alta para mesclar GPS, bússola, giroscópio, acelerômetro e outros dados que vêm em uma variedade de intervalos de tempo. Relatará sua melhor estimativa de o que seu ar, mar, submarino, ou veículo terrestre está fazendo nos termos do movimento. Estes são os dados críticos que permitem que você combine pings sonar individuais ou intervalos de laser para criar um modelo corretamente um georreferenciado do ambiente. Eu tomei um arquivo de amostra de um cruzeiro de pesquisa no Alasca no navio de pesquisa NOAA Fairweather. Para simplificar o exemplo eu só mantive cada 1 / 10000ª mensagem de dados. O arquivo original tinha 22 milhões de relatórios eo novo arquivo tem 166 relatórios. When learning, smaller examples are easier to work with I will not show you how I did this, but once you have worked through this chapter, you should be able to write a python program to subsample the data exactly as I have. Read the documentation Applanix provides documentation for the POSPac SBET files. It is essential to look at the documentation (if it is available) before starting to parse the data. The documentation might not be perfect, but it can save you tons of time (and likely frustration). FIX: reference the actual documentation FIX: table of the format. Initial look at an SBET file Before digging in to the details of parsing with python, lets use the command line and emacs to inspect what we have. First take a look at the file sizes. I am not going to provide the original file, but I have included it here so you can see how it differs from the small sample. sbet file. To download the file, you can save it from a web browser or pull it down in the terminal using curl or wget . You will just have the sample. sbet, but here I am showing you both the original and the smaller sample. sbet: It is often good to use the unix file command to see if it knows about a particular file type. Here we discover that file is not much help, but it does tell us that this is binary data. We can try to see if there is any embedded text later in the data, as file only checks a bit of the beginning of the file. The unix strings command will scan through a file and find sections that have 4 or more printable characters in a row. To avoid too much random junk that just happens to match the character codes of ASCII, we will ask string to return only matches of 6 or more characters much j Octal dump also has a mode where it will print out the special meaning of any bytes that might have special meaning. These are things like new lines (nl), start message (stx), end message (etx), and so forth. Unfortunately, there is nothing obvious about the format. The output here is not helpful. Better yet, Octal Dump has a mode that will try to treat the file as uniform binary data (for example, a series of 4 byte integers). Since we know that our SBET file will contain a series of 17 doubles (8 bytes each) in a row, lets try out a sample file that contains the numbers 0 through 16, It might look weird to you, but 1.40e01 is actually the number 14.0. We can now try to same thing on our sbet. Each datagram has 17 fields of 8 byte doubles for a total of 168 bytes. If we want to view the first two datagrams, we can ask od to print out just up to a certain byte count with the - n option. Two datagrams will be be 272 bytes. If we look at the first number from both datagrams, which is supposed to be a measure of time, we can see that the numbers are 3.349590048233234e05 and 3.350090035135288e05. Its hard to see, but it looks like time is moving slightly forward. This means we are on the right track. Its time to switch from the terminal to python Opening a file and reading the data in python There are several ways to open a file and access the data. Lets start with the simplest method. If you try this on a multi-gigabyte file, it will take a really long time, but in the case of a small test file, this is a great way to get started. Later, I will show you how to read the file a bit at a time and finally, I will show you a fancy method called mmap that can has the potential to greatly speed up your program. First, open the file. This will return a file object back to you that you can use to read or manipulate the contents of the file. FIX: link to python file object documentation FIX: this does not work in python3 There are many things you can do with a file, but in our case, we want to pull the entire file into a variable. Decoding values with pythons struct module We now have 22712 bytes in a string. We can start using the python struct module to begin decoding the file. Struct is designed just for our needs - going between python and binary data. We specify letter codes and python does the hard work of figuring out how to decode the bytes from the type. However, If we specify a type different than what is actually in the data, python will happily decode the data and give us back meaningless junk. Pack goes from python to binary and unpack goes from binary to python variable types. FIX: put in table of types Lets give it a try on the time field. d is for doubles and we want one double that takes up the first 8 bytes of the data. struct is designed to decode a whole bunch of values at the same time, so it returns the results in a tuple (unchangeable list). Note that you must pass in exactly the right number of bytes to unpack for the format codes that you give it, so we will pull a sub-array of the sbet data array with 0:8. The next two fields are the latitude and longitude in radians. Lets first grab the second two values at the same time. Being the 2nd double, the latitude will start at position 8. We then at 16 bytes on to the 8 to get the stopping position of the longitude. Reading latitude and longitude in radians is no fun. The math module has, among many other things, functions to convert between degrees and radians. Also, if you know how many values will be returned from a function call, you can specify that many variables before the equal sign and python will put the results into each variable in order. You can now go look at a map for 60.4N and 146.7W to see the area where the Fairweather was located when collecting this data. Since we have 17 variables, it can be annoying to do either 17 struct. unpack calls or write out 17 d characters in a string, so struct allows you to put a number before the d to specify the number of values you would like to decode. Here is the sample latitude and longitude example, but using 2d rather than dd. We can now try decoding all 17 variables. This is not so much fun. We can use the field names separated by commas to fill in all the variable. The character allows you to continue a line of code on to the next line. It is really hard to follow what is going on in that last python call to unpack. Rather than list out each field name, we can have python create a dictionary with named entries for each of our values. The last command needs some explanation. First here is what it returns: That is a python dictionary with each field stored by name. You might ask how the heck that works First the call to zip combines the list of field names and the list of values into paired entries. They have to be in exactly the same order. Here is an example with the first 4 entries in each: The python dictionary can be created by a sequence of key and value pairs (often referred to as k, v). You now have a dictionary that you can work with or pass around. You can do conversions and store them back into the dictionary and only have to pass around one thing. Creating a function that reads an SBET record A stub function Now that we have the basics of decoding a datagram down, we should turn it into a function so that we can reuse it in the future. Create a new file called sbet. py in your favorite text editor (in emacs: C-x C-f sbet. py). We are going to work on our function by using ipython to test it. Now start off by creating a file with a stub function that does not do anything real. stubs are things that are placeholders that do not do much if anything. The above python code creates one function that is started by the def for define function. decode is the function name. All functions have an argument list that is in the (). These are the variables that you will pass into the function. By having nothing in the parentheses, you are saying that the decode function does not let you pass anything to it. As we say in the previous chapters, block or groups of code are separated by indentation. Any change of the indentation either stops or starts a block. By indenting 4 spaces, I start a new function. You can use any indentation, but 4 is the convention in the python community. A python file can work exactly like the modules you have been using so far. Try importing it and kick the tires. With import it is important to notice that you leave off the. py. In our case here, be sure to start ipython in the same directory as you are putting the sbet. py and sample. sbet files. You now have a working module. It doesnt do much yet, but we will get there quickly. As you make changes to the python file, if you rerun the sbet. decode(), you will find that nothing changes. You need to reload the python file into ipython with the reload command. Change the file to match what I have here: The new first print line is not inside a function. It is there to show you that anything not inside a function (or later a you will see a class), will get run immediately. This is helpful here - we can see if the reload actually happened. Try a reload in ipython. Once you have reloaded the sbet. py module, you can now use the new version of the decode function. Getting data ready to parse Parsing means to pull apart some data or text into pieces that we can use locally. Think of writing a program to find all the words in a text document. The parser has to take the text and break into chunks separated by white space (new lines, space characters, or tabs) or punctuation. But before you can parse data, you need to load the data. We will use the simplest approach as described above. There are faster ways, but it is usually better to get a working program first before you try to make it go fast (call optimizing). We will put our controlling code into a function called main. Functions in a module (aka python file) can come in any order, but I put my main functions at the bottom of the file. This is just my personal style. Here is the program with the new main function that uses the open and read calls discussed previously. It still doesnt do anything useful, but we are getting closer Give it a try to make sure it works. You can see the prints at the beginning and ending of the main function. Now we need to pass in the data that we loaded in main to the decode function. We must add an argument to the decode function. The name of this argument has nothing to do with the name of what we pass in. What ever is passed in first will get assigned to the first argument inside the function. So here, the contents of the sbet data variable will get assigned to the data variable inside the decode function. It is also time to start doing a bit of documentation. Python has a mechanism called doc strings. If there is a string as the first line of a file, function, class, or class method, then python considers that string as the documentation for the class. In the above example, I have added a string right after the definition of the decode function. There are two ways to ask for help from ipython: the help command and appending a. after something: So we have documentation, but a function that doesnt do anything. I know you are getting impatient with me, so lets actually decode the first datagram in the SBET file. Here is the new decode function that actually does a little bit of decoding and prints the time, latitude/longitude in degrees. Since the decode function uses unpack from the struct library and degrees from the math library, we need to add an import statement to the top of the file. You might wonder why if we have done an import of math in ipython, why do we need it in the file imports only work in the context of the local module or python interactive session. Each module is independent and needs to tell python which modules it needs. We should now be able to reload the sbet module and try it out decoding actual data: This is pretty exciting We now have a file that we can use to redo a decoding. Its not very flexible, but it works. We need to work to improve it to be more useful. The first thing to do to make it more useful is to allow it to run from the command line. We can almost do that already, but not as easily as we would like. First quit ipython and get back to the bash terminal prompt. We can tell python to run a file: We need to add some special code that detects if the python is being run as a main program. There is a special trick in python to detect this case using the name variable. Add this line to your sbet. py file: If you import the module from ipython, name will be set to the name of the module: in this case sbet. Run ipython and import sbet. If you exit ipython to bash, and use python to run the sbet script, you will see that name has changed to main . Using this, we can add a check at the bottom of sbet. py to see if it is being run as a script. If so, we can right away start up the process of getting the script going. If sbet. py is imported, the code will not run, which is what we want because it will be some other codes job to use the functions in the sbet module. Then if we run the script using python from the bash prompt, it will actually call the main() function and get things going. It can be really annoying to have to remember to type python before the script all the time. You dont want to be required to tell other people which language the script uses any time they want to run it. There is a special mechanism that bash uses to see how it should run a script file: it checks the first line. If that line starts with a (pound bag), then bash will use the program listed after to run the rest of the file. The trouble is that we dont know exactly where python is installed on the computer. It might be in /bin, /usr/bin, or elsewhere. Plus the person might have changed their path to point to a different version of python that works better for them. We want to honor that choice. There is a unix command called env that is supposed to always be located in the same place. It looks at the path and finds the python interpreter. This is the recommended way to create a python script. Add this line to the very beginning of your sbet. py file. One more thing to fix. You have to tell the computer that the file is executable. Otherwise it will not think that it can run the file. The chmod command will let you set the permissions on the sbet. py file. After chmod is run, not the extra x characters for executable on the left side of the return from the ls command. Now you can run your sbet. py script without knowing that it is python inside. Before we go any farther, lets clean up the file and give it a look over. I have deleted extra print statements. Now lets change the decode function to get all of the fields as we did before. I am going to use the dict and zip method before, but if you are writing your own decoder for something else, you can certainly decode each field individually. Add the field names to your file before the decode function and change decode to look like this: I have change the printing of the result at the end to be easier to read. If we just print a dictionary, it will be a big mush. However, looping over a dictionary with a for loop will return the keys of the dictionary one by one. Try running the resulting program. Returning data from functions Really, when programming, it is a bad idea to mix the logic and data handling with the view or output of the program. What if you want to parse a datagram, but have no need to print it We should split the printing part into a separate program, but that means our decode function needs to return back what it figured out so we can pass it on. We need to change the main to look like this: To get the datagram information back from the decode function. The way to do that is to return the dictionary sbet values back at the end of the decode and to remove the printing. Then we need to take that printing code from before and make a function for it. I would use print as the function name, but that is already taken by pythons print, so I will call it sbet print . We havent done anything to how the script looks when it is run, but now we have a program that is a little bit more flexible. However, we now have the problem that we can only decode the first datagram. Being able to use the whole file It would be nice to be able to decode any datagram from the file that we would like. First, we need to modify the decode function to know where the datagram starts in the data. We can pass in a second argument to decode that tells it how far into the data we want it to look for the datagram. This is commonly referred to as the offset. We can also tell python that if decode is called without an offset, it is okay to start at the beginning of the file. This is done by setting offset to the default value of 0. Now we need to know how many datagrams are in the file and where each datagram starts. We need some helper functions to capture our knowledge of datagrams in the file. First, we need a function that will tell us how many datagrams are in file. We know that there are 17 parameters in a datagram and each one is 8 bytes long because the are double precision floating point numbers for a total of 136 bytes. We can save the datagram size as a variable and we will not have to remember the size. We use an assert to check the size of data. To do this use the remainder (also known as mod) operator: . We have to make sure that the remainder is always zero or we have a problem. After that, we can then divide the length of data by the size of each datagram. We can then modify the main function to print out just the total number of datagrams. The results of running the program now tell us something about the overall file. The next thing we need is a function that, given a datagram number, tells us the offset for that datagram. We can then pass that offset to the decode function. Give it a test with ipython. Now, in our main function, we can loop through each datagram index, calculate the offset to the datagram in the data variable, decode the datagram and print one line of summary data. The python range function will return a list starting at 0 and going up to the number given minus 1. Here, we have 167 datagrams, so range will return 0 to 166. Now, if we run the sbet. py script, it should tell us about the overall file To make sure you are all caught up, here is the entire sbet. py file as I have it now. Its up to 63 lines. Creating a Class Before we go adding lots of other features, it is time to clean up the handling of sbet files. In python, we can wrap the handling of an sbet file into a Class. For each sbet file that we work with, a class will create an object that can keep track of what we are doing with the sbet file as a thing. We can ask the thing to print itself, get the next datagram, etc. This is where we get to objected oriented programming (OOP). Dont worry what that is right now. You will learn by doing and start to get a feel for it as you see more examples in use. Start a new file called sbet2.py. Enter this in and then I will walk you through what is here. Now, make that file executable and give it a run. Lets start with the 3 lines starting with class . A class is a collection of functions, but when they are part of a class, they are termed methods . Class names by convention in python start with a capital letter. The (object) says that the Sbet class will get capabilities of the default python object. For now, just assume that it is required text for all your classes. There are a number of special methods that start and end with two underscores (). The first one is init. It is called when you create a new object of type Sbet and is called to handle instantiation of the instance of the Class. Confusing terminology, I know. You create an object like this: By running the program, you create an instance of an Sbet Class. The init gets called. The first argument to all methods in a class will be a copy of the object. In other languages, it might be called this, but self is the convention in python. The print type(self) returned a string of ltclass main. Sbetgt You can store data in self and init is the time to get things setup for later processing. We need to get the sbet file opened, read the data, and figure out how many datagrams are around. Here is how I would do that. While I am rewriting the previous code as a class, I am going to make it more flexible. The init can take extra arguments, so it is time to pass in the name of the sbet file. Hard coding file names like we did before is great for quick development, but it is bad to leave it in your code over the long run. I have moved the filename into the main function. Now we can start adding methods to the class to help us out. The first one we need is to bring back the decode method. Thats pretty important. We will have to bring back the imports of math and struct. Additionally, I will use the field names tuple (remember parentheses are for tuples and square brackets are lists), so put it into this new file. And add a call in main to the decode method on our lowercase sbet object. Notice that when I call struct. unpack, I passed it self. data instead of data. self. data goes back to the data that we saved back in the init method. Give it a try: We also would like to be able to get packets by index again, but it would be nice to do that without having to think about the decode method and offsets. We should add a get datagram method that takes the datagrams index number. Using what we have, we can recreate printing out a summary of the ship navigation in main. The results of this look just like before, but the python code is getting cleaner. Adding iteration / looping to the Class Python has a convention for making looping or iteration to be built into classes. This tries to simplify your overall code. For example, for loops should not have to keep track of the datagram index. Python does this for classes when you add two special methods: iter and next . Note: In python 2, it is just next, python 3 uses next. iter is the call that starts the iteration. We in this function, we need to record where we are in the data - starting at position 0. We then return the self back to the caller (e. g. the for loop). There are times when you want the iteration to be handled outside the class. Then in the next method, we have to check to see if we have reached the end. Python has a concept called exceptions that are useful for unusual events. Here the raise throws an exception of type StopIteration. This triggers the looping to end. Now we need to simplify our main function. The sbet object now can be iterated by a for loop. Each time through the for loop, the values that were returned in the next method get put into the datagram variable. Thats definitely simpler, but we have lost the count of the datagram. enumerate is a special function that takes an iteratable object and returns each element with a count before it. We can then just loop through the sbet and not worry about which datagram we are at. It runs just like before: Adding Google Earth KML export Its time to add a first try at a Google Earth KML export. First, here is an example of a line with three points in KML. KML is a form of the Extensible Markup Language (XML ). The key to XML is that everything in the file starts with a beginning tag (e. g. lttaggt) and finishes with a matching end tag (e. g. lt/taggt). You will see a large number of angle brackets in XML files. Do not worry too much about the details of XML and KML. The key thing to observe is that there is a ltcoordinatesgt lt/coordinatesgt block that contains longitude and latitude pairs (e. g. x, y). Be careful that you dont do y, x (aka lat, lon). If you save that KML into a file called test. kml and open it in Google Earth, you will see that the program will fly to Alaska and show you a very short line. We now want to write KML will all of the points in an SBET from our Sbet python class. We do this by splitting the task into three sections. First we add the KML from the beginning line to the ltcoordinatesgt tag. Next, we will add all of the x, y points for the sbet datagrams one line at a time. Finally, we will add the text for lt/coordinatesgt to the final lt/kmlgt. Lets add a new kml method to our Sbet class. The design of our kml function is that it will return a string with the KML in it. In python, the operator appends a string on to an existing string (aside: it creates a new longer string and assigns it to the old variable name). Also the triple quote ( ) allows for strings that span multiple lines. We can now write the header. The outstr ( output string ) variable will now return the first part of the KML. We can now use a for loop iterator like we did before to get all the coordinates. After we add the for loop, we can also add the footer to finish the KML. That gives a compete KML generation method, but it wont go anywhere until we use it. Lets change the main() function to get the KML string and write it to a file. If you run sbet2.py, you should now see a sample. kml file. On the mac, you can use the open command to view the new KML file with the ship track. Going faster with partial reads (read(numbytes), seek, tell) Our sample file is small, but if we were working on a typical SBET file, it would be hundreds of megabytes or bigger. Reading all that data into memory at one time is not very efficient. FIX: write an example with read and demonstrate seek and tell. Going faster with mmap Most people will try to switch their code to using partial reads combined with seek and tell commands to step through the file. The problem is that, there is a lot of copying of data going on when the data is read in. Now: REMOVE your code that does partial reads. You can save it somewhere, but we will not use it. Modern operating systems have a special concept called a memory map or mmap. This style of loading data lets the operating system work with python rather than have python copy everything into local storage. The operating system can load and unload the data behind the scenes as needed and the data in the file magically appears in the programs memory. Only data that is needed is paged into RAM from the disk. mmap is weird to use, but you can hide it in the class. One word of caution If you are using a 32-bit operating system, you may run into troubles with reading files bigger than 2 GB and you will definitely have problems with files bigger than 4 GB. This comes from a limitation of being able to address that much memory at one time. The best solution to get around the problem is to upgrade to a 64-bit operating system (and make sure you are using a 64-bit version of python). If that is not possible, you will need to break your file into 2GB or smaller files. We have to use a fileno, which is a number that identifies our open file and the length of the file. We also want to specify the access control and tell mmap that we want to open the file as read-only. That way we cant accidentally modify the file. Our new initializer looks like this: Python makes it easy to switch between either style at run time, so I have made the mmap style of loading the data be the default with the argument usemmap that defaults to True. Checkpoint - what does the whole file look like here FIX: insert a python file that matches all that was done above. Another improvement - a better iterator Before we add more features to the class, we need to improve the iterator. The trouble with our current design is that there can only be one iterator at a time. Each iterator should be independent so that programmers do not have to worry about stepping on their own tows if they need to loop over all or part of the file. The way to do this is to pull the iterator out of the Sbet class and have a separate iterator class that handles looping over the datagrams in an Sbet object. At this point, I am going to start over in a new file called sbet3.py. Here is the whole file rewritten to have a separate iterator class. FIX: walk through how the SbetIterator class works keep a reference to the sbet object set the datagram index ( iterposition ) to the beginning of the file Loop through the file in next and throw the exception StopIteration when it gets to the end of the file Creating a summary method

No comments:

Post a Comment