Wednesday, 18 April 2018

Fórum de bala de opções binárias


À prova de balas Forex.
Procurando Forex à prova de balas? Você deve ver isso!
Tagged with forex forum
forex fx trader.
forex fx trader.
Em um padrão crescente entre os agentes, a Sydney Professional Benefits FX junta-se à lista de empresas que incluem atualizações para o produto MT4. Essas atualizações são instantaneamente configuradas com a aquisição exclusiva e não requerem atividades adicionais por parte de seus clientes. A atualização existente permite que um basicamente simplesmente clique em trabalhar, basicamente simplesmente clique em parte e a cópia do veículo está funcionando. Um basicamente simplesmente clicar no trabalho é talvez a operação mais necessária dos clientes para o MT4, pois, na sua forma padrão, a base de trabalho não possui esta operação básica e amplamente disponível. Até recentemente, os comerciantes que esperavam que um simplesmente simplesmente clique em trabalho precisasse configurar uma EA na base do lado do cliente para habilitar essa habilidade. O trabalho de cópia funciona após a saída dos sinais de trabalho anunciados ontem à noite para o MT4.
Além dos recursos de acesso a pedidos, o Benefits FX também anunciou que envolveu escolhas de trabalho binárias para sua base MT4. De acordo com um associado de Benefícios FX, não só a base MT4 se tornará um programa para negociação de trabalho FX e de opções binárias, mas os clientes podem oferecer os dois produtos simultaneamente de uma preocupação. O MT4 opera além da base independente que o Benefits FX também oferece para escolhas de trabalho binárias.
Atualmente, a Benefits FX está fazendo pouco em seu site para negociar as escolhas binárias. Portanto, será emocionante ver se o novo fornecimento começará a ser comercializado como seu próprio produto ou será basicamente um envolvido operado visando melhorar sua oferta FX existente; semelhante ao fornecimento de CFDs.
Organização de negociação de Forex de Sydney moderna Benefícios A FX produz nova e surpreendente diferença do MetaTrader 4.
Nov 2012 - sydney moderno, na Austrália.
Principais Benefícios da Moderna Sydney A organização Forex Deal Benefits lançou uma versão nova e significativamente desenvolvida de sua base MetaTrader 4 (MT4).
A atualização tem uma série de novos e excitantes recursos criados diretamente no aplicativo MT4 existente, agora com trabalho com um clique, trabalho de cópia automática e um clique em parte próximo. A base melhorada foi projetada com uma interface de usuário ainda mais fácil de usar, juntamente com uma série de ferramentas de trabalho inovadoras, novas imperfeições de sinais personalizáveis ​​e um cpanel personalizado.
Em um mundo-primeiro, o novo MT4 da Benefits FX também oferece aos comerciantes nenhum custo de admissão 24 horas para opções binárias trabalhando diretamente no MT4. Todos os clientes não terão admissão de custo para verificar binários sem ter que se afastar da base. Todos disponíveis permanecem em tempo real, especialmente benéficos para 60 Second Binary Options working.
forex fx trader,
leo comerciante pro fórum,
bot de crescimento forex,
leo trader pro ea,
"A nova base permite uma melhoria da experiência geral do cliente para todos os clientes, seja na verificação ou permaneça no ambiente de trabalho", disse Antony Goddard Handling Home of Benefits FX. "Os comerciantes que se sentem confortáveis ​​com o MT4 antigo estarão felizes em saber que a base preserva todo o desempenho existente da compilação mais antiga. A nova base dará aos clientes a capacidade de gerenciar suas preocupações de trabalho com mais facilidade do que nunca ".
Esta qualidade dos sistemas de trabalho de forex, juntamente com as taxas de performance de negociação de Forex do IBTimes 2012 da Benefits FX's, os custos extremamente competitivos e a premiada equipe de suporte líder de 24 horas, fazem com que o provedor de Sydney seja um dos mais adequados na indústria .
Uma versão de checagem completa do MetaTrader 4 está disponível para que os comerciantes adquiram agora. Esta versão de verificação de 30 dias é uma expressão do ambiente de trabalho restante e irá mostrar-lhe uma réplica exata em relação ao desenvolvimento e desempenho da empresa. Inscreva-se para receber uma solicitação gratuita de avaliação de US $ 20.000 hoje, juntamente com uma cópia gratuita de e-book gratuita do "Guia individual do MetaTrader 4" aqui.
Sobre os benefícios FX.
Benefícios A FX é uma empresa de serviços econômicos de alto padrão da Sydney, que oferece habilidades operacionais Forex on-line para clientes de lojas, clientes de alto patrimônio e institucionais em todo o mundo. Este ano, os Benefícios FX são os vencedores do Melhor Desempenho de Negociação em Forex (Prêmio de Negociação do IBT na Ásia para o Havaí), Melhor Corretor de Negociação em Forex & amp; Forex Deal Performance House - Sul do Sul do Japão (The DealMakers Annually Financial Awards) e Melhor Forex que negocia a Agência Australasia (World Finance Foreign Exchange Awards).
Benefícios A FX está constantemente determinada a fornecer uma experiência de negociação de Forex, completamente interessante e amigável ao cliente. Como uma equipe, sempre procuramos inovar e fazer a tecnologia mais inovadora, transmitindo os benefícios aos nossos clientes. Benefícios A FX é uma Corporativa Autorizada Associada a Enfinium Pty Ltd (AFSL N ° 322081 e controlada pela Sydney Internacional, oportunidades de compromisso financeiro e Percentagem de oportunidades de compromisso financeiro (ASIC).

Por que Gazebo?
A simulação de robô é uma ferramenta essencial na caixa de ferramentas de todos os roboticistas. Um simulador bem projetado torna possível testar rapidamente algoritmos, projetar robôs, realizar testes de regressão e treinar sistemas de IA usando cenários realistas. O Gazebo oferece a capacidade de simular com precisão e eficiência as populações de robôs em ambientes internos e externos complexos. Ao seu alcance está um motor robusto de física, gráficos de alta qualidade e interfaces programáticas e gráficas convenientes. O melhor de tudo, Gazebo é gratuito com uma comunidade vibrante.
O mais recente.
Lançamento do Gazebo 9.0.0.
Liberar destaques.
Gazebo 9 Ilhas rosqueadas paralelas em ODE Sombras aprimoradas Reflexo de lente de câmera Anexar luzes a links Plugin de joystick (a ser lançado na versão 9.1.0) Plugin de compensação de gravidade Ignição CMake 0.4 Versão beta de um conjunto consolidado de scripts CMake. Ignition Math 4 Classe e algoritmos gráficos Ignition Msgs 1 & Ignition Common 1 Primeira versão 1.0 de ambas as bibliotecas. Transporte de ignição 4 Zero-copy on publish. Suporte para publicação e recebimento de bytes brutos. Autenticação básica para tópicos.
Estamos orgulhosos de anunciar o lançamento do Gazebo 9. Esta versão do Gazebo tem suporte de longo prazo com um fim-de-vida em 25 de janeiro de 2023.
Um esforço contínuo ao longo dos últimos anos tem sido separar as bibliotecas internas da Gazebo em um conjunto de bibliotecas sob o projeto Ignition Robotics. Essas bibliotecas afastarão o Gazebo de uma grande base de código monolítica. Um objetivo adicional é aumentar a transparência do desenvolvimento e a adoção de recursos que podem ter sido escondidos por trás do véu do Gazebo.
Embora ainda esteja nos primeiros estágios de desenvolvimento, algumas das bibliotecas da Ignition estão prontas para um amplo consumo público. Essas bibliotecas incluem Ignition Math, Messages e Transport. Bibliotecas mais altas na pilha de dependências, como Rendering, Sensores, Física e GUI, verão o progresso em direção a versões 1.0 durante este ano.
O roteiro de 2018 para as bibliotecas Gazebo e Ignition estará disponível nas próximas semanas.
As seções abaixo descrevem alguns projetos com um pouco mais de detalhes. Aproveite o novo lançamento e obrigado por todas as contribuições,
Equipe de Desenvolvimento do Gazebo.
Plataforma de Documentação de Ignição Robótica.
Uma plataforma de documentação atualizada foi criada para a Ignition Robotics na ignitionrobotics. Este site detalha as bibliotecas disponíveis, juntamente com uma breve descrição de cada uma e links para documentação e tutoriais da API, que são escassos neste momento. Um histórico de versões para cada biblioteca também é exibido com links para a documentação da versão.
Combustível de ignição.
Na época do DARPA Robotics Challenge, a Gazebo enfrentou o problema de onde e como hospedar modelos de simulação e ativos relacionados. Na época, optamos por usar um repositório Bitbucket junto com um clone suportado pelo Apache.
Desde então, o Gazebo superou a abordagem do Bitbucket e do Apache. Os principais problemas que encontramos são escalabilidade, tempo de atividade, hospedagem de metadados, inclusão de mundos e outros ativos e facilidade de uso. Depois de estudar as opções disponíveis, como usar o S3, decidimos fornecer um novo serviço de hospedagem de ativos de simulação chamado Ignition Fuel.
Ignition Fuel está em Beta e não substitui a solução Bitbucket + Apache existente. Quando o Fuel sair da versão beta, haverá um longo período de transição em que ambas as soluções de hospedagem estarão ativas e mantidas. O horário exato será determinado quando estivermos confortáveis ​​com o estado do combustível.
No Ignition Fuel, você encontra uma lista de modelos disponíveis. Fazer o login no site permite que você faça o upload de novos modelos. Também há informações sobre como acessar os modelos programaticamente por meio de uma API REST. O Gazebo 9, opcionalmente, usa essa API para listar e baixar modelos do Fuel. Na seção de tutorial do Ignition Fuel Tools, você pode encontrar exemplos de como gerenciar modelos de um servidor de combustível programaticamente.
A principal diferença entre o Fuel e outros sites de hospedagem de ativos é que os modelos hospedados no Fuel contêm não apenas informações visuais, mas também informações de simulação, como links, articulações e inércia. O combustível também avançará para a inclusão de mundos e potencialmente plugins de simulação.
Destaque de transporte de ignição.
Gazebo faz uso pesado de passagem de mensagem assíncrona. Por exemplo, a GUI do Gazebo opera em um processo separado do servidor e depende da passagem de mensagens para exibir informações e transmitir solicitações do usuário. A atual comunicação interna da Gazebo usa uma estratégia nacional baseada em Protobuf e boost :: asio. Isso funcionou bem, mas requer manutenção e ficou um pouco desatualizado.
O desenvolvimento do transporte de ignição proporcionou a oportunidade de escolher uma nova estratégia que reduziria nosso esforço de manutenção e ofereceria novos recursos. O ZeroMQ foi escolhido como substituto do boost :: asio, e o Protobuf permanece como a definição da mensagem. O ZeroMQ é uma biblioteca de comunicação de código aberto que é usada em vários domínios e tem uma comunidade grande e ativa. Além desses aspectos, o ZeroMQ tem um recurso bem estabelecido e um processo de mudança, desempenho conhecido, várias vinculações de idioma, suporte a várias plataformas e segurança por meio de autenticação e criptografia.
Além dos recursos fornecidos pelo ZeroMQ, o Ignition Transport fornece ferramentas de descoberta e de linha de comando para introspecção de tópicos e publicação de mensagens. Os recursos futuros incluem registro de dados e integração de criptografia e UDP fornecidos no ZeroMQ. Recentemente, uma série de testes de referência do Ignition Transport foi realizada para avaliar o desempenho da biblioteca e estabelecer uma linha de base. Vamos começar com algumas definições para maior clareza. Intraprocesso: Publicador e assinante no mesmo processo. Interprocessar: Publicador e assinante em processos separados na mesma máquina física. Wireless: Publicador e assinante em máquinas separadas em que um computador estava conectado ao ponto de acesso sem fio e o outro à rede. Latência: A latência foi medida publicando uma mensagem no tópico A e aguardando uma resposta no tópico B. O tempo entre a publicação e a recepção da resposta foi dividido ao meio para calcular o tempo de latência unidirecional. Taxa de transferência: a taxa de transferência foi medida publicando rapidamente N mensagens. Depois que as N mensagens forem publicadas, o editor aguarda N respostas. O tempo desde o início da publicação até a recepção de todas as N mensagens é usado para calcular a taxa de transferência.
Os testes foram realizados no Ubuntu Xenial com o kernel Linux 4.5.2, em um PC de mesa Intel i7-5930K. O programa de testes, chamado de banco, está disponível publicamente. Use a opção de linha de comando `-h` com banco para informações de uso. Os resultados de latência e throughput estão abaixo. Clique no rótulo do conjunto de dados, como "Interprocessar", para ativar ou desativar os dados.
Estes resultados podem ser usados ​​como um ponto de referência, mas não são de forma alguma um estudo exaustivo ou abrangente do Transporte de Ignição.
Links Úteis.
Encontre respostas e faça perguntas.
Junte-se a discussões e anúncios.
Modelos de Simulação.
Robôs, objetos e outros modelos de simulação.
Código fonte.
Obtenha o código-fonte do Gazebo.
Simulação Dinâmica.
Acesse vários mecanismos de física de alto desempenho, incluindo ODE, Bullet, Simbody e DART.
Gráficos 3D avançados.
Utilizando o OGRE, o Gazebo fornece renderização realista de ambientes, incluindo iluminação, sombras e texturas de alta qualidade.
Sensores e Ruído.
Gere dados de sensores, opcionalmente com ruído, de buscadores de alcance a laser, câmeras 2D / 3D, sensores estilo Kinect, sensores de contato, torque de força e muito mais.
Desenvolva plugins personalizados para robô, sensor e controle ambiental. Plugins fornecem acesso direto à API do Gazebo.
Modelos de robôs.
Muitos robôs são fornecidos, incluindo PR2, Pioneer2 DX, iRobot Create e TurtleBot. Ou construa o seu próprio usando o SDF.
Transporte TCP / IP.
Execute a simulação em servidores remotos e faça a interface com o Gazebo por meio de passagem de mensagens baseada em soquete usando o Google Protobufs.
Simulação de nuvens.
Use o CloudSim para executar o Gazebo no Amazon AWS e no GzWeb para interagir com a simulação por meio de um navegador.
Ferramentas de linha de comando.
Extensas ferramentas de linha de comando facilitam a introspecção e o controle da simulação.
Iniciar.
Molhe os pés.
Um simples conjunto de passos para colocar o Gazebo em funcionamento rapidamente.
Descrição das interações de teclas de atalho e mouse do Gazebo.
A melhor maneira de começar a usar o Gazebo é percorrer os tutoriais. Estes tutoriais cobrem conceitos básicos e simples através de uma série de exercícios.
Confira os exemplos de mundos e programas que estão no código-fonte.
Se você não encontrar o que está procurando, experimente nosso fórum de ajuda sobre askbot localizado em answers. gazebosim.
Quer trocar ideias com o resto da comunidade? Venha para community. gazebosim.
Fontes de informação.
Uma descrição de alto nível do Gazebo e seus vários componentes.
Documentação gerada pelo Doxygen para as bibliotecas do Gazebo.
Uma lista completa de todas as mensagens do protobuf usadas pelo Gazebo.
SDFormat é um formato de arquivo XML que define ambientes e modelos. Esta especificação define todos os elementos XML para descrever o mundo e os modelos.
Status do projeto.
Gazebo 10.0 Progresso.
Lançamento de cronograma e roteiro.
A Gazebo lançará uma nova versão principal uma vez por ano na última semana de janeiro. Lançamentos pares numerados terão uma duração de dois anos e cinco anos ímpares.
O roteiro a seguir é o melhor palpite para os recursos disponíveis para cada versão. No momento da liberação, mais ou menos recursos podem estar disponíveis.
Consulte a documentação em aplicativos downstream, como o ROS, para compatibilidade de versão.
Gazebo 1.9 2013-07-24 EOL 2015-07-27.
Divida o SDFormat em um pacote separado Suporte aperfeiçoado ao ROS Sensor de sonar, torque forçado e sensores de pressão adicionados Permite que a câmera do usuário siga os objetos Suporte básico ao OS X.
Gazebo 2.2 2013-11-07 EOL 2016-01-25 Ubuntu P, Q, R, S.
Mapas de sombra aprimorados Paredes quebráveis ​​Visualize o momento de inércia Redimensione graficamente formas simples Modelos de sensores transceptores sem fio Suporte de áudio OpenAL Paginação de terreno.
Gazebo 3.0 2014-04-11 EOL 2015-07-27 Ubuntu P, R, S, T.
Ferramenta de linha de comando unificada Mapas de luz para melhorar o realismo de renderização Formas simples e destrutivas Importar DEM Dividir nos pacotes da Debian, passando para a inclusão do suporte ao Bullet Beta da Gazebo Beta OSX.
Gazebo 4.0 2014-07-28 EOL 2016-01-25 Ubuntu P, S, T.
Modelos de suspensão de veículos Mais tutoriais e documentação Suporte Oculus Rift Suporte a Razer Hydra Copie e cole modelos via GUI Texturas de estrada personalizadas Suporte DART 4.1 Nova geometria de polilinha extrudada Animações de ator fixas Adicionada classe KMeans.
Gazebo 5.0 2015-01-26 EOL 2017-01-25 Ubuntu T, U, V.
Suporte à sobreposição da GUI de integração do C ++ 11 Simulações de execução do clone Editor de construção aprimorado Interface de Javascript.
Gazebo 6.0 2015-07-27 EOL 2017-01-25 Ubuntu T, U, V.
Suporte do Windows, ao compilar a partir da fonte Suporte a plugins de hidrodinâmica Oculus 2 Plugins de aerodinâmica aprimorados Múltiplos perfis físicos por mundo Aplicar forças e torques através da GUI Importar formas através da extrusão de arquivos SVG Suporte de bitmask de colisão em SDF Plugins de elevador e teleport na velocidade da junta.
Gazebo 7.1 2016-01-25 EOL 2021-01-25 Ubuntu T, V, W.
Modelos aninhados Integração com a matemática do aprimoramento Aprimore a documentação para usuários iniciantes Melhoria na gravação e reprodução de log Ferramentas de design de GUI, como cortar / copiar / colar e desfazer Sensor de câmera grande angular Atrito de torção Classe da bateria e plug-in.
Gazebo 8.2 2017-12-10 EOL 2019-01-25 Ubuntu X, Y.
Utilitário de plotagem de GUI e editor de modelo de GUI de instruções do sistema Generalização de animações de ator Suporte a QT 5 Importar arquivos OBJ Suporte para simulação de vento Quadcopter Gravação de vídeo incorporada.
Gazebo 9.0 2018-01-25 EOL 2023-01-25 Ubuntu X, A.
Plugin de compensação de gravidade Integração do DART 6 com loops cinemáticos fechados Integração com o Ignition Fuel Plug-in do joystick Parallel threaded islands no ODE Sombras aprimoradas Reflexo da lente da câmera Conecte as luzes aos links.
Gazebo 10.0 2019-01-24 EOL 2021-01-24.
Importar arquivos de malha FBX GUI movie maker Contorno GUI editor Physics plugin API Integração Hydrax para melhor simulação de água Pipeline de renderização foto-realista Geometrias de referência para alinhamento de links com restrições cinemáticas Console GUI (mensagens do servidor de exibição) Graficamente redimensionar inércias e suporte para portáteis Integrar simulação de rede (ns-3 ou EMANE) Formas de deformáveis ​​Retroceder e repetir simulação Simulação de vento Interfaces de scripts Melhorar o suporte a SDF / URDF Ferramentas de linha de comando para Ignição Ferramentas Visualizar estado do plug-in Salvar o estado do plug-in para arquivos de log Controladores quadcopter com simulação Instalação binária OSX Instalação binária do Windows Ferramenta gráfica para auxiliar na validação de física Quebrar biblioteca de renderização para Ignition Rendering Break out biblioteca comum para Ignition Common Update Integração Cloudsim Ignition Transport.
Gazebo 11.0 2020-01-29 EOL 2025-01-29.
Em tutoriais de GUI Navegação global e local para robôs móveis Integração do suporte ao MoveIt e / ou Reflexxes Constructive Solid Geometry no editor de modelos.
Versão.
Ciclo de Liberação Tick-tock.
Um ciclo de lançamento de tick-tock permite fácil migração para novas versões de software. O código obsoleto do Gazebo está marcado como obsoleto para uma versão principal. O código obsoleto produz avisos em tempo de compilação. Esses avisos servem como notificação para os usuários de que seu código deve ser atualizado. A próxima versão principal removerá o código obsoleto.
Exemplo em que a função foo é reprovada e substituída pela barra de funções:
Suporte do Motor de Física.
O Gazebo suporta os motores físicos ODE, Bullet, Simbody e DART. Por padrão, o Gazebo é compilado com suporte para ODE. Para usar os outros motores, primeiro verifique se eles estão instalados e, em seguida, compile o Gazebo a partir da fonte.
Estamos desenvolvendo uma estrutura de plugins de física para resolver problemas de dependência. Cada mecanismo de física fará a interface com o Gazebo por meio de um plug-in, evitando a necessidade de compilar o Gazebo com suporte para cada mecanismo.
O desenvolvimento do mirante começou no outono de 2002 na Universidade do Sul da Califórnia. Os criadores originais foram o Dr. Andrew Howard e seu aluno Nate Koenig. O conceito de um simulador de alta fidelidade surgiu da necessidade de simular robôs em ambientes externos sob várias condições. Como um simulador complementar ao Stage, o nome Gazebo foi escolhido como a estrutura mais próxima de um palco externo. O nome ficou preso apesar do fato de que a maioria dos usuários do Gazebo simula ambientes internos.
Ao longo dos anos, Nate continuou o desenvolvimento do Gazebo ao completar seu PhD. Em 2009, John Hsu, engenheiro sênior de pesquisa da Willow, integrou o ROS e o PR2 ao Gazebo, que desde então se tornou uma das principais ferramentas usadas na comunidade ROS. Alguns anos depois, na primavera de 2011, a Willow Garage começou a fornecer suporte financeiro para o desenvolvimento do Gazebo. Em 2012, a Open Source Robotics Foundation (OSRF) saiu da Willow Garage e tornou-se a responsável pelo projeto Gazebo. Após um esforço significativo de desenvolvimento por uma equipe de talentos, a OSRF usou o Gazebo para executar o Virtual Robotics Challenge, um componente do DARPA Robotics Challenge, em julho de 2013.
OSRF continua o desenvolvimento do Gazebo com o apoio de uma comunidade diversificada e ativa. Fique atento a desenvolvimentos mais interessantes relacionados à simulação de robôs.

Meus maiores erros de negociação de opções binárias & # 8211; Leia e evite.
Nós todos os erros, aqui estão os meus. Leia, aprenda, evite!
Se por algum meio inexplicável você pudesse voltar e mudar uma coisa relacionada à sua negociação, o que seria isso? Espere, vamos torná-lo ainda melhor: se você pudesse desfazer três erros, quais você escolheria? Vamos lá, não seja tímido, todos nós erramos às vezes. É claro que essa maneira inexplicável de viajar no tempo não está disponível para nós, por isso não podemos consertar nossos erros, mas talvez este artigo ajude os novatos a evitarem os mesmos. Bem, eu fiz tantos que é bem difícil escolher os três maiores, mas aqui vai:
1. A falácia dos 60 segundos.
Eu realmente estou escrevendo isso durante a noite ... eu não conseguia dormir então achei melhor levantar e fazer algo útil do que apenas deitar na cama pensando em negociar (sim, é isso que Eu faço quando não consigo dormir). Uma xícara de café à minha direita, cinzeiro à minha esquerda (fumar é ruim, eu sei, mas eu estou usando um adesivo de nicotina tentando chutar esse hábito) e meu gato comendo minhas plantas da casa (eu gostaria que houvesse um remendo para isso…) então tudo está dentro dos parâmetros normais, exceto a falta de sono. Mas mesmo sem descanso suficiente, é fácil ver o grande erro que cometi ao entrar em 60 segundos. É verdade que eu não troco mais dessa forma, mas devo admitir que, pela primeira vez, fui tentado pela oportunidade de lucros tão rápidos e tentei. Eu até tive algum sucesso… claro que não foi por causa das minhas “habilidades analíticas”, mas sim devido a uma combinação de sorte e algum movimento forte do mercado. No momento em que percebi que não posso prever consistentemente o resultado da próxima vela de um minuto, também foi a última vez que coloquei uma negociação de opção binária de 60 segundos. O importante é que ganhar dinheiro com esse tipo de negociação é perfeitamente viável e viável (o que nos atrai), mas o principal problema é a consistência. Ganhar algum dinheiro hoje não me ajuda se eu vou devolver tudo amanhã. Tudo o que falta consistência na negociação está fadado ao fracasso, mais cedo ou mais tarde, então sim, é possível ganhar dinheiro com 60 segundos ... mantê-los é o desafio.
2. A planilha do Excel.
Metaforicamente falando, a planilha é a coisa que nos faz avançar e mantém o sonho vivo. Em uma nota mais realista, é apenas ... uma planilha do Excel que contém um cálculo de como nossa conta ficará se continuarmos fazendo uma determinada porcentagem a cada semana, mês ou ano e aumentando nossos ganhos. Com & # 8220; apenas & # 8221; 15% adicionados à sua conta todo mês você ganhará um milhão de dólares em alguns anos e a planilha do Excel faz com que pareça fácil, mas não considera outros fatores, como o aspecto psicológico. Medo, ganância, dúvida, perda de listras, interferência do corretor, nada disso é contabilizado na planilha, de modo que o objetivo de alcançar o seu sonho se torna um pouco mais próximo, mas não se apaixona por ele, como eu fiz. Negociar com todos os seus aspectos é muito diferente do que uma planilha do Excel faz você acreditar e eu aprendi da maneira difícil e decepcionante; anos se passaram e minha conta não estava onde minha planilha dizia que seria. A única coisa é que você tem que tratar cada negócio como se sua conta inteira dependesse disso e não pensar em quanto dinheiro uma planilha do Excel diz que você vai ter em um ano ou 5.
3. Broker Madness.
Nós todos sabemos que os golpistas atormentam a indústria de Opções Binárias e dão a ela um nome ruim. Bem, eu não sabia quando comecei a negociar e me depositei com o primeiro corretor com quem entrei em contato. Sites como o binaryoptionsthatsuck eram quase inexistentes naquela época e eu não me incomodei em ler os Termos e Condições do corretor… era muito trabalho e eu estava muito ocupado ficando rico para prestar atenção aos sinais de um possível golpe ou mau corretor . Eu pensei que o bônus é um presente de boas-vindas, não que ele vai amarrar meu dinheiro à sua plataforma; Eu pensei que o gerente de contas é realmente um bom operador que quer que eu fique rico. Grande erro, mas nunca cometi outro.
Erro cometido, lição aprendida.
Eu aprendi da maneira mais difícil não cometer esses erros novamente e paguei pelos três. Espero que tudo o que você pagará seja apenas atenção aos meus erros e você os evitará no futuro. Se você é um novo operador ou um mais avançado, não faça nenhum dos meus erros e lembre-se das palavras de Otto von Bismarck: Apenas um idiota aprende com seus próprios erros. O homem sábio aprende com os erros dos outros.
Comecei a negociar Opções Binárias com Opções RB, no Canadá. Deposite $ 1000. A & # 8221; Pro & # 8221; contactou-me e disse que ele vai negociar para mim. Eu estava cético e ele fez algumas trocas vencedoras. Então ele pediu que eu aumentasse o financiamento e, nesse momento, a maioria de seus 5 negócios venceu. Então, eu depositei mais dinheiro até o saldo da minha conta ser de $ 11800. Então o & # 8221; Pro & # 8221; Andy Goldman & # 8217; as negociações começaram a perder até que ele colocou 14 negociações e 4 ganhou 1 empatado e 9 derrotas. Os negócios que ele sugeriu foi, por exemplo. um PUT em Bitcoin / Bitstamp por US $ 2500 o saldo da conta foi inferior a US $ 5000 na época. Eu questiono seu ofício e ele respondeu: & # 8221; "Mesmo se você está perdendo alguns dias de negociação, eu estou fazendo para você Money Management & # 8211; e essa é a maneira real de ganhar dinheiro, meu amigo, e não WIN RATE ”.
POR FAVOR, FIQUE LONGE DESTE CORRETOR E SEU PRO ANDY GOLDMAN.
Obrigado por admitir e depois compartilhar seus erros. Eu tentei o material de 60 segundos. $ 1 dólar por comércio, perdeu alguns, ganhou alguns. Cheguei à mesma conclusão, pelo menos impossível para mim, de ser coerente com eles. Meh, levemente divertido, mas basicamente jogando. Loucura dos corretores, hoje eu me esquivei da bala.
Apenas devido às informações deste site, então 5.000 obrigado a todos no BOTS.
Agora, o mais difícil, novamente para mim, é o Excel. Tendo ensinado o Excel aos adultos iniciantes, o poder e a diversão de projetá-los, às vezes, foram uma explosão. No entanto, acredito que qualquer planilha, banco de dados (Filemaker Pro qualquer um) com base em informações futuras é nada mais do que, no máximo, motivacional. As planilhas baseadas em informações atuais também não são preditivas de sucesso futuro, mas ajudam a mostrar seus resultados atuais.
Talvez eu ainda tenha uma pergunta: como as minhas opiniões citadas acima me colocariam em problemas, desde que eu não deixasse que mudasse o meu sistema de gerenciamento de dinheiro e usasse apenas para desempenho passado para me concentrar na otimização de estratégias?
Obrigado novamente por este artigo na escola.
Por favor, aguarde 24-72 horas para rever o seu comentário.
Reservamo-nos o direito de decidir qual comentário será publicado.
Para perguntas sobre corretores - use nossos fóruns.
Para reclamações detalhadas - Por favor, use o nosso sistema de reclamações na página inicial.

Fórum bullet de opções binárias
Esta página contém um monte de fragmentos de códigos Python diversos, receitas, mini-guias, links, exemplos, tutoriais e idéias, variando de coisas muito (muito) básicas a avançadas. Espero que eles sejam úteis para você. Todos os trechos são mantidos em uma única página HTML para que você possa facilmente & # 10102; salvar para leitura offline (e manter uma chave USB) & # 10103; pesquisar nele.
Note que os scripts que fazem algum web-scraping podem não funcionar mais devido a mudanças no website. A web é uma fera em evolução :-)
(Não se esqueça de ler minha página principal do Python (sebsauvage / python /): há alguns outros programas e guias.)
Envie um arquivo usando o FTP.
session = ftplib. FTP ('myserver', 'login', 'passord') # Conecta ao servidor FTP.
myfile = open ('toto. txt', 'rb') # Abre o arquivo para enviar.
session. storbinary ('STOR toto. txt', myfile) # Envia o arquivo.
myfile. close () # Fecha o arquivo.
session. quit () # Fechar sessão FTP.
Filas (FIFO) e pilhas (LIFO)
Python faz uso de filas e pilhas de um pedaço de bolo (eu já disse "pedaço de bolo"?).
Não adianta criar uma classe específica: basta usar objetos de lista.
Para uma pilha (LIFO), pilha com append () e destack com pop ():
Para uma fila (FIFO), enfileire com append () e desenfileire com pop (0):
Como as listas podem conter qualquer tipo de objeto, você cria filas e pilhas de qualquer tipo de objeto!
(Observe que há também um módulo Queue, mas é principalmente útil com threads.)
Uma função que retorna vários valores.
Quando você não está acostumado com o Python, é fácil esquecer que uma função pode retornar apenas qualquer tipo de objeto, incluindo tuplas.
Isso é ótimo para criar funções que retornam vários valores. Esse é tipicamente o tipo de coisa que não pode ser feita em outros idiomas sem alguma sobrecarga de código.
Você também pode usar designação múltipla:
E, claro, suas funções podem retornar qualquer combinação / composição de objetos (strings, integer, listas, tuplas, dicionários, lista de tuplas, etc.).
Trocando o conteúdo de 2 variáveis.
Na maioria das linguagens, a troca do conteúdo de duas variáveis ​​envolve o uso de uma variável temporária.
No Python, isso pode ser feito com várias atribuições.
Em Python, tuplas, listas e dicionários são realmente seus amigos!
Leitura altamente recomendada: Mergulhe no Python (diveintopython /). O primeiro capítulo contém um bom tutorial sobre tuplas, listas e dicionários. E não esqueça de ler o resto do livro (você pode baixar o livro inteiro de graça).
Livrar-se de itens duplicados em uma lista.
O truque é converter temporariamente a lista em um dictionnário:
Desde o Python 2.5, você também pode usar conjuntos:
Obter todos os links em uma página da web (1)
. ou expressão regular maravilha.
para link em linksList:
Obter todos os links em uma página da Web (2)
Você também pode usar o módulo HTMLParser.
def handle_starttag (self, tag, attrs):
para link em p. links:
Para cada tag de início HTML encontrada, o método handle_starttag () será chamado.
Por exemplo, o & lt; a href = "google & gt; acionará o método handle_starttag (self, 'A', [('href', 'google')]).
Veja também todos os outros manipulam os métodos _ * () no manual do Pyhon.
(Note que o HTMLParser não é à prova de balas: ele vai sufocar em HTML mal formado. Neste caso, use o módulo sgmllib, volte para expressões regulares ou use o BeautifulSoup.)
Obter todos os links em uma página da web (3)
As principais vantagens da Beautiful Soup são sua capacidade de lidar com códigos HTML muito ruins e sua simplicidade. Sua desvantagem é sua velocidade (é lenta).
para item em soup. fetch ('a'):
Obter todos os links em uma página da Web (4)
Ok, aqui está outro:
Olha ma! Nenhum analisador nem regex.
para pedaço em htmlSource. lower (). split ('href =') [1:]:
indexes = [i para i in [chunk. find ('"', 1), chunk. find ('& gt;'), chunk. find ('')] se i & gt; -1]
Concedido, este é um truque bruto.
Zipar / descompactar arquivos.
Substitua 'w' por 'a' para adicionar arquivos ao arquivo zip.
Descompactando todos os arquivos de um arquivo zip:
para nome do arquivo no zfile. namelist ():
file = open (nome do arquivo, 'w + b')
Se você quiser zipar todos os arquivos em um diretório recursivamente (todos os subdiretórios):
para dirpath, dirnames, nomes de arquivos em os. walk (startdir):
para nome do arquivo em nomes de arquivos:
Listando o conteúdo de um diretório.
Você tem 4 maneiras de fazer isso, dependendo da sua necessidade.
O método listdir () retorna a lista de todos os arquivos em um diretório:
para nome do arquivo em os. listdir (r'c: \ windows '):
Observe que você pode usar o módulo fnmatch () para filtrar nomes de arquivos.
O módulo glob envolve listdir () e fnmatch () em um único método:
para nome do arquivo em glob. glob (r'c: \ windows \ *. exe '):
E se você precisar coletar subdiretórios, use os. path. walk ():
def processDirectory (args, dirname, nomes de arquivos):
para nome do arquivo em nomes de arquivos:
os. path. walk () funciona com um retorno de chamada: processDirectory () será chamado para cada diretório encontrado.
dirname irá conter o caminho do diretório.
nomes de arquivos conterão uma lista de nomes de arquivos nesse diretório.
Você também pode usar os. walk (), que funciona de maneira não-recursiva e é um pouco mais fácil de entender.
para dirpath, dirnames, nomes de arquivos em os. walk ('c: \\ winnt'):
print 'Diretório', dirpath.
para nome do arquivo em nomes de arquivos:
print 'File', nome do arquivo.
Um servidor web em 3 linhas de código.
Este servidor servirá arquivos no diretório atual. Você pode usar os. chdir () para alterar o diretório.
Esse truque é útil para servir ou transferir arquivos entre computadores em uma rede local.
Observe que esse servidor da Web é bastante rápido, mas só pode atender a uma solicitação HTTP no momento. Não é recomendado para servidores de alto tráfego.
Se você quer um melhor desempenho, dê uma olhada nos sockets assíncronos (asyncore, Medusa.) Ou nos servidores web multi-thread.
Criando e aumentando suas próprias exceções.
Não considere exceção como coisas desagradáveis ​​que querem quebrar seus programas. Exceções são seu amigo. Exceções são uma coisa boa. Exceções são mensageiros que dizem que algo está errado e o que está errado. E tente / exceto blocos lhe dará a chance de lidar com o problema.
Em seus programas, você também deve tentar / capturar todas as chamadas que podem cair em erro (acesso a arquivos, conexões de rede).
Geralmente é útil definir suas próprias exceções para sinalizar erros específicos da sua classe / módulo.
Aqui está um exemplo de definição de uma exceção e uma classe (digamos em myclass. py):
levante o meuexception, 'Você cometeu um erro!'
(myexception é uma exceção óbvia: não contém nada. No entanto, é útil porque a exceção em si é uma mensagem.)
Se você usar a classe, você poderia fazer:
Se você executar este programa, você receberá:
Arquivo "a. py", linha 3, em?
Arquivo "myclass. py", linha 9, em dosomething.
levante o meuexception, 'Você cometeu um erro!'
myclass. myexception: Você cometeu um erro!
myclass diz que você fez algo errado. Então é melhor você tentar / pegar, apenas no caso de haver um problema:
imprimir 'oops! myclass me diz que fiz algo errado.
Isto é melhor ! Você tem a chance de fazer algo se houver algum problema.
Scripting Microsoft SQL Server com Python.
Se você tem o Microsoft SQL Server, você deve ter encontrado esta situação em que você diz a si mesmo: "Se eu conseguisse fazer o script de todos os cliques no Enterprise Manager (também conhecido como MMC)!"
Você pode ! É possível fazer script em Python, o que você pode fazer no MMC.
Você só precisa do módulo python win32all para acessar objetos COM de dentro do Python (veja starship. python / crew / mhammond / win32 /)
(O módulo win32all também é fornecido com a distribuição Python do ActiveState: activeestate / Products / ActivePython /)
Uma vez instalado, basta usar os objetos SQL-DMO.
Por exemplo, obtenha a lista de bancos de dados em um servidor:
para i no intervalo (1, s. Databases. Count):
Ou pegue o script de uma tabela:
Acessando um banco de dados com o ODBC.
No Windows, o ODBC fornece uma maneira fácil de acessar praticamente qualquer banco de dados. Não é muito rápido, mas tudo bem.
Você precisa do módulo python win32all.
Primeiro, crie um DSN (por exemplo: 'mydsn') e, em seguida:
c. execute ('selecione clientid, nome, cidade do cliente')
Você também pode usar fetchone () ou fetchmany (n) para buscar - respectivamente - uma ou n linhas de uma só vez.
Nota: Em grandes conjuntos de dados, tenho truncamentos de dados bastante estranhos e não regulares em tabelas com um alto número de colunas. Isso é um bug no ODBC ou no driver ODBC do SQL Server? Eu vou ter que investigar.
Acessando um banco de dados com o ADO.
No Windows, você também pode usar o ADO (Microsoft ActiveX Data Objects) em vez de ODBC para acessar bancos de dados. O código a seguir usa objetos ADO COM para se conectar a um banco de dados do Microsoft SQL Server, recuperar e exibir uma tabela.
connexion. Open ("Provider = 'SQLOLEDB'; Fonte de Dados = 'myserver'; Catálogo Inicial = 'mydatabase'; ID do Usuário = 'mylogin'; Senha = 'mypassword';")
recordset = connexion. Execute ('SELECT clientid, clientName FROM clientes') [0]
enquanto não recordset. EOF:
print 'clientid =', recordset. Fields (0).Value, 'nome do cliente =', recordset. Fields (1).Value.
Para documentação do ADO, consulte MSDN: msdn. microsoft/library/en-us/ado270/htm/mdmscadoobjects. asp.
CGI no Windows com o TinyWeb.
O TinyWeb é um servidor web de um arquivo para Windows (o exe tem apenas 53 kb). É fantástico para criar servidores web instantâneos e compartilhar arquivos. O TinyWeb também é capaz de servir CGI.
Let's have some fun and create some CGI with Python !
First, let's get and install TinyWeb:
Get TinyWeb from ritlabs/tinyweb/ (it's free, even for commercial use !) and unzip it to c:\somedirectory (or any directory you'd like). Create the " www " subdirectory in this directory Create index. html in the www directory:
(make sure you use an absolute path) Point your browser at localhost.
If you see "Hello, world !", it means that TinyWeb is up and running.
Let's start making some CGI:
In the www directory, create the " cgi-bin " subdirectory. Create hello. py containing:
print "Hello, this is Python talking !"
(SHIFT+rightclick on a. py file, " Open with. ", choose python. exe,
check the box " Always use this program. ", click Ok) Point your browser at localhost/cgi-bin/hello. py.
You should see " Hello, this is Python talking ! " (and not the source code).
If it's ok, you're done !
Now you can make some nice CGI.
(If this does not work, make sure the path to python. exe is ok and that you used an absolute path in tinyweb's command line.)
Note that this will never be as fast as mod_python under Apache (because TinyWeb will spawn a new instance of the Python interpreter for each request on a Python CGI). Thus it's not appropriate for high-traffic production servers, but for a small LAN, it can be quite handy to serve CGI like this.
Refer to Python documentation for CGI tutorials and reference.
Hint 1: Don't forget that you can also use TinySSL, which is the SSL/HTTPS enabled version of TinyWeb. That's fantastic for making secure webservers (especially to prevent LAN sniffing, when authentication is required). Hint 2: If you wrap your Python CGI with py2exe, you'll be able to run your CGI on computers where Python is not installed.
Sub-hint: Compress all exe/dll/pyd with UPX, and you can take the whole webserver and its CGI on a floppy disk and run it everywhere ! (A typical " Hello, world ! " CGI example and TinyWeb weight together only 375 kb with Python 2.2 !)
if sys. platform == "win32":
import os, msvcrt.
Creating. exe files from Python programs.
Like Sun's Java or Microsoft's , if you want to distribute your Python programs, you need to bundle the virtual machine too.
You have several options: py2exe , cx_Freeze or pyInstaller .
For example, under Windows, if you want to transform myprogram. py into myprogram. exe , create the file setup. py as follows:
py2exe will get all dependant files and write them in the \dist subdirectory. You will typically find your program as. exe , pythonXX. dll and complementary. pyd files. Your program will run on any computer even if Python is not installed. This also works for CGI.
(Note that if your program uses tkinter, there is a trick.)
Hint : Use UPX to compress all dll / exe / pyd files. This will greatly reduce file size. Use: upx --best *.dll *.exe *.pyd (Typically, python22.dll shrinks from 848 kb to 324 kb.)
Note that since version 0.6.1, py2exe is capable of creating a single EXE (pythonXX. dll and other files are integrated into the EXE).
from distutils. core import setup.
You can also use cx_Freeze , which is an alternative to py2exe (This is what I used in webGobbler).
or even create a console-less version:
This is a pain when you want your program to be able to run in GUI mode and command-line mode.
To safely disable console output, do as follows at the beginning of your program:
''' dummyStream behaves like a stream but does nothing. '''
def __init__(self): pass.
def write(self, data): pass.
def read(self, data): pass.
def flush(self): pass.
def close(self): pass.
# and now redirect all default streams to this dummyStream:
This way, if the program starts in console-less mode, it will work even if the code contains print statements.
And if run in command-line mode, it will print out as usual. (This is basically what I did in webGobbler, too.)
pyInstaller.
Then pack your program:
You program will be available in the \distmyprogram subdirectory. (myprogram. exe, pythonXX. dll, MSVCR71.dll, etc.)
--onefile will create a single EXE file. E. g.:
Reading Windows registry.
key = _winreg. OpenKey(_winreg. HKEY_CURRENT_USER, 'Software\\Microsoft\\Internet Explorer', 0, _winreg. KEY_READ)
(value, valuetype) = _winreg. QueryValueEx(key, 'Download Directory')
Measuring the performance of Python programs.
Python is provided with a code profiling module: profile . It's rather easy to use.
For example, if you want to profile myfunction(), instead of calling it with:
you just have to do:
This will display a report like this:
1 0.224 0.224 0.279 0.279 myprogram. py:512(compute)
10 0.078 0.008 0.078 0.008 myprogram. py:234(first)
1 0.077 0.077 0.502 0.502 myprogram. py:249(give_first)
1 0.051 0.051 0.051 0.051 myprogram. py:1315(give_last)
3 0.043 0.014 0.205 0.068 myprogram. py:107(sort)
1 0.039 0.039 0.039 0.039 myprogram. py:55(display)
139 0.034 0.000 0.106 0.001 myprogram. py:239(save)
139 0.030 0.000 0.072 0.001 myprogram. py:314(load)
This report tells you, for each function/method:
how many times it was called ( ncalls ). total time spent in function (minus time spent in sub-functions) ( tottime ) total time spent in function (including time spent in sub-functions) ( cumtime ) average time per call ( percall )
As you can see, the profile module displays the precise filename, line and function name. This is precious information and will help you to spot the slowest parts of your programs.
But don't try to optimize too early in development stage. This is evil ! :-)
Note that Python is also provided with a similar module named hotspot , which is more accurate but does not work well with threads.
Speed up your Python programs.
To speedup your Python program, there's nothing like optimizing or redesigning your algorithms.
In case you think you can't do better, you can always use Psyco: Psyco is a Just-In-Time-like compiler for Python for Intel 80x86-compatible processors. It's very easy to use and provides x2 to x100 instant speed-up.
Download psyco for your Python version (psyco. sourceforge) unzip and copy the \psyco directory to your Python site-packages directory (should be something like c:\pythonXX\Lib\site-packages\psyco\ under Windows)
Then, put this at the beginning of your programs:
This way, if psyco is installed, your program will run faster.
If psyco is not available, your program will run as usual.
(And if psyco is still not enough, you can rewrite the code which is too slow in C or C++ and wrap it with SWIG (swig).)
Note: Do not use Psyco when debugging, profiling or tracing your code. You may get innacurate results and strange behaviours.
Regular expressions are sometimes overkill.
I helped someone on a forum who wanted process a text file: He wanted to extract the text following "Two words" in all lines starting whith these 2 word. He had started writing a regular expression for this: r = repile("Two\sword\s(.*?)") .
His problem was better solved with:
for line in file:
if line. startswith("Two words "):
Regular expression are sometime overkill. They are not always the best choice, because:
They involve some overhead: You have to compile the regular expression ( repile() ). This means parsing the regular expression and transforming it into a state machine. This consumes CPU time. When using the regular expression, you run the state machine against the text, which make the state machine change state according to many rules. This is also eats CPU time. Regular expression are not failsafe: they can fail sometimes on specific input. You may get a " maximum recusion limit exceeded " exception. This means that you should also enclose all match() , search() and findall() methods in try/except blocks. The Zen of Python ( import this :-) says « Readability counts ». That's a good thing. And regular expression quickly become difficult to read, debug and change.
Besides, string methods like find() , rfind() or startwith() are very fast, much faster than regular expressions.
Do not try to use regular expressions everywhere. Often a bunch of string operations will do the job faster.
Executing another Python program.
Bayesian filtering.
Bayesian filtering is the last buzz-word of spam fighting. And it works very well indeed !
Reverend is a free Bayesian module for Python. You can download it from divmod/trac/wiki/DivmodReverend.
Here's an example: Recognizing the language of a text.
First, train it on a few sentences:
guesser. train('french','La souris est rentrйe dans son trou.')
guesser. train('english','my tailor is rich.')
guesser. train('french','Je ne sais pas si je viendrai demain.')
guesser. train('english','I do not plan to update my website soon.')
And now let it guess the language:
[('english', 0.99990000000000001), ('french', 9.9999999999988987e-005)]
The bayesian filter says: " It's english, with a 99,99% probability. "
Let's try another one:
[('french', 0.99990000000000001), ('english', 9.9999999999988987e-005)]
It says: " It's french, with a 99,99% probability. "
Not bad, isn't it ?
You can train it on even more languages at the same time. You can also train it to classify any kind of text.
Tkinter and cx_Freeze.
(This trick also works with py2exe).
You create your program:
This program works on your computer. Now let's package it with cx_Freeeze:
If you run your program (test. exe), you will get this error:
In fact, you need to copy the TKinter DLLs. Your builing batch becomes:
copy C:\Python24\DLLs\tcl84.dll .\bin\
copy C:\Python24\DLLs\tk84.dll .\bin\
Ok, john, build it again.
Run the EXE: it works !
Run the EXE on another computer (which does not have Python installed): Error !
File "cx_Freeze\initscripts\console. py", line 26, in ?
exec code in m.__dict__.
File "test. py", line 20, in ?
File "test. py", line 14, in main.
File "C:\Python24\Lib\lib-tk\Tkinter. py", line 1569, in __init__.
_tkinter. TclError: Can't find a usable init. tcl in the following directories:
The reason it fails is that Tkinter needs the runtime tcl scripts which are located in C:\Python24\tcl\tcl8.4 and C:\Python24\tcl\tk8.4.
So let's copy these scripts in the same directory as you application.
copy C:\Python24\DLLs\tcl84.dll .\bin\
copy C:\Python24\DLLs\tk84.dll .\bin\
xcopy /S /I /Y "C:\Python24\tcl\tcl8.4\*.*" "bin\libtcltk84\tcl8.4"
xcopy /S /I /Y "C:\Python24\tcl\tk8.4\*.*" "bin\libtcltk84\tk8.4"
But you also need to tell your program where to get the tcl/tk runtime scripts (in bold below):
# Take the tcl/tk library from local subdirectory if available.
This depends on which features of Tkinter your program will use.
(cx_Freeze and - AFAIK - all other packagers are not capable of resolving tcl/tk dependencies.)
A few Tkinter tips.
Tkinter is the basic GUI toolkit provided with Python.
Tkinter. Label(self. root, text="Hello, world !").grid(column=0,row=0) #4.
#1 : It's always better to code a GUI in the form of a class. It will be easier to reuse your GUI components.
I lack time, so this list of recommendations could be much larger after my experience with webGobbler.
Tkinter file dialogs.
Tkinter is provided with several basic dialogs for file or directory handling. There's pretty easy to use, but it's good to have some examples:
directory = tkFileDialog. askdirectory(parent=root, initialdir="/",title='Please select a directory')
if len(directory) > 0:
print "You chose directory %s" % directory.
Select a file for open ( askopenfile will open the file for you. file will behave like a normal file object):
file = tkFileDialog. askopenfile(parent=root, mode='rb',title='Please select a file')
print "I got %d bytes from the file." % len(data)
('Portable Network Graphics','*.png'),
filename = tkFileDialog. asksaveasfilename(parent=root, filetypes=myFormats, title="Save image as. ")
if len(filename) > 0:
print "Now saving as %s" % (filename)
Including binaries in your sources.
Sometime it's handy to include small files in your sources (icons, test files, etc.)
Get the text created by this program and use it in your source:
For example, if you use PIL (Python Imaging Library), you can directly open this image:
Good practice: try/except non-standard import statements.
If your program uses modules which are not part of the standard Python distribution, it can be a pain for your users to identify which module are required and where to get them.
Ease their pain with a simple try/except statement which tells the module name (which is not always the same name as stated in the import statement) and where to get it.
raise ImportError, 'This program requires the win32all extensions for Python. See starship. python/crew/mhammond/win32/'
Good practice: Readable objects.
Let's define a "client" class. Each client has a name and a number.
Now if we create an instance of this class and if we display it:
Quite exact, but not very explicit.
return '<client id="%s" name="%s">' % (self. number, self. name)
Let's do it again:
Muito melhor. Now this object has a meaning to you.
It's much better for debugging or logging.
You can even apply this to compound objects, such as a client directory:
for client in self. clients:
Then create a directory, and add clients to this directory:
Much better, isn't it ?
For example, if your program goes tits ups, you can log the objects states in a file for debugging purposes in the except clause of a try/except block.
Good practice: No blank-check read()
When you read a file or a socket, you often use simply. read() , such as:
You program will eat all the system's memory, slow down to a crawl and probably crash the system too.
For example, I do not expect to process files larger than 10 Mb, nor read HTML pages larger than 200 kb, so I would write:
data = file. read(10000000)
html = url. read(200000)
This way, I'm safe from buggy or malicious external data sources.
1.7 is different than 1.7 ?
This is a common pitfall amongst novice programmers:
When you see a floating number 1.7, you only see a textual representation of the binary data stored in computer's memory .
When you use a date, such as :
"2006-03-21 15:23:20.904000" is NOT the date. It's a textual representation of the date (The real date is binary data in the computer's memory).
This leads to pitfalls, such as:
b = 0.9 + 0.8 # This should be 1.7.
print "a and b are equal."
print "a and b are different !"
What do you expect this code to print ? " a and b are equal ? ".
a and b are different !
How can this be ?
How can 1.7 be different than 1.7 ?
The program says they are different because a and b are different at the binary level.
Only their textual representation is the same.
print "a and b are equal."
print "a and b are different !"
print "a and b are equal."
print "a and b are different !"
Because the computer can only handle bits, and you cannot precisely represent all numbers in binary.
But it's not capable of storing the exact value 0.3 (because there is no exact representation of 0.3 in binary).
Get user's home directory path.
It's handy to store or retreive configuration files for your programs.
Note that this also works under Windows. Nice !
(It points to the "Document and settings" user's folder, or even the network folder if the user has one.)
Python's virtual machine.
Python - like Java or Microsoft - has a virtual machine .
Python has a specific bytecode . It's an machine language like Intel 80386 or Pentium machine language, but there is no physical microprocessor capable of executing it.
The bytecode runs in a program which simulates a microprocessor : a virtual machine.
This is the same for Java and . Java's virtual machine is named JVM (Java Virtual Machine), and 's virtual machine is the CLR (Common Language Runtime)
Let's have an example: mymodule. py.
This no-nonsense program takes a number, displays it, multiplies it by 3, adds 77 if the result is less than 50 and returns it. (Granted, this is weird.)
Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)] on win32.
Type "help", "copyright", "credits" or "license" for more information.
The. pyc files are automatically generated by Python whenever a module is imported.
Python can directly run the. pyc files if you want. You could even run the. pyc without the. py.
If you update the. py source, Python will detect this change and automatically update the corresponding. pyc.
2 0 LOAD_CONST 1 ('I have')
4 LOAD_FAST 0 (a)
12 LOAD_CONST 2 (3)
16 STORE_FAST 1 (b)
22 LOAD_CONST 3 (50)
25 COMPARE_OP 0 (<)
28 JUMP_IF_FALSE 14 (to 45)
35 LOAD_CONST 4 (77)
39 STORE_FAST 1 (b)
42 JUMP_FORWARD 1 (to 46)
You can see the virtual machine instructions ( LOAD_CONST, PRINT_ITEM, COMPARE_OP . ) and their operands ( 0 which is the reference of the variable a, 1 which is the reference of variable b. )
In Python bytecode, this translates to:
12 LOAD_CONST 2 (3) # Load the value 3 on the stack.
15 BINARY_MULTIPLY # Multiply them.
16 STORE_FAST 1 (b) # Store result in variable b.
For example, the string "I have" will not be reused after line 2. So Python decides to reuse the adresse of the string (1) for variable b.
SQLite - databases made simple.
SQLite is a tremendous database engine. I mean it.
very fast (faster than mySQL on most operations). Respects almost the whole SQL-92 standard. Does not require installation of a service. No database administration to perform. Does not eat computer memory and CPU when not in use. SQLite databases are compact 1 database = 1 file (easy to move/deploy/backup/transfer/email). SQLite databases are portable across platforms (Windows, MacOS, Linux, PDA. ) SQLite is ACID (data consistency is assured even on computer failure or crash) Supports transactions Fields can store Nulls, integers, reals (floats), text or blob (binary data). Can handle up to 2 Tera-bytes of data (although going over 12 Gb is not recommended). Can work as a in-memory database (blazing performances !) SQLite is very fast, very compact, easy to use. It's god gift for local data processing (websites, data crunching, etc.).
Oh. and it's not only free , it's also public domain (no GPL license headaches).
For Python 2.4 and ealier, it must be installed separately: initd/tracker/pysqlite.
from sqlite3 import dbapi2 as sqlite.
cur. execute('create table clients (id INT PRIMARY KEY, name CHAR(60))')
client = (5,"John Smith")
cur. execute("insert into clients (id, name) values (?, ?)", client )
clients = [ (7,"Ella Fitzgerald"),
cur. executemany("insert into clients (id, name) values (?, ?)", clients )
Now let's use the database:
from sqlite3 import dbapi2 as sqlite.
print "Row by row:"
cur. execute('select id, name from clients order by name;')
print "All rows at once:"
cur. execute('select id, name from clients order by name;')
(7, u'Ella Fitzgerald')
(8, u'Louis Armstrong')
All rows at once:
[(7, u'Ella Fitzgerald'), (5, u'John Smith'), (8, u'Louis Armstrong'), (9, u'Miles Davis')]
(But make sure you have enough memory to handle your data.)
Hint 2: To make your program compatible with Python 2.5 and Python 2.4+pySqlLite, do the following:
from sqlite3 import dbapi2 as sqlite # For Python 2.5.
from pysqlite2 import dbapi2 as sqlite # For Python 2.4 and pySqlLite.
raise ImportError, "This module requires either: Python 2.5 or Python 2.4 with the pySqlLite module (initd/tracker/pysqlite)"
Dive into Python.
You're programming in Python ?
Then you should be reading Dive into Pyhon .
The book is free.
I can't imagine decent Python programing without reading this book.
At least download it.
This is a must-read.
This book is available for free in different formats (HTML, PDF, Word 97. ).
Plenty of information, good practices, ideas, gotchas and snippets about classes, datatypes, introspection, exceptions, HTML/XML processing, unit testing, webservices, refactoring, whatever.
Creating a mutex under Windows.
I use a mutex in webGobbler so that the InnoSetup uninstaller knows webGobbler is still running (and that it shouldn't be uninstalled while the program is still running).
That's a handy feature of InnoSetup.
if CTYPES_AVAILABLE and sys. platform=="win32":
I perform an except:pass , because if the mutex can't be created, it's not a big deal for my program (It's only an uninstaller issue).
Your mileage may vary.
urllib2 and proxies.
With urllib2 , you can use proxies.
What is nice about this trick is that this will set the proxy parameters for your whole program.
If your proxy requires authentication, you can do it too !
Note that as of version 2.4.2 of Python, urllib2 only supports the following proxy authentication methods: Basic and Digest .
If your proxy uses NTLM (Windows/IE-specific), you're out of luck.
Beside this trick, there is a simplier way to set the proxy:
You can also do the same with os. environ['FTP_PROXY'] .
A proper User-agent in your HTTP requests.
If you have a Python program which sends HTTP requests, the netiquette says it should properly identify itself.
You should change this.
request = urllib2.Request('sebsauvage', None, request_headers)
Make sure the program name you use in User-Agent is really unique (Search on Google !). Adopt the form: applicationName/version , such as webGobbler/1.2.4 . If your program spiders websites, you should respect robot rules. Always use bound reads. (eg..read(200000) , not. read() alone). Choose the network timeout wisely. You can use the following code to set the timeout in your whole program:
Error handling with urllib2.
You are using urllib/urllib2 and want to check for 404 and other HTTP errors ?
Here's the trick:
except urllib2.HTTPError , exc:
if exc. code == 404:
print "Not found !"
print "HTTP request failed with error %d (%s)" % (exc. code, exc. msg)
except urllib2.URLError , exc:
print "Failed because:", exc. reason.
This way, you can check for 404 and other HTTP error codes.
Note that urllib2 will not raise an exception on 2xx and 3xx codes. The exception urllib2.HTTPError will be raised with 4xx and 5xx codes (which is the expected behaviour).
(Note also that HTTP 30x redirections will be automatically and transparently handled by urllib2.)
urllib2: What am I getting ?
When you send a HTTP request, this may return html, images, videos, whatever.
In some cases you should check that the type of data you're receiving is what you expected.
print "Document type is", urlfile. info().getheader("Content-Type","")
This will output:
Warning : You may find other info after a semi-colon, such as:
So what you should always do is:
to get only the "text/html" part.
This would print things like:
Tipo de Conteúdo: text / html; charset=iso-8859-1.
Reading (and writing) large XLS (Excel) files.
In one of my projects, I had to read large XLS files.
Of course you can access all cells content through COM calls, but it's painfully slow.
This is the fastest way to read large XLS data files.
filepath = os. path. abspath(filename) # Always make sure you use an absolute path !
xlCSVWindows =0x17 # from enum XlFileFormat.
Example: For Excel 2000, it's C:\Program Files\Microsoft Office\Office\1036\VBAXL9.CHM.
This will automatically generate the VBA code (which can be easily translated into Python).
Run makepy. py (eg. C:\Python24\Lib\site-packages\win32com\client\makepy. py) In the list, choose " Microsoft Excel 9.0 Object Library (1.3) " (or similar) and click ok. Have a look in C:\Python24\Lib\site-packages\win32com\gen_py\ directory.
You will find the wrapper (such as 00020813-0000-0000-C000-000000000046x0x1x3.py) Open this file: it contains Excel constants and their values (You can copy/paste them in your code.)
xlCSVWindows =0x17 # from enum XlFileFormat.
Sub-hint 2: You can also use CSS styles to set formatting/colors in several cells. Simply include a <style> stylesheet in the generated HTML.
Sub-hint 3: Using CSS, you can even force the cell format (text, numeric, etc.). por exemplo. <style><!--.mystyle --></style> then use <td class=mystyle>25</td> to force the cell to text (usefull, for example, to prevent Excel from trying to compute international phone number - you stupid app !)
Or mso-number-format:"0\.000"; to force a numeric format with 3 digits precision.
Saving the stack trace.
Sometimes when you create an application, it's handy to have the stack trace dumped in a log file for debugging purposes.
b = fifths(value) * 100.
except Exception, ex:
print "Oops ! Something went wrong. Please look in the log file."
After running this program, mylog. log contains:
File "a. py", line 10, in ?
File "a. py", line 7, in myfunction.
b = fifths(value) * 100.
File "a. py", line 4, in fifths.
ZeroDivisionError: integer division or modulo by zero.
Filtering out warnings.
Sometimes, Python displays warning.
While they are usefull and should be taken care of , you sometimes want to disable them.
warnings. filterwarnings(action = 'ignore',message='.*?no locals\(\) in functions bound by Psyco')
Saving an image as progressive JPEG with PIL.
PIL (Python Imaging Library) is very good graphics library for image manipulation (This is the library I used in webGobbler ).
This may seem obvious, but hey.
(Assuming that myimage is an Image PIL object.)
Charsets and encoding.
So when we have symbols such as the letter 'a' or the question mark '?', we have to create binary representation of these symbols for the computer.
That's the only way to store them in the computer's memory.
The character set.
First , we have to choose which number to use for each symbol. That's a simple table.
The usual suspect is ASCII.
In ASCII, the letter 'a' is the number 97. The question mark '?' is the number 67.
Unicode is a huge table which tells which number to use for each symbol .
0000 to 007F (0 to 127)
0080 to 00FF (128 to 255)
including accented characters)
0900 to 097F (2304 to 2431)
1100 to 117F (4352 to 4479)
The encoding.
ASCII uses the simple mapping: 1 ASCII code (0. 127) = 1 byte (8 or 7 bits). It's ok for ASCII, because ASCII uses only numbers from 0 to 127. It fits in a byte.
Most of them use a multi-byte encoding (a character is represented by several bytes).
For Unicode , there are several encodings. The first one is the raw 16 bits Unicode. 16 bits (2 bytes) per character.
But as most texts only use the lower part of the Unicode table (codes 0 to 127), that's huge waste of space.
If you need special, less common characters (128 to 2047), use two bytes.
If you need more specific characters (2048 to 65535), use three bytes.
Thus for most latin texts, this will be as space-savvy as ASCII, but you have the ability to use any special Unicode character if you want.
Let's sum up all this.
The charset will tell you which number to use for each symbol,
the encoding will tell you how to encode these numbers into bits.
One simple example is:
For example the word "bйbй" ( baby in French):
then will ask " Why am I getting those strange characters ? ".
If you transmit a text, you must always also tell which charset/encoding was used.
Do you know that in this case all browsers try to guess the charset ?
Every webpage should have its encoding specified in HTTP headers or in the HTML header itself, such as:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
Python and Unicode.
Use them as much as possible.
Your programs will smoothly support international characters.
First, you should always indicate which charset/encoding your Python source uses, such as:
Next, use Unicode strings in your programs (use the ' u ' prefix):
bestString = u"Good unicode string."
anotherGoodString = u"Ma vie, mon \u0153uvre."
( \u0153 is the unicode character "œ". (0153 is the code for "œ"). The "œ" character is in the latin-1 section of the charts: unicode/charts/ )
To convert a Unicode string to a specific charset:
The list of charsets/encodings supported by Python are available at docs. python/lib/standard-encodings. html.
Traceback (most recent call last):
File "c:\python24\lib\encodings\cp437.py", line 18, in encode.
UnicodeEncodeError: 'charmap' codec can't encode character u'\u0153' in position 0: character maps to <undefined>
Python is telling you that the Unicode character 153 (œ) has no equivalent in the charset your operating system console uses.
So to make sure you print without error, you can do:
Unicode characters which cannot be displayed by the console will be converted to '?'.
Reading the same file:
Oops you see there's a problem here. We opened the file but we didn't specify the encoding when reading. That's why we get this "┼ф" garbage (which is UTF-8 codes).
Let's decode the UTF-8:
There, we got it right. That's our "œuvre" word.
Remember our console does not support the \u0153 character ? (That's why we used repr() .)
Yes, this looks cumbersome.
But don't forget we are translating between 3 modes : UTF-8 (the input file), Unicode (the Python object) and cp437 (the output console charset).
Explicit is better than implicit.
A shorter syntax.
For example, when iterating over the elements of a table, you would probably iterate using an index:
for i in range(0,len(countries)):
It's better to use iterators:
for country in countries:
It does the same thing, but:
You've spared a variable (i). The code is more compact. It's more readable.
" for country in countries " is almost plain English.
for line in file. readlines():
for line in file:
These kind of constructs can help to keep code shorter and more readable .
Iterating with multiple items.
print manager,'manages',nbclients,'clients in',country.
for country in data: # This is the same as for country in data. keys()
print 'We have',data[country],'clients in',country.
But it's better to do it this way:
for (country, nbclients) in data. items():
print 'We have',nbclients,'clients in',country.
because you spare a hash for each entry.
Creating iterators.
and we want a class capable of reading this file format. It must return the country and the number of clients.
We create a clientFileReader class:
self. file. readline() # We discard the first line.
return ( line[:13], int(line[13:]) )
To create an iterator:
Create a __iter__() method which returns the iterator (which happen to be ourselves !) The iterator must have a next() method which returns the next item. The next() method must raise the StopIteration() exception when no more data is available. It's as simple as this !
print 'We have',nbclients,'clients in',country.
This is much better than chopping file lines in the main loop.
Parsing the command-line.
It's not recommended to try to parse the command-line ( sys. argv ) yourself. Parsing the command-line is not as trivial as it seems to be.
Python has two good modules dedicated to command-line parsing: getopt ant optparse .
They do their job very well (They take care of mundane tasks such as parameters quoting, for example).
Ok, let's create a program which is supposed to reverses all lines in a text file .
Our program has:
a mandatory argument: file , the file to process. an optional parameters with value: - o to specify an output file (such as - o myoutputfile. txt ) an optional parameter without value: - c to capitalize all letters. an optional parameters: - h to display program help.
opts, args = getopt. getopt(sys. argv[1:], "hco:",["help", "capitalize","output="])
except getopt. GetoptError, e:
raise 'Unknown argument "%s" in command-line.' % e. opt.
if option in ('-h','--help'):
print 'You asked for the program help.'
if option in ('-c','--capitalize'):
print "You used the --capitalize option !"
elif option in ('-o','--output'):
print "You used the --output option with value",value.
print 'You must specify one file to process. Use - h for help.'
The getopt. getopt() will parse the command-line: sys. argv[1:] skips the program name itself (which is sys. argv[0] ) "hco:" give the list of possible options ( - h , - c and - o ). The colon ( : ) tells that - o requires a value. ["help", "capitalize","output="] allows the user to use the long options version (--help/--capitalize/--output).
User can even be mix short and long options in the command-line, such as: reverse --capitalise - o output. txt myfile. txt The for loop will check all options. It's typically in this loop that you will modify your program options according to command-line options. The --help will display the help page and exit ( sys. exit(0) ). The if len(args)!=1 is used to make sure our mandatory argument ( file ) is provided. You can choose to allow (or not) several arguments.
Let's use out program from the command line:
You used the --capitalize option !
You used the --output option with value output. txt.
The file to process is myfile. txt.
You can also call for help:
You asked for the program help.
print "You used the --capitalize option !"
print "You used the --output option with value",options. outputFilename.
print 'You must specify one file to process. Use - h for help.'
Not much different, but:
You first create a parser ( optparse. OptionParser() ), add options to this parser ( parser. add_option(. ) ) then ask him to parse the command-line ( parser. parse_args() ). Option - c does not take a value. We merely record the presence of - c with action="store_true" .
dest="capitalize" will store this option in the attribute capitalize of our parser. For - o , we specify a string to store in the outputFilename attribute of our parser. We later simply access our options through options. capitalize and options. outputFilename . No loop. args still gives us our file argument.
You used the --capitalize option !
You used the --output option with value output. txt.
The file to process is myfile. txt.
Funciona. Let's ask for help:
usage: reverse2.py [options]
-h, --help show this help message and exit.
-o OUTPUTFILENAME, --output=OUTPUTFILENAME.
But did you notice ?
We didn't code the --help option !
You can even add help information in options with the help parameter, such as:
parser. add_option("-o","--output",action="store",type="string",dest="outputFilename", help="Write output to a file" )
Which will give:
usage: reverse2.py [options]
-h, --help show this help message and exit.
-c, --capitalize Capitalize all letters.
-o OUTPUTFILENAME, --output=OUTPUTFILENAME.
Write output to a file.
Help is automatically generated.
Using AutoIt from Python.
AutoIt is a fabulous free scripting language for scripting Windows: you can click buttons, send keystrokes, wait for Windows, etc.
Although you could do the same in Python using raw Win32 API, it's a pain. It's much easier to use AutoIt COM interface.
The AutoIt COM documentation is C:\Program Files\AutoIt3\AutoItX\AutoItX. chm.
Don't forget that this COM control must be registered prior usage (with the command-line: regsvr32 AutoItX3.dll ).
raise ImportError, 'This program requires the pywin32 extensions for Python. See starship. python/crew/mhammond/win32/'
# If can't instanciate, try to register COM control again:
os. system("regsvr32 /s AutoItX3.dll")
raise ImportError, "Could not instanciate AutoIT COM module because",e.
print "Could not instanciate AutoIT COM module."
What's in a main.
If you've spent some time with Python, you must have encountered this strange Python idiom:
A Python program can be used in (at least) two ways:
executed directly: python mymodule. py imported: import mymodule.
What is under the if __name__=="__main__" will only be run if the module is run directly.
If you import the module, the code will not be run.
Parse the command-line in the main and call the methods/functions, so that the module can be used from the command line. Run the unit tests (unittest) in the main, so that the module performs a self-test when run. Run example code in the main (for example, for a tkinter widget).
Example: Parsing the command-line.
for link in linksList:
if link. startswith('"'): link=link[1:] # Remove quotes.
if link. endswith('"'): link=link[:-1]
opts, args = getopt. getopt(sys. argv[1:],"")
print "You must specify a file to process."
print "Linkextractor is processing %s. " % args[0]
The class linkextractor contains our program logic. The main only parses the command-line, reads the specified file and uses our linkextractor class to process it.
We can use our class by running it from the command line:
Linkextractor is processing myPage. html.
or from another Python program by importing it:
In this case, the main will not run.
Being able to use our class directly from the command-line is very handy.
Example: Running self-tests.
for link in linksList:
if link. startswith('"'): link=link[1:] # Remove quotes.
if link. endswith('"'): link=link[:-1]
Welcome to <a href="sebsauvage/">sebsauvage/</a><br>
'First link is %s. It should be sebsauvage/ without quotes.' % links[0])
'Second link is %s. It should be python without quotes.' % links[1])
print "Performing self-tests. "
You can simply self-test our module by running it:
Ran 1 test in 0.000s.
This is very usefull to auto-test (or at least sanity-check) all your programs/modules/classes/libraries automatically.
Mixing both.
If nothing provided in command-line (or a special --selftest option is provided), perform the self-test. Otherwise perform what the user asked in command line.
Disable all javascript in a html page.
If you have a Python program which grabs html pages from the web, javascript is a real nuisance when you browse these pages offline.
Here's a simple trick to disable all javascript:
This will disable all javascript (browsers will simply ignore the <noscript> tag), and you will still be able to have a look in the code if you want.
Multiplying.
Python can multiply. It can even multiply strings, tuples or lists.
('hello', 'hello', 'hello')
['hello', 'hello', 'hello']
('hello', 'world', 'hello', 'world', 'hello', 'world')
Notice the difference between ('hello') which is a single string and ('hello',) which is a tuple .
That's why they do not multiply the same.
Creating and reading. tar. bz2 archives.
tar. bz2 archives are usually smaller than. zip or. tar. gz.
Python can natively create and read those archives.
archive. debug = 1 # Display the files beeing compressed.
archive. add(r'd:\myfiles') # d:\myfiles contains the files to compress.
archive. debug = 1 # Display the files beeing decompressed.
for tarinfo in archive:
archive. extract(tarinfo, r'd:\mydirectory') # d:\mydirectory is where I want to uncompress the files.
Enumerating.
A simple function to get a numbered enumeration: enumerate() works on sequences (string, list. ) and returns a tuple (index, item):
& gt; & gt; & gt; for i in enumerate('hello world'):
Zip that thing.
zip , map and filter are powerful sequence operators which can replace list comprehension in some cases.
List comprehension.
& gt; & gt; & gt; print [value*2 for value in mylist]
This reads almost as plain english: compute value*2 for each value in my list .
& gt; & gt; & gt; print [i*2 for i in mylist if i>4 ]
You can even zip multiple sequences together:
Strings are sequences too. You can zip them:
The output list will be as long as the shortest input sequence:
which is the equivalent of:
Except that map is faster.
You can also use a function which takes several argument. In this case, you must provide as many lists as arguments.
This is the equivalent of:
(I say 'equivalent' because in Python things like zero or an empty list are the equivalent of None ).
This is the equivalent of:
Except that filter is faster.
Assim. map/filter or list comprehension ?
It's usually better to use map/filter, because they're faster. But not always .
You could express the same thing with filter , maps and lambda :
The list comprehension is not only easier to read: It's also surprisingly faster .
There are other sequences operators:
& gt; & gt; & gt; print reduce(myfunction, mylist)
which is the equivalent of:
In fact, you can import the operator from the operator module:
& gt; & gt; & gt; print reduce(operator. mul, mylist)
& gt; & gt; & gt; print reduce(operator. add, mylist)
Conversions.
& gt; & gt; & gt; print list(mytuple) # Tuple to list.
& gt; & gt; & gt; mylist = [1,2,3] # List to tuple.
& gt; & gt; & gt; print dict(mylist2) # List to dictionnary.
& gt; & gt; & gt; print list(mystring) # String to list.
& gt; & gt; & gt; print ''.join(mylist3) # List to string.
You get the picture.
& gt; & gt; & gt; for character in list(mystring): # This is BAD . Don't do this.
& gt; & gt; & gt; for character in mystring: # Simply do that !
Keep in mind sequence functions require any sequence , not only lists .
Thus it's ok to do:
A Tkinter widgets which expands in grid.
When you lay out widgets in a tkinter application, you use either the pack() or the grid() geometry manager.
Grid is - in my opinion - a far more powerful and flexible geometry manager than Pack .
(By the way, never ever mix. pack() and. grid(), or you'll have nasty surprises.)
When using grid() , specify sticky (usually 'NSEW') Then use grid_columnconfigure() and grid_rowconfigure() to set the weights (usually 1).
Example: A simple Window with a red and a blue canvas. The two canvas automatically resize to use all the available space in the window.
self. root. grid_rowconfigure (0,weight=1)
self. root. grid_rowconfigure (1,weight=1)
If you comment the lines containing grid_columnconfigure and grid_rowconfigure , you will see that the canvas do not expand.
You can even play with the weights to share the available space between widgets, eg:
Convert a string date to a datetime object.
Let's say we want to convert a string date (eg."2006-05-18 19:35:00") into a datetime object.
& gt; & gt; & gt; stringDate = "2006-05-18 19:35:00"
& gt; & gt; & gt; dt = datetime. datetime. fromtimestamp(time. mktime(time. strptime(stringDate,"%Y-%m-%d %H:%M:%S")))
time. strptime() converts the string to a struct_time tuple. time. mktime() converts this tuple into seconds (elasped since epoch, C-style). datetime. fromtimestamp() converts the seconds to a Python datetime object. Yes, this is convoluted.
Compute the difference between two dates, in seconds.
& gt; & gt; & gt; def dateDiffInSeconds(date1, date2):
. timedelta = date2 - date1.
. return timedelta. days*24*3600 + timedelta. seconds.
Managed attributes, read-only attributes.
Sometimes, you want to have a greater control over attributes access in your object.
You can do this:
Create a private attribute ( self.__x ) Create accessor functions to this attribute ( getx, setx, delx ) Create a property() and assign it these accessors. Exemplo:
def setx(self, value): self.__x = value.
def delx(self): del self.__x.
x = property(getx, setx, delx, "I'm the 'x' property.")
This way, you can control access in the getx/setx/delx methods.
For example, you can prevent a property from being written or deleted:
def setx(self, value): raise AttributeError,'Property x is read-only.'
def delx(self): raise AttributeError,'Property x cannot be deleted.'
x = property(getx, setx, delx, "I'm the 'x' property.")
a. x = 5 # This line will fail.
If you run this program, you will get:
File "example. py", line 11, in ?
a. x = 5 # This line will fail.
File "example. py", line 6, in setx.
def setx(self, value): raise AttributeError,'Property x is read-only.'
AttributeError: Property x is read-only.
First day of the month.
& gt; & gt; & gt; print firstDayOfMonth( datetime. datetime(2006,05,13) )
This function takes a datetime object as input ( dt ) and returns the first day of the month at midnight (12:00:00 AM).
Fetch, read and parse a RSS 2.0 feed in 6 lines.
Dumbed-down version. Fácil.
This program gets the RSS 2.0 feed from sebsauvage , parses it and displays all titles.
for item in document. getElementsByTagName('item'):
print "Title:", title. encode('latin-1','replace')
Get a login from BugMeNot.
BugMeNot provides logins/passwords for sites which have a compulsory registration.
Here's a simple function which returns a login/password for a given domain or URL.
''' Returns a login/password for a given domain using BugMeNot.
Will return (None, None) if no login is available.
if not url. lower().startswith(''): url = ""+url.
address = 'bugmenot/view/%s? utm_source=extension&utm_medium=firefox' % domain.
Note: It looks like BugMeNot sometimes serves an error page, or tells you that no login are available although they are. Você está avisado.
Logging into a site and handling session cookies.
Here's an example of logging into a website and using the session cookie for further requests (We log into imdb).
request = urllib2.Request("imdb/register/login", data)
url = urlOpener. open(request) # Our cookiejar automatically receives the cookies.
# (which is the cookie containing the session identifier.)
if not 'id' in [cookie. name for cookie in cookiejar]:
raise ValueError, "Login failed with login=%s, password=%s" % (login, password)
# (Our urlOpener automatically uses cookies from our cookiejar)
This requires Python 2.4 or later (because of the cookielib module).
Note that you can have cookie support for older versions of Python with third-party modules ( ClientCookie for example).
For forms: Menu "Tools" > "Page info" > "Forms" tab. For cookies: Menu "Tools" > "Options" > "Privacy" tab > "Cookies" tab > "View cookies" button.
Most of the time, you do not need to logout.
Searching on Google.
This class searchs Google and returns a list of links (URL). It does not use the Google API.
It automatically browses the different result pages, and gathers only the URLs.
re_links = repile(r'<a class=l href="(.+?)"',re. IGNORECASE|re. DOTALL)
'''Searchs Google for these terms. Returns only the links (URL).
Duplicates links are removed, links are sorted.
print "Google: Searching for '%s'" % terms.
print "Google: Querying page %d (%d links found so far)" % (currentPage/100+1, len(links))
address = "google/search? q=%s&num=100&hl=en&start=%d" % (urllib. quote_plus(terms),currentPage)
for url in GoogleHarvester. re_links. findall(page):
if "</div>Next</a></table></div><center>" in page: # Is there a "Next" link for next page of results ?
currentPage += 100 # Yes, go to next page of results.
break # No, break out of the while True loop.
print "Google: Found %d links." % len(links)
links = GoogleHarvester().harvest('monthy pythons')
Links found will be written in the file links. txt .
Building a basic GUI application step-by-step in Python with Tkinter and wxPython.
Here is a full tutorial on how create a GUI. You will learn to build a GUI step-by-step.
Tkinter and wxPython are compared. Each and every object, method and parameter are explained.
Flatten nested lists and tuples.
Here's a function which flattens nested lists and tuples.
''' Flattens nested lists and tuples in L. '''
if type(x) in (types. ListType, types. TupleType): _flatten(x, a)
[5, 'foo', -52.5, 'bar', 'foo', 'bar', 'bar', 1, 2, 3, 4, 5, 6, 'foo', 'bar']
Efficiently iterating over large tables in databases.
When reading rows from a SQL database, you have several choices with the DB-Api:
fetchone() : Read one row at time. fetchmany() : Read several rows at time. fetchall() : Read all rows at time. Which one do you think is better ?
Let's see: I have a 140 Mb database in SQLite3 format with a big table. Maybe reading all rows at once is faster ?
cur. execute('select discid, body from discussion_body;')
for row in cur. fetchall():
As soon as we run the program, it eats up 140 Mb of memory. Oops !
Why ? Because fetchall() loads all the rows in memory at once.
We don't want our programs to be a memory hog. So using fetchall() is barely recommenced.
There are better ways of doing this. So let's read row by row with fetchone() :
cur. execute('select discid, body from discussion_body;')
for row in iter(cur. fetchone, None):
fetchone() returns one row at time, and returns None when no more rows are available: In order to use fetchone() in a for loop, we have to create an iterator which will call fetchone() repeatedly for reach row, until the None value is returned.
cur. execute('select discid, body from discussion_body;')
for row in iter(cur. fetchmany, []):
fetchmany() returns a list of row at time (of variable size), and returns an empty list when no more rows as available: In order to use fetchmany() in a for loop, we have to create an iterator which will call fetchmany() repeatedly, until an emptylist [] is returned.
(Note that we did not specify how many rows we wanted at once: It's better to let the database backend choose the best threshold.)
fetchmany() is the optimal way of fetching rows: It does not use a lot of memory like fetchall() and it's usually faster than fetchone() .
Note that in our example we used SQLite3, which it not network-based. The difference between fetchone/fetchmany is even greater with network-based databases (mySQL, Oracle, Microsoft SQL Server. ), because those databases also have a certain granularity for network packets.
A range of floats.
Python has a range() function which produces a range of integers.
But it does not support floats.
''' Computes a range of floating value.
start (float) : Start value.
end (float) : End value.
steps (integer): Number of values.
A list of floats.
[0.25, 0.51249999999999996, 0.77500000000000002, 1.0375000000000001, 1.3]
return [start+float(i)*(stop-start)/(float(steps)-1) for i in range(steps)]
[0.25, 0.51249999999999996, 0.77500000000000002, 1.0375000000000001, 1.3]
Converting RGB to HSL and back.
HSL (Hue/Saturation/Lightness) is a more human-accessible representation of colors, but most computer work in RGB mode.
Hue : The tint (red, blue, pink, green. ) Saturation : Does the color falls toward grey or toward the pure color itself ? (It's like the "color" setting of your TV). 0=grey 1=the pure color itself. Lightness : 0=black, 0.5=the pure color itself, 1=white Here are two functions which convert between the two colorspaces. Examples are provided in docstrings.
''' Converts HSL colorspace (Hue/Saturation/Value) to RGB colorspace.
Formula from easyrgb/math. php? MATH=M19#text19.
h (float) : Hue (0. 1, but can be above or below.
(This is a rotation around the chromatic circle))
s (float) : Saturation (0. 1) (0=toward grey, 1=pure color)
l (float) : Lightness (0. 1) (0=black 0.5=pure color 1=white)
(r, g,b) (integers 0. 255) : Corresponding RGB values.
def Hue_2_RGB( v1, v2, vH ):
while vH<0.0: vH += 1.0.
while vH>1.0: vH -= 1.0.
if 6*vH < 1.0 : return v1 + (v2-v1)*6.0*vH.
if 2*vH < 1.0 : return v2.
if 3*vH < 2.0 : return v1 + (v2-v1)*((2.0/3.0)-vH)*6.0.
if not (0 <= l <=1): raise ValueError,"l (lightness) parameter must be between 0 and 1."
if l<0.5 : var_2 = l * ( 1.0 + s )
else : var_2 = ( l + s ) - ( s * l )
var_1 = 2.0 * l - var_2.
r = 255 * Hue_2_RGB( var_1, var_2, h + ( 1.0 / 3.0 ) )
g = 255 * Hue_2_RGB( var_1, var_2, h )
b = 255 * Hue_2_RGB( var_1, var_2, h - ( 1.0 / 3.0 ) )
''' Converts RGB colorspace to HSL (Hue/Saturation/Value) colorspace.
Formula from easyrgb/math. php? MATH=M18#text18.
(r, g,b) (integers 0. 255) : RGB values.
(h, s,l) (floats 0. 1): corresponding HSL values.
(0.69953051643192476, 0.69607843137254899, 0.59999999999999998)
if not (0 <= r <=255): raise ValueError,"r (red) parameter must be between 0 and 255."
if not (0 <= g <=255): raise ValueError,"g (green) parameter must be between 0 and 255."
if not (0 <= b <=255): raise ValueError,"b (blue) parameter must be between 0 and 255."
var_Max = max( var_R, var_G, var_B ) # Max. value of RGB.
del_Max = var_Max - var_Min # Delta RGB value.
if l<0.5: s = del_Max / ( var_Max + var_Min )
else: s = del_Max / ( 2.0 - var_Max - var_Min )
del_R = ( ( ( var_Max - var_R ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max.
del_G = ( ( ( var_Max - var_G ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max.
del_B = ( ( ( var_Max - var_B ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max.
if var_R == var_Max : h = del_B - del_G.
elif var_G == var_Max : h = ( 1.0 / 3.0 ) + del_R - del_B.
elif var_B == var_Max : h = ( 2.0 / 3.0 ) + del_G - del_R.
while h < 0.0: h += 1.0.
while h > 1.0: h -= 1.0.
Note that h (hue) is not constrained to 0. 1 because it's an angle around the chromatic circle: You can walk several times around the circle :-)
Edit : Doh ! Of course, I forgot that Python comes with batteries included: The colorsys module already does that. Repeat after me: RTFM RTFM RTFM.
Generate a palette of rainbow-like pastel colors.
This function generates a palette of rainbow-like pastel colors.
Note that it uses the HSL_to_RGB() and the floatrange() functions.
""" Return different pastel colours.
n (integer) : The number of colors to return.
A list of colors in HTML notation (eg.['#cce0ff', '#ffcccc', '#ccffe0', '#f5ccff', '#f5ffcc'])
['#cce0ff', '#f5ccff', '#ffcccc', '#f5ffcc', '#ccffe0']
start_hue = 0.6 # 0=red 1/3=0.333=green 2/3=0.666=blue.
# We take points around the chromatic circle (hue):
# (Note: we generate n+1 colors, then drop the last one ([:-1]) because it equals the first one (hue 0 = hue 1))
return ['#%02x%02x%02x' % HSL_to_RGB(hue, saturation, lightness) for hue in floatrange(start_hue, start_hue+1,n+1)][:-1]
Columns to rows (and vice-versa)
You have a table. You want the columns to become rows, and rows to become columns.
I told you it was easy :-)
How do I create an abstract class in Python ?
mmm. Python does not know this "abstract class" concept. We do not really need it.
I don't care what abstract "duck" class it is derived from as long as it quacks when I call the. quack() method.
If it has a. quack() method, then that's good enough for me.
This will create the file mylog. txt which contains the error instead of displaying the error on the console.
I don't need the class myLogger to derive from an abstract "IOstream" or "Console" class thing: It just needs to have the. write() method. That's all I need.
But you do can enforce some checks this way:
if self.__class__ is myAbstractClass:
raise NotImplementedError ,"Class %s does not implement __init__(self)" % self.__class__.
raise NotImplementedError ,"Class %s does not implement method1(self)" % self.__class__.
If you try to call a method which is not implemented in a derived class, you will get an explicit "NotImplementedError" exception.
File "myprogram. py", line 19, in <module>
File "myprogram. py", line 10, in method1.
raise NotImplementedError,"Class %s does not implement method1(self)" % self.__class__.
NotImplementedError: Class __main__.myClass does not implement method1(self)
matplotlib, PIL, transparent PNG/GIF and conversions between ARGB to RGBA.
Yes, that's a lot of things in a single snippet, but if you work with matplotlib or PIL, you will probably need it some day:
Generate a matplotlib figure without using pylab Get a transparent bitmap from a matplotlib figure Get a PIL Image object from a matplotlib Figure Convert ARGB to RGBA Save a transparent GIF and PNG.
import matplotlib, matplotlib. backends. backend_agg.
# or use figure. set_size_inches() to resize it.
# and especially this example:
tempBuffer = [None]*len(stringImage) # Create an empty array of the same size as stringImage.
im = Image. fromstring("RGBA", (int(w),int(h)), stringImage)
im = im. convert('RGB').convert("P", dither=Image. NONE, palette=Image. ADAPTIVE)
# PIL ADAPTIVE palette uses the first color index (0) for the white (RGB=255,255,255),
# so we use color index 0 as the transparent color.
You can test both images with a non-white background:
The PNG always look better, especially on darker backgrounds.
IE 5.5 and 6 do not support transparent PNG. Período. So you may have to favor the. GIF format. Your mileage may vary.
Note 1: The ARGB to RGBA conversion could probably be made faster using numpy, but I haven't investigated.
Automatically crop an image.
Here's a function which removes the useless white space around an image. It's especially handy with matplotlib to remove the extraneous whitespace around charts.
In case of transparent images, the image transparency is used to determine what to crop. Otherwise, this function will try to find the most popular color on the edges of the image and consider this color "whitespace". (You can override this color with the backgroundColor parameter)
It requires the PIL library.
'''Intelligent automatic image cropping.
This functions removes the usless "white" space around an image.
to choose what to crop.
on the edges of the image and consider this color "whitespace".
(You can override this color with the backgroundColor parameter)
image (a PIL Image object): The image to crop.
backgroundColor (3 integers tuple): eg. (0,0,255)
The color to consider "background to crop".
If the image is transparent, this parameters will be ignored.
If the image is not transparent and this parameter is not.
provided, it will be automatically calculated.
a PIL Image object : The cropped image.
''' Compute who's the most popular color on the edges of an image.
image: a PIL Image object.
The most popular color (A tuple of integers (R, G,B))
pixels = left. tostring() + right. tostring() + top. tostring() + bottom. tostring()
for i in range(0,len(pixels),3):
if RGB in counts:
mostPopularColor = sorted([(count, rgba) for (rgba, count) in counts. items()],reverse=True)[0][1]
# Otherwise, we look at the pixels around the image (top, left, bottom and right)
# and use the most used color as the color to crop.
if 'A' in image. getbands(): # If the image has a transparency layer, use it.
# This works for all modes which have transparency layer.
if not backgroundColor:
# Crop a non-transparent image.
#.getbbox() always crops the black color.
# So we need to substract the "background" color from our image.
bg = Image. new("RGB", image. size, backgroundColor)
diff = ImageChops. difference(image, bg) # Substract background color from image.
bbox = diff. getbbox() # Try to find the real bounding box of the image.
raise NotImplementedError, "Sorry, this function is not implemented yet for images in mode '%s'." % image. mode.
Crop non-transparent image in other modes (palette, black & white).
Counting the different words.
A quick way to enumerate the different species in a population (in our case: the different words used and their count):
This is the kind of thing you could use - for example - to see how many files have the same size, same name or same checksum.
for item in items:
if item in counters:
print sorted([(counter, word) for word, counter in counters. items()],reverse=True)[0][1]
Most popular word:
You may change the for loop this way:
This works too, but that's slighly slower than " if item in counters " because generating an exception involves some overhead (creating an KeyError exception object).
Quick code coverage.
How can you be sure you have tested all parts of your program ? This is an important question, especially if you write unit tests.
Python has an undocumented module capable of performing code coverage: Trace .
tracer = trace. Trace(ignoredirs=[sys. prefix, sys. exec_prefix],trace=0,count=1,outfile=r'./coverage_dir/counts')
This will create a coverage_dir subdirectory containing. cover files: These files will tell you how many times each line has been executed, and which lines were not executed.
''' Converts. cover files generated by the Python Trace module to. html files.
You can generate cover files this way:
tracer = trace. Trace(ignoredirs=[sys. prefix, sys. exec_prefix],trace=0,count=1,outfile=r'./coverage_dir/counts')
directory (string): The directory where the *.cover files are located.
The html files are written in the input directory.
# Note: This function is a quick & dirty hack.
border: 1px solid #ccc;
font-family:"DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace;
indexHtml = "" # Index html table.
for filename in glob. glob(os. path. join(directory,'*.cover')):
print "Processing %s" % filename.
for line in filein:
if line[5] == ':': runcount = cgi. escape(line[:5].strip())
htmlTable += '<tr class="%s"><td align="right">%s</td><td align="right">%d</td><td nowrap>%s</td></tr>\n' % (cssClass, runcount, linecounter, cgi. escape(line[7:].rstrip()).replace(' ','&nbsp;'))
html = '''<html><!-- Generated by cover2html. py - sebsauvage --><head><link rel="stylesheet" href="style. css" type="text/css"></head><body>
''' % (cgi. escape(sourceFilename),coveragePercent) + htmlTable + '</body></html>'
print "Writing index. html"
file. write('''<html><head><link rel="stylesheet" href="style. css" type="text/css"></head>
Run this program in the directory containing your. cover files, then simply open index. html .
There are other code coverage modules:
Trapping exceptions to the console under wxPython.
When an exception occurs in your wxPython program, it is displayed in a wxPython window. Sometimes, you just want everything to be logged to the console (stderr), like any other Python program. Here's how to do it:
STDERR = sys. stderr # Keep stderr because wxPyhon will redirect it.
app = MyWxApplication() # Start you wxPython application here.
Of course, you can use this trick to log everything to a file if you prefer.
Get a random "interesting" image from Flickr.
Note: Flickr website has changed, and the following code will not work. It is kept as an example.
''' Returns a random "interesting" image from Flickr.
The image is saved in current directory.
the image is not saved and None is returned.
filename (string): An optional filename.
If filename is not provided, a name will be automatically provided.
(string) Name of the file.
None if the image is not available.
# Get a random "interesting" page from Flickr:
print 'Getting a random "interesting" Flickr page. '
# Choose a random date between the beginning of flickr and yesterday.
yesterday = datetime. datetime. now() - datetime. timedelta(days=1)
randomDay = flickrStart + datetime. timedelta(days=random. randint(0,nbOfDays))
# Get a random page for this date.
url = 'flickr/explore/interesting/%s/page%d/' % (randomDay. strftime('%Y/%m/%d'),random. randint(1,20))
raise ValueError,"Oops. could not find images URL in this page. Either Flickr has problem, or the website has changed."
urls = [url. replace('_m. jpg','_o. jpg') for url in urls]
print 'Downloading %s' % url.
except MemoryError: # I sometimes get this exception. Why ?
return None # Sometimes flickr returns nothing.
return None # Image too big. Discard it.
return None # "This image is not available" image.
if not filename:
WARNING: These images may be NSFW.
Why is Python a good beginner language ?
Python is a good language to learn programming, because you can start to write in scripting mode (variables, assigment. ), then learn new concepts (procedural programming, conditional branching, loops, objet orientation. ).
Then learn about variables and inputs/outputs:
Then learn about procedural programming (loops, conditional branching. ):
print "More than 10 !"
Then learn structured programming (functions, return values, recursivity. ):
Then learn object orientation:
print "Woof woof !"
And more importantly, experimenting using the Python console (as Python does not require explicit compilation).
public static void main ( String args[] )
System. out. println ( "Hello World!" ) ;
printf ( "Hello, World!\n" ) ;
Why Python is not a good beginner language.
Memory allocation problems (malloc/free and try/except/finally blocks). More generally, unexperienced Python programers may not be aware of ressources allocation issues (as the Python garbage collector takes care of most problems (file handles, network connections, etc.)).
Reading LDIF files.
LDIF files contain information exported from LDAP servers.
For example, you can use the LDIF class provided in python-ldap. sourceforge. This module provides a nifty LDAP client, but if you need just to read LDIF files, take only ldif. py .
if 'person' in entry['objectclass']:
print "Identifier = ",entry['uid'][0]
print "FirstName = ",entry. get('givenname',[''])[0]
print "LastName = ",entry. get('sn',[''])[0]
Capture the output of a program.
It's easy to capture the output of a command-line program.
For example, under Windows, we will get the number of bytes received by the workstation by picking up the " Bytes received " line displayed by this command: net statistics workstation.
for line in sout. split('\n'):
if line. strip().startswith('Bytes received'):
print "This workstation received %s bytes." % line. strip().split(' ')[-1]
Note that the subprocess module also allows you to send data to program input .
Thus you can communicate with the command-line program like if it was a user typing (read program output, then react by sending characters, etc.)
for line in sout. split('\n'):
if line. strip().startswith('Bytes received'):
print "This workstation received %s bytes." % line. strip().split(' ')[-1]
myprocess. wait() # We wait for process to finish.
print myprocess. returncode # then we get its returncode.
Writing your own webserver.
A webserver is relatively easy to understand:
The client (browser) connects to the webserver and sends it HTTP GET or POST request (including path, cookies, etc.)
You can take the entire control of this process and write your own webserver in Python.
Here is a simple webserver which say " Hello, world ! " on localhost:8088/
server = BaseHTTPServer. HTTPServer(('', 8088), MyHandler)
We create a class which will handle HTTP requests arriving on the port ( MyHandler ). We only handles GET requests ( do_GET ). We respond with HTTP code 200, which means "everything is ok." ( self. send_response(200) ). We tell the browser that we're about to send HTML data ( self. send_header('Content-type','text/html') ). Then we sends the HTML itself ( self. wfile. write(. ) )
From there, you can extend the server:
by responding with specific HTTP error codes if something goes wrong (404 for "Not found", 400 for "Invalid request", 401 for "No authorized", 500 for "Internal server error", etc.) by serving different html depending on the requested path ( self. path ). by serving files from disk or pages (or images !) generated on the fly. by sending html data (text/html), plain text (text/plain), JPEG images (image/jpeg), PNG files (image/png), etc. by handling cookies (from self. headers) by handling POST requests (for forms and file uploads) etc.
Possibilities are endless.
But there are some reasons why you should not try to write your own webserver:
You webserver can only server one request at time. For high-traffic websites, you will need to either fork, use threads or use asynchronous sockets. There are plenty of webserver which are already highly optimized for speed and will be much faster than what you are writing.
While writing your own webserver can be fun, think twice before putting this into production.
SOAP clients.
I have to use a SOAP webservice.
(Yeah. I know SOAP is a mess, and I'd better not touch that, but I have no choice.)
First try: SOAPy. Huu. last updated April 26, 2001 ? Try to run it. Oops it is based on xmllib which is deprecated in Python. No luck !
SyntaxError: from __future__ imports must occur at the beginning of the file. WTF ?
By the way, SOAP. py depends on pyXML. which is not maintained since late 2004 and is not available for Python 2.5 !
What am I supposed to do with this ?
Ok, let's try another one:
Visual Studio 2003 was not found on this system. WTF .
Am I supposed to buy an expensive and outdated IDE to use this Python SOAP library ?
Out of question !
So what am I left with ?
Java and have decent implementations, Python has none (At least not without buying VisualStudio on Windows).
It does not understand WSDL, but that's not a big deal, and it's good enough for me .
# delayed stock quote demo (xmethods)
url = "66.28.98.121:9090/soap" # Put webservice URL here.
def getQuote(self, symbol):
request = SoapRequest(" getQuote") # Create the SOAP request.
SoapElement(request, "symbol", "string", symbol) # Add parameters.
response = self. call(action, request) # Call webservice.
return float(response. findtext("Result")) # Parse the answer and return it.
print "MSFT", q. getQuote("MSFT")
print "LNUX", q. getQuote("LNUX")
No bell and whistles, but it does the job .
Archive your whole GMail box.
Gmail is neat, but what happens if you account disappears ? (Shit happens. and Google gives no warranty.)
Better safe than sorry: This baby can archive your whole GMail box in a single standard mbox file which can be easily stored and imported into any email client.
It's easy: Run it, enter login and password, wait, and you have a yourusername. mbox file.
Note: You must have activated IMAP in your GMail account settings.
""" GMail archiver 1.1.
Simply enter your login and password, and all your emails will.
be downloaded from GMail and stored in a standard mbox file.
This inclues inbox, archived and sent mails, whatever label you applied.
Spam is not downloaded.
Sйbastien SAUVAGE - sebsauvage at sebsauvage dot net.
Webmaster for sebsauvage/
In no event will the authors be held liable for any damages arising from.
the use of this software.
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
claim that you wrote the original software. If you use this software.
in a product, an acknowledgment in the product documentation would be.
appreciated but is not required.
be misrepresented as being the original software.
- GMail settings in english.
user = raw_input("Enter your GMail username:")
pwd = getpass. getpass("Enter your password: ")
resp, items = m. search(None, "ALL")
print "Found %d emails." % len(items)
for emailid in items:
print "Downloading email %s (%d remaining)" % (emailid, count)
resp, data = m. fetch(emailid, "(RFC822)")
# We duplicate the From: line to the beginning of the email because mbox format requires it.
from_line = [line for line in email_body[:16384].split('\n') if line. lower().startswith('from:')][0].strip()
print " 'from:' unreadable."
email_body = "From %s\n%s" % (from_line[5:].strip(),email_body)
Note that depending on your language, the folder name will change. For example, if you use the french version, change "[Gmail]/All Mail" to "[Gmail]/Tous les messages" .
Performing HTTP POST requests.
When using urllib or urllib2 to send HTTP requests, it default sends HTTP GET requests. Sometime, you need to POST , either because the remote form does not support GET, or you want to send a file, or you do not want the request parameters to appear in proxy logs or browser history.
Here's how to do it:
request = urllib2.Request(url, data)
response = urllib2.urlopen(request) # This request is sent in HTTP POST.
This is equivalent to the GET request: commentcamarche/search/search. php3?Mot=Gimp.
Read a file with line numbers.
Sometime when you read a file, you want to have also the line number you are working on. That's easy to do:
for (num, value) in enumerate(file) :
print "line number",num,"is:",value.
This is very handy - for example - when importing a file and signaling which line is erroneous.
Filter all but authorized characters in a string.
mmm. maybe there's a better way to do this:
& gt; & gt; & gt; filtered = ''.join([c for c in mystring if c in 'abcdefghijklmnopqrstuvwxyz0123456789_-. '])
hello world. badscript.
Writing your own webserver (using web. py)
Writing your own webserver can be fun, but it's tedious. web. py is a very nice minimalist web framework which simplifies the whole thing.
Here is a no-brainer example:
print "Hello, %s !" % name.
/sayHelloTo/(\w+) is a regular expression. All URLs arriving on the server matching this pattern will call myfunction . Then myfunction will handle the GET request and return a response.
We got it ! We wrote a page capable of handling requests with parameters in 7 lines of code. Nice.
web. py also has features to handle html templates, database access and so on.
XML-RPC: Simple remote method call.
Let's call a method:
We know the method sayHello() is executed on the same computer. How about a calling the sayHello() method of another computer ?
Pure sockets (which is a pain in the ass because you have to deal with message encoding/formatting and low-level transmission problem (end-of-message)) Webservices/SOAP (which is a pain in the ass because of its horrendous complexity) XML-RPC is simple and does the job. Let's see:
You see ? Sheer simplicity. You just declare the server, then call the method as usual.
The sayHello() method is executed on the server localhost:8888 (which can be another computer). The xmlrpclib library takes care of the low-level details.
def sayHello(self, name):
return u"Hello, %s !" % name.
server = SimpleXMLRPCServer. SimpleXMLRPCServer(("localhost", 8888)) # (2)
print "Listening on port 8888"
You define a class with all its methods ( MyClass ) You create a XML-RPC server on a given IP/port ( SimpleXMLRPCServer ) You register your objet on this server ( register_instance ) On the low-level side, XML-RPC basically converts you method calls in XML and sends them in a HTTP request.
Performance : In our example, the server can only serve one request at once. For better performance, you should either use multi-threading, asynchronous sockets, forking. Performance (2) : Keep in mind that objets that you pass back and forth between client and server are transmitted on the network. Don't send large datasets. Or think about zlib/base64-encoding them. Security : In our example, anyone can call your webservice. You should implement access control (for example, using HMAC and a shared secret). Security (2) : Objects are transmitted in clear text. Anyone can sniff the network and grab your data. You should use HTTPS or use an encryption scheme. Text encoding : Although Python handles UTF-8 nicely, most XML-RPC services can only handle ASCII. You sometimes will have to use UTF-7 (Luckly, Python knows how to "talk" UTF-7).
Signing data.
In our previous webservice, anyone can call the server. That's bad.
We can sign the data to make sure:
that only authorized programs will be able to call the webservice. that data was not tampered during transport. HMAC is a standardized method for signing data. It takes data and a key , and produces a signature .
& gt; & gt; & gt; print hmac. new("mykey","Hello world !").hexdigest()
d157e0d7f137c9ffc8d65473e038ee86 is the signature of the data "Hello world !" with the key "mykey" .
A different message or a different key will produce a different signature.
It's impossible to produce the correct signature for the data without the correct key. The slighest modification in the message will produce a different signature too.
Let's do it.
The client signs the data and sends the signature and the data to the server.
print server. sayHello( signature, name)
Our server receives the signature and the data ( name ), and checks if the signature is correct.
def sayHello(self, signature , name):
if hmac. new(key, name).hexdigest() != signature:
return "Wrong signature ! You're a hacker !"
return u"Hello, %s !" % name.
server = SimpleXMLRPCServer. SimpleXMLRPCServer(("localhost", 8888)) # (2)
print "Listening on port 8888"
Let's use our client:
The server has accepted our signature.
Hacker with a wrong key.
key = "idontknowthekey" # I don't know the correct key. I try anyway !
We call the server:
Wrong signature ! You're a hacker !
The server rejected us because we used the wrong key, which cannot generate a correct signature.
Hacker tampered the message.
I try to alter the message and send it to the server with the same signature:
signature = "f927a5f8638f9dc3eaf0804f857e6b34" # I sniffed the signature of "Homer" from the network.
name = " Superman " # I changed "Homer" to "Superman".
We call the server:
Wrong signature ! You're a hacker !
The server detected that the message was modified and rejected us.
Conclusion, facts and hints.
Trying to call the server when you don't have the correct key is pointless. You will never be able to generate the correct signature.
Just don't forget to import hashlib .
& gt; & gt; & gt; data_to_sign = "###".join(str(i) for i in data)
& gt; & gt; & gt; print data_to_sign, signature.
Replay : A hacker can pickup the message sent by the client, and replay it as-is on the server: The server will accept the message. Protection: You can protect against this by inserting a counter in the message, or a date/time, etc.
HMAC is a great and simple way to ensure data authenticity and integrity. It's fast to compute and super-resistant.
Week of the year.
Get the week of the year (week starts on Monday):
Stripping HTML tags.
When grabbing HTML from the web, you sometimes just want the text, not the HTML tags. Here's a function to remove HTML tags:
''' Strips HTML tags.
Taken from aspn. activestate/ASPN/Cookbook/Python/Recipe/440481.
You may then want to decode HTML entites:
Decode HTML entities to Unicode characters.
When grabbing HTML from the web, when you have stripped HTML tags, it's always a pain to convert HTML entities such as &eacute; or &#233; to simple characters.
Here's a function which does exactly that, and outputs a Unicode string:
# First convert alpha entities (such as &eacute;)
# (Inspired from mail. python/pipermail/python-list/2007-June/443813.html)
if entity in htmlentitydefs. name2codepoint:
return u" " # Unknown entity: We replace with a space.
t = re. sub(u'&(%s);' % u'|'.join(htmlentitydefs. name2codepoint), entity2char, s)
t = re. sub(u'&#(\d+);', lambda x: unichr(int(x. group(1))), t)
return re. sub(u'&#x(\w+);', lambda x: unichr(int(x. group(1),16)), t)
Hello world ! й й й.
So if you just want to extract the text from a webpage, you can do:
Ready for indexing !
Maybe you'll want to strip accented characters before ? Ok:
Stripping accented characters.
Stripping accents ? Isso é fácil. when you know how (as seen on the french Python wiki) :
That's handy - for example - when indexing or comparing strings.
A dictionnary-like object for LARGE datasets.
Python dictionnaries are very efficient objects for fast data access. But when data is too large to fit in memory, you're in trouble.
Here's a dictionnary-like object which uses a SQLite database and behaves like a dictionnary object:
You can work on datasets which to not fit in memory. Size is not limited by memory, but by disk. Can hold up to several tera-bytes of data (thanks to SQLite). Behaves like a dictionnary (can be used in place of a dictionnary object in most cases.) Data persists between program runs. ACID (data integrity): Storage file integrity is assured. No half-written data. It's really hard to mess up data. Efficient: You do not have to re-write a whole 500 Gb file when changing only one item. Only the relevant parts of the file are changed. You can mix several key types (you can do d["foo"]=bar and d[7]=5468 ) (You can't to this with a standard dictionnary.) You can share this dictionnary with other languages and systems (SQLite databases are portable, and the SQlite library is available on a wide range of systems/languages, from mainframes to PDA/iPhone, from Python to Java/C++/C#/perl. )
from sqlite3 import dbapi2 as sqlite.
''' dbdict, a dictionnary-like object for large datasets (several Tera-bytes) '''
self. db_filename = "dbdict_%s. sqlite" % dictName.
if not os. path. isfile(self. db_filename):
self. con. execute("create table data (key PRIMARY KEY, value)")
row = self. con. execute("select value from data where key=?",(key,)).fetchone()
if not row: raise KeyError.
if self. con. execute("select key from data where key=?",(key,)).fetchone():
self. con. execute("update data set value=? where key=?",(item, key))
self. con. execute("insert into data (key, value) values (. )",(key, item))
if self. con. execute("select key from data where key=?",(key,)).fetchone():
self. con. execute("delete from data where key=?",(key,))
return [row[0] for row in self. con. execute("select key from data").fetchall()]
Use it like a standard dictionnary, except that you give it a name (eg."mydummydict"):
# At this point, foo and bar are *written* to disk.
You can access your dictionnary later on:
print "John is in there !"
You can open dbdict_mydummydict. sqlite with any other SQLite-compatible tool.
Some possible improvements:
You can't directly store Python objects. Only numbers, strings and binary data. Objects need to be serialized first in order to be stored. Database path is current directory. It could be passed as a parameter. keys() could be improve to use less memory through the use of an iterator or yield . We do not currently handle database connection closing. The file stays open until the object is destroyed.
Renaming. ogg files according to tags.
If you have properly-tagged. OGG files (artist, album. ) but with wrong filenames (eg. Track01.cda. ogg ), the following program will rename files according to OGG tags.
The ogg files will be renamed to: artist - album - track number - track title. ogg.
Vorbis headers parsed for stream 1, information follows.
Vendor: Xiph libVorbis I 20070622 (1.2.0)
Upper bitrate not set.
Lower bitrate not set.
User comments section follows.
title=Enjoy The Ride.
Vorbis stream 1:
Total data length: 5238053 bytes.
Playback length: 4m:02.613s.
Average bitrate: 172,721027 kb/s.
Logical stream 1 ended.
We parse this output to get artist, album, title and track number (We simply search for strings like "album=", "artist=", etc.)
# Renames. ogg files accotding to OGG tags: artist - album - track number - title.
# This program is public domain.
for line in sout. split('\n'):
for item in ("title","artist","album","tracknumber"):
newfilename = "%(artist)s - %(album)s - %(tracknumber)02d - %(title)s. ogg" % trackinfo.
for filename in glob. glob("Track*.cda. ogg"):
Morcheeba - Dive Deep - 02 - Riverbed. ogg.
Morcheeba - Dive Deep - 03 - Thumbnails. ogg.
Morcheeba - Dive Deep - 04 - Run Honey Run. ogg.
Morcheeba - Dive Deep - 05 - Gained The World. ogg.
Morcheeba - Dive Deep - 06 - One Love Karma. ogg.
Morcheeba - Dive Deep - 07 - Au-delа. ogg.
Morcheeba - Dive Deep - 08 - Blue Chair. ogg.
Morcheeba - Dive Deep - 09 - Sleep On It. ogg.
Morcheeba - Dive Deep - 10 - The Ledge Beyond The Edge. ogg.
Morcheeba - Dive Deep - 11 - Washed Away. ogg.
Reading configuration (.ini) files.
Reading. ini files such as the following one is easy, because Python has an module dedicated to that.
Let's write a program which reads all parameters from all sections:
for section in config. sections():
print "In section %s" % section.
for (key, value) in config. items(section):
print " Key %s has value %s" % (key, value)
Key john has value doe.
Key var3 has value kiki.
Key var4 has value roro.
In section sectionA.
Key homer has value simpson.
Key var1 has value toto.
Key var2 has value titi.
Note that parameters and sections are in no particular order . Never expect to have the parameters in order.
You can also read a single parameter:
There are a few gotchas regarding case:
Parameters are case - in sensitive Sections are case-sensitive.
& gt; & gt; & gt; print config. get(" SECTIONB ","john")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\python25\lib\ConfigParser. py", line 511, in get.
ConfigParser. NoSectionError: No section: 'SECTIONB'
When reading those file, you should be ready to handle missing parameters, which can be done using has_option() or by catching the exception ConfigParser. NoOptionError :
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\python25\lib\ConfigParser. py", line 520, in get.
raise NoOptionError(option, section)
ConfigParser. NoOptionError: No option 'duffy' in section: 'sectionB'
& gt; & gt; & gt; if config. has_option ("sectionB","Duffy"):
. print "Oops. option not found !"
Oops option not found !
. print "Oops. option not found !"
Oops option not found !
miniMusic - a minimalist music server.
Serving your MP3/OGG collection over the LAN ? Here's a simple server which does the trick.
Copy this python program in your music folder and run. Point you browser are mycomputer:8099 If your browser is configured properly, the m3u file will immediately start to playing in your favorite player. That's all is takes !
# Run me in the directory of your MP3/OGG files.
# and point your browser at me.
# Great for a simple LAN music server.
# Get all. mp3/.ogg files from subdirectories, and built a playlist (.m3u)
for dirpath, dirnames, filenames in os. walk(directory):
for filename in filenames:
if os. path. splitext(filename)[1].lower() in (u'.mp3',u'.ogg'):
# urllib. quote does not seem to handle all Unicode strings properly.
if self. path == u"/": # We will return the. m3u file.
else: # Return the music file with proper MIME type.
if ext in MIME_TYPES: mimetype=MIME_TYPES[ext] # Get the correct MIME type for this extension.
else: # File not found ? Will simply return a 404.
print u"Music server ready at %s:%s" % (HOSTNAME, PORT)
Music server ready at mycomputer:8099.
Then point your browser at this URL. If you're prompted to either save or open, choose "Open". Your favorite player will play the songs. For example, in VLC:
(Note that some music players have problems with. m3u files (such as Foobar2000), but most will do fine (VLC, WMP. )).
Explanations.
The ThreadingTCPServer listens on the given port (8099). Each time a client connects, it spawns a new thread and instanciates a miniMusicServer object which will handle the HTTP request ( do_GET() ). Therefore each client has its miniMusicServer objet working for him in a separate thread.
m3u files are simple text files containing the URLs of each music file (. ). Most browsers are configured to open m3u files in media players.
We add EXTINF informations so that the names show up more nicely in audio players.
We use some quote/replace/encode so that special characters in filenames are not mangled by browsers or mediaplayers.
If the file does not exist, we let the base class SimpleHTTPServer display the 404 error page.
FTP through a HTTP proxy.
# (You will have to parse the HTML to extract the list of files and directories.)
If someone knows how to upload a file, I'd appreciate the information.
A simple web dispatcher.
There are plenty of web frameworks out there for Python (such as web. py), but let's write our own again, just for fun.
We need a simple way to map each url to a piece of code. That's what our program below does (Let's see the code first, explanations will follow):
self. wfile. write('Hello. Go to <a href="/form">the form<a>.')
self. wfile. write('<form action="/say" method="GET">Enter a phrase:<input name="phrase" type="text" size="60"><input type="submit" value="Say it !"></form>')
for item in phrase:
self. wfile. write("I say %s<br>" % item)
if action=="": action="hello"
self. wfile. write("404 - Not found")
except TypeError: # URL not called with the proper parameters.
self. wfile. write("400 - Bad request")
print u"Server listening at %s:%s" % (HOSTNAME, PORT)
Puzzled ? I explain: Every url will call the corresponding method.
/hello calls the req_hello() method which displays a welcome page. /form calls the req_form() method which displays a form. /say? phrase=I love you calls the req_say() method which will handle data entered in the form. Sounds too easy ? Let's try it:
The /hello URL simply called the req_hello() method. We have also instructed our server to serve this page as the default page ( if action=="": action="hello" ), so we can call our server like this:
Now let's clic to go to the form:
The /form URL calls the req_form() method which displays the form. Let's enter a phrase and clic " Say it! ".
How nice. The URL /say? phrase=I+love+you called the method req_say() , passing the phrase as parameter.
And if you ask for a non-existing page, it will serve a HTTP 404 error:
The only thing I have to write is one simple method:
self. send_response(200) # 200 means "ok"
self. send_header("Content-Type","text/plain") # We are about to send simple text.
self. end_headers() # We are done with HTTP headers.
self. wfile. write(text[0].upper()) # We send the data itself.
Isso é tudo. Now let's try it:
First, we decode URL parameters with params = cgi. parse_qs(urlparse. urlparse(self. path).query)
For example? foo=bar&homer=simpson&foo=kilroy will return.
So using the url /say? phrase=I love you is equivalent to self. req_say( phrase=['I love you'] )
Not so fast.
You can serve local files : Simply do:
extension = os. path. splitext(filepath)[1].lower() # Get file extension (".jpg", ".mp3". )
mimetype = "application/octet-stream" # Default MIME type when extension is unknown.
if extension in MIME_TYPES: mimetype = MIME_TYPES[ extension ] # Get the MIME type (".jpg"--->"image/jpeg")
self. send_response(200) # We are ok, let's respond.
self. send_header('Content-Type', mimetype ) # Send MIME type in HTTP response headers.
self. end_headers() # We're finished with HTTP headers.
self. wfile. write(open( filepath ,"rb").read()) # Then send the file itself.
extension = os. path. splitext(filepath)[1].lower() # Get file extension (".jpg", ".mp3". )
mimetype = "application/octet-stream" # Default MIME type when extension is unknown.
if extension in MIME_TYPES: mimetype = MIME_TYPES[ extension ] # Get the MIME type (".jpg"--->"image/jpeg")
self. send_response(200) # We are ok, let's respond.
self. send_header('Content-Type', mimetype ) # Send MIME type in HTTP response headers.
self. send_header('Content-Length',str(os. path. getsize(filepath))) # Send response size.
self. end_headers() # We're finished with HTTP headers.
self. wfile. write(open( filepath ,"rb").read()) # Then send the file itself.
sessionid = ''.join([random. choice("abcdefghijklmnopqrstuvwxyz0123456789") for i in range(60)])
A few more hints.
It's possible to create URLs which accept an arbitrary number of parameters:
for (k, v) in kwargs. items():
self. wfile. write(" %s=%s\n" % (k, item))
Using **kwargs , your method will accept any parameters, or even no parameter at all.
You can call it with:
mycomputer/test mycomputer/test? foo=bar&john=doe&foo=55 mycomputer/test? foo=bar&john=doe&a=b&c=d&e=f&g=h kwargs is a dictionnary. The key is the parameter name, the value is a list of values.
For example, in the second example, kwargs =
Separating GUI and processing.
If you don't want your GUI to stall when your program is processing data, you'd better use multi-threading. It's always better to clearly separate the processing from the GUI : Create one class to handle all interface/user-interaction things, and one or several others which will do the real stuff.
while self._value>0 and not self._stop:
self._value = self._value - 1.
print u"Thread: I'm working. (value=%d)" % self._value.
print u"Thread: I have finished."
self. worker. start() # Start the worker thread.
button = Tkinter. Button(self, text=u"Click me to stop",command=self. OnButtonClick)
'''' Called when button is clickec. '''
self. labelVariable. set( u"Button clicked" )
self. worker. stop() # We ask the worker to stop (it may not stop immediately)
while self. worker. isAlive(): # We wait for the worker to stop.
# We display the result:
self. labelVariable. set( u"Result: %d" % self. worker. result() )
In our example, a simple integer is exchanged between the GUI and the worker thread, but it can be more complex objects, or even lists.
You can even have several "worker" objects work at the same time if you want.
Separating GUI and processing, part 2 : Accessing common ressources.
When different threads work on the same ressources, you have a risk of data corruption. The typical example is two threads who want to change the value of the same variable:
On the end, you got a wrong value (6) when you expected 7.
When a thread wants to perform an action on a ressource, it:
asks for the lock (eventually waiting for the lock to be available) perform its operations release the lock. Only one thread can take the lock at the same time. This ensure proper operation:
print "T1: I have the lock. Let's work."
time. sleep(5) # Do my work.
print "T1: Finished"
print "T2: I have the lock. Let's work."
time. sleep(5) # Do my work.
print "T2: Finished"
Which will output:
T2: I have the lock. Let's work.
You can see that thread2 only works when thread1 does not need the ressource anymore.
(In fact, we have here 3 threads: The two we started plus the main thread.)
print "T1: I have the lock. Let's work."
time. sleep(5) # Do my work.
print "T1: Finished"
while not lock. acquire(0):
print "T2: I do not have to lock. Let's do something else."
print "T2: I have the lock. Let's work."
time. sleep(5) # Do my work.
print "T2: Finished"
Which will give:
T2: I do not have to lock. Let's do something else.
T2: I do not have to lock. Let's do something else.
T2: I do not have to lock. Let's do something else.
T2: I do not have to lock. Let's do something else.
T2: I do not have to lock. Let's do something else.
T2: I have the lock. Let's work.
You see that thread2 can continue to work while waiting for the lock.
Imagine two threads wanting to work on two ressources: Both threads want to work on objects A and B , but they do not lock in the same order:
Thread1 will not release the lock on A until it has the lock on B.
Thread2 will not release the lock on B until it has the lock on A.
They block each other. You're toasted. Your program will hange indefinitely. So watch out.
To prevent deadlocks, you may use non-blocking acquire() and decide it's a failure if you could not get the lock after x seconds. At least you will have the chance to handle the error instead of having your program hang forever.
Reducing the number of threads:
Will lower ressource usage (memory, CPU. ) Will make your program easier to debug and maintain. Reducing the number of locks:
Will make your program run faster (no threads waiting for locks). Will reduce the risk of deadlocks.
Locks are interesting, but Queue objects are better. Not only they are thread-safe (you can put and pickup object into/from the Queue without bothering with locking it), but you can pass objects between threads . Threads can pickup all they want from the Queue, re-insert objet, insert new ones, wait for a specific objects or messages to be present in the queue, etc.
You can have one big Queue and put object in it (and only interested threads will pick the relevant object from the Queue), or a Queue per thread, to send order to the thread and get its results (input queue/output queue for example). You can also put special "message" objects in the Queue, for example to ask all threads to die or perform special operations.
Path of current script.
Want to know what is the path of the current script ?
Get current public IP address.
The following module will return your current public IP address.
It uses several external websites to get the address, and will try with another website if one fails (up to 3 times).
''' Returns your public IP address.
Output: The IP address in string format.
None if not internet connection available.
# List of host which return the public IP address:
for i in range(3):
if results: return results[0][0]
pass # Let's try another host.
If you are not connected to the internet, this function will return None .
Bypassing aggressive HTTP proxy-caches.
When you scap the web, you sometimes have to use proxies. The trouble is that some proxies are agressive and will retain an old copy of a web document, whatever no-cache directives you throw at them.
You can add a dummy parameters with a random value:
Most webservers will simply ignore parameters they don't expect, but the cache will see a different URL, and perform an real outgoing request.
Parameters can be added to any URL, even URL pointing to static content (like images).
We use current time and a random number. Chances that the two are identitcal are almost nil. Let's generate a few URLs:
& gt; & gt; & gt; url = u"sebsauvage/images/nbt_gros_oeil. gif? ihatebadlyconfiguredcaches=%s" % randomstring()
Each time you construct the URL, the ihatebadlyconfiguredcaches parameter value will be different, preventing caches to cache the page.
Yes, I know this trick is ugly , but I encountered some very badly behaved caches ignoring all no-cache directives (yes, even in forms ) and this method got rid of the problem.
Make sure the script is run as root.
If you want to make sure you program is run as root:
if os. geteuid() != 0:
print "This program must be run as root. Aborting."
Note that it only works under *nix environments (Unix, Linux, MacOSX. ), but not Windows.
Automated screenshots via crontab.
If you have a script which runs as daemon or cron, you may want to know if a user has started a graphical session. Here's a way to do it (Runs under Linux only).
''' Return the user who is currently logged in and uses the X session.
None if could not be determined.
for line in runprocess(["who","-s"]).split('\n'):
user = line. split(" ")[0]
This is useful, for example, to take a screenshot of the user's screen with scrot :
print "No user logged in."
# If a user is logged in, we take a screenshot:
commandline = 'DISPLAY=:0 su %s - c "scrot /tmp/image. png"' % user.
This trick is needed because when your script runs in crontab, it does not have a full environment and - obviously - no X. So scrot won't run as-is: We have to run it as the user who has a graphical session, and we also force the DISPLAY environment variable so that scrot knows which display to capture.
External links.
Python Idioms and Efficiency: jaynes. colorado. edu/PythonIdioms. html Python speed/Performance tips: wiki. python/moin/PythonSpeed/PerformanceTips Python Grimoire: the. taoofmac/space/Python/Grimoire Python Cookbook: aspn. activestate/ASPN/Python/Cookbook/ 10 Python pitfalls: zephyrfalcon/labs/python_pitfalls. html Python beginner's mistakes: zephyrfalcon/labs/beginners_mistakes. html Python Gotchas: ferg/projects/python_gotchas. html Python Essays: python/doc/essays/ Python FAQs: python/doc/faq/ DaniWeb Python code snippets: daniweb/code/python. html " Answer My Searches " Python code snippets: answermysearches/index. php/category/python/ and of course the famous Python Eggs (lots of links): python-eggs/
Each snippet in this page has an anchor for easier reference. Feel free to link to this page.

GUI Control Types.
Índice.
Text, Edit, UpDown, Picture Button, Checkbox, Radio DropDownList, ComboBox ListBox, ListView, TreeView Link, Hotkey, DateTime MonthCal, Slider, Progress GroupBox, Tab3, StatusBar ActiveX (e. g. Internet Explorer Control) Custom.
Description: A region containing borderless text that the user cannot edit. Often used to label other controls. Exemplo:
In this case, the last parameter is the string to display. It may contain linefeeds (`n) to start new lines. In addition, a single long line can be broken up into several shorter ones by means of a continuation section.
If a width (W) is specified in Options but no rows (R) or height (H), the text will be word-wrapped as needed, and the control's height will be set automatically.
Since the control's contents are in the last parameter of the Gui command, literal commas do not need to be escaped. This is also true for the last parameter of all other commands.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user clicks the text. This can be used to simulate an underlined, blue hyperlink as shown in the following working script:
A double-click can be detected by checking whether A_GuiEvent contains the word DoubleClick.
An ampersand (&) may be used in the text to underline one of its letters. Por exemplo:
In the example above, the letter F will be underlined, which allows the user to press the shortcut key Alt+F to set keyboard focus to the first input-capable control that was added after the text control. To instead display a literal ampersand, specify two consecutive ampersands (&&). To disable all special treatment of ampersands, include 0x80 in the control's options.
Description: An area where free-form text can be typed by the user. Exemplo:
The control will be multi-line if it has more than one row of text. For example, specifying r3 in Options will create a 3-line edit control with the following default properties: a vertical scroll bar, word-wrapping enabled, and the Enter key captured as part of the input rather than triggering the window's default button.
To start a new line in a multi-line edit control, the last parameter (contents) may contain either a solitary linefeed (`n) or a carriage return and linefeed (`r`n). Both methods produce literal `r`n pairs inside the Edit control. However, when the control is saved to its variable via Gui Submit or GuiControlGet, each `r`n in the text is always translated to a plain linefeed (`n). To write the text to a file, follow this example: FileAppend, %MyEdit%, C:\Saved File. txt .
If the control has word-wrapping enabled (which is the default for multi-line edit controls), any wrapping that occurs as the user types will not produce linefeed characters (only the Enter keystroke can do that).
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user or the script changes the contents of the control.
TIP: To load a text file into an Edit control, use FileRead and GuiControl. Por exemplo:
Edit Options.
To remove an option rather than adding it, precede it with a minus sign:
Limit : Restricts the user's input to the visible width of the edit field. Alternatively, to limit input to a specific number of characters, include a number immediately afterward. For example, Limit10 would allow no more than 10 characters to be entered.
Lowercase : The characters typed by the user are automatically converted to lowercase.
Multi : Makes it possible to have more than one line of text. However, it is usually not necessary to specify this because it will be auto-detected based on height (H), rows (R), or contents ( Text ).
Number : Prevents the user from typing anything other than digits into the field (however, it is still possible to paste non-digits into it). An alternate way of forcing a numeric entry is to attach an UpDown control to the Edit.
Password : Hides the user's input (such as for password entry) by substituting masking characters for what the user types. If a non-default masking character is desired, include it immediately after the word Password. For example, Password* would make the masking character an asterisk rather than the black circle (bullet), which is the default on Windows XP. Note: This option has no effect for multi-line edit controls.
ReadOnly : Prevents the user from changing the control's contents. However, the text can still be scrolled, selected and copied to the clipboard.
Tn : The letter T may be used to set tab stops inside a multi-line edit control (since tab stops determine the column positions to which literal TAB characters will jump, they can be used to format the text into columns). If the letter T is not used, tab stops are set at every 32 dialog units (the width of each "dialog unit" is determined by the operating system). If the letter T is used only once, tab stops are set at every n units across the entire width of the control. For example, Gui, Add, Edit, vMyEdit r16 t64 would double the default distance between tab stops. To have custom tab stops, specify the letter T multiple times as in the following example: Gui, Add, Edit, vMyEdit r16 t8 t16 t32 t64 t128 . One tab stop is set for each of the absolute column positions in the list, up to a maximum of 50 tab stops. Note: Tab stops require a multiline edit control.
Uppercase : The characters typed by the user are automatically converted to uppercase.
WantCtrlA [v1.0.44+]: Specify - WantCtrlA (minus WantCtrlA) to prevent the user's press of Control-A from selecting all text in the edit control.
WantReturn : Specify - WantReturn (that is, a minus sign followed by WantReturn) to prevent a multi-line edit control from capturing the Enter keystroke. Pressing Enter will then be the same as pressing the window's default button (if any). In this case, the user may press Control-Enter to start a new line.
WantTab : Causes a tab keystroke to produce a tab character rather than navigating to the next control. Without this option, the user may press Control-Tab to produce a tab character inside a multi-line edit control. Note: Although WantTab also works in a single-line edit control, each tab character is displayed as an empty-box character (though it is stored as a real tab).
-Wrap (minus wrap): Turns off word-wrapping in a multi-line edit control. Since this style cannot be changed after the control has been created, use one of the following to change it: 1) Destroy then recreate the window and its control; or 2) Create two overlapping edit controls, one with wrapping enabled and the other without it. The one not currently in use can be kept empty and/or hidden.
A more powerful edit control : HiEdit is a free, multitabbed, large-file edit control consuming very little memory. It can edit both text and binary files. For details and a demonstration, see autohotkey/forum/topic19141.html.
Description: A pair of arrow buttons that the user can click to increase or decrease a value. By default, an UpDown control automatically snaps onto the previously added control. This previous control is known as the UpDown's buddy control . The most common example is a "spinner", which is an UpDown attached to an Edit control. Por exemplo:
In the example above, the Edit control is the UpDown's buddy control. Whenever the user presses one of the arrow buttons, the number in the Edit control is automatically increased or decreased.
An UpDown's buddy control can also be a Text control or ListBox. However, due to OS limitations, controls other than these (such as ComboBox and DropDownList) might not work properly with g-labels and other features.
Specify the UpDown's starting position as the last parameter (if omitted, it starts off at 0 or the number in the allowable range that is closest to 0).
When the Gui Submit command is used, the control's associated output variable (if any) receives the current numeric position of the UpDown. If the UpDown is attached to an Edit control and you do not wish to validate the user's input, it is best to use the UpDown's value rather than the Edit's. This is because the UpDown will always yield an in-range number, even when the user has typed something non-numeric or out-of-range in the Edit control. On a related note, numbers with more than three digits get a thousands separator (such as comma) by default. These separators are stored in the Edit's output variable but not that of the UpDown.
If the UpDown has a g-label, it will be launched whenever the user clicks one of the arrow buttons or presses an arrow key on the keyboard. Each launch of the g-label also stores the UpDown's position in its associated output variable (if any).
UpDown Options.
Horz : Make's the control's buttons point left/right rather than up/down. By default, Horz also makes the control isolated (no buddy). This can be overridden by specifying Horz 16 in the control's options.
Left : Puts the UpDown on the left side of its buddy rather than the right.
Range : Sets the range to be something other than 0 to 100. After the word Range, specify the minimum, a dash, and maximum. For example, Range1-1000 would allow a number between 1 and 1000 to be selected; Range-50-50 would allow a number between -50 and 50; and Range-10--5 would allow a number between -10 and -5. The minimum and maximum may be swapped to cause the arrows to move in the opposite of their normal direction. The broadest allowable range is -2147483648-2147483647. Finally, if the buddy control is a ListBox, the range defaults to 32767-0 for verticals and the inverse for horizontals (Horz).
Wrap : Causes the control to wrap around to the other end of its range when the user attempts to go beyond the minimum or maximum. Without Wrap , the control stops when the minimum or maximum is reached.
-16 (minus 16): Causes a vertical UpDown to be isolated; that is, it will have no buddy. This also causes the control to obey any specified width, height, and position rather than conforming to the size of its buddy control. In addition, an isolated UpDown tracks its own position internally. This position can be retrieved normally by means such as Gui Submit.
0x80 : Include 0x80 in Options to omit the thousands separator that is normally present between every three decimal digits in the buddy control. However, this style is normally not used because the separators are omitted from the number whenever the script retrieves it from the UpDown control itself (rather than its buddy control).
Increments other than 1 : In this script, NumEric demonstrates how to change an UpDown's increment to a value other than 1 (such as 5 or 0.1).
Picture (or Pic)
Description: An area containing an image (see last two paragraphs for supported file types). The last parameter is the filename of the image, which is assumed to be in A_WorkingDir if an absolute path isn't specified. Exemplo:
To retain the image's actual width and/or height, omit the W and/or H options. Otherwise, the image is scaled to the specified width and/or height (this width and height also determines which icon to load from a multi-icon. ICO file). To shrink or enlarge the image while preserving its aspect ratio, specify -1 for one of the dimensions and a positive number for the other. For example, specifying w200 h-1 would make the image 200 pixels wide and cause its height to be set automatically. If the picture cannot be loaded or displayed (e. g. file not found), the control is left empty and its width and height are set to zero.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user clicks the picture. A double-click can be detected by checking whether A_GuiEvent contains the word DoubleClick.
To use a picture as a background for other controls, the picture should normally be added prior to those controls. However, if those controls are input-capable and the picture has a g-label, create the picture after the other controls and include 0x4000000 (which is WS_CLIPSIBLINGS) in the picture's Options . This trick also allows a picture to be the background behind a Tab control or ListView.
Icons, cursors, and animated cursors : Icons and cursors may be loaded from the following types of files: ICO, CUR, ANI, EXE, DLL, CPL, SCR, and other types that contain icon resources. To use an icon group other than the first one in the file, include in Options the word Icon followed by the number of the group. In the following example, the default icon from the second icon group would be used: Gui, Add, Picture, Icon2, C:\My Application. exe .
Specifying the word AltSubmit in Options tells the program to use Microsoft's GDIPlus. dll to load the image, which might result in a different appearance for GIF, BMP, and icon images. For example, it would load an ICO/GIF that has a transparent background as a transparent bitmap, which allows the BackgroundTrans option to take effect (but in [v1.1.23+] , icons support transparency without AltSubmit). If GDIPlus is not available (see next paragraph), AltSubmit is ignored and the image is loaded using the normal method.
All operating systems support GIF, JPG, BMP, ICO, CUR, and ANI images. On Windows XP or later, additional image formats such as PNG, TIF, Exif, WMF, and EMF are supported. Operating systems older than XP can be given support by copying Microsoft's free GDI+ DLL into the AutoHotkey. exe folder (but in the case of a compiled script, copy the DLL into the script's folder). To download the DLL, search for the following phrase at microsoft: gdi redistributable.
Animated GIFs : Although animated GIF files can be displayed in a picture control, they will not actually be animated. To solve this, use the AniGIF DLL (which is free for non-commercial use) as demonstrated at autohotkey/forum/topic19264.html.
[v1.1.23+]: A bitmap or icon handle can be used instead of a filename. For example, HBITMAP:%handle% .
Description: A pushbutton, which can be pressed to trigger an action. In this case, the last parameter is the name of the button (shown on the button itself), which may include linefeeds (`n) to start new lines. Exemplo:
The example above includes the word Default in its Options to make "OK" the default button. The default button's action is automatically triggered whenever the user presses ENTER, except when the keyboard focus is on a different button or a multi-line edit control having the WantReturn style. To later change the default button to another button, follow this example, which makes the Cancel button become the default: GuiControl, +Default, Cancel . To later change the window to have no default button, follow this example: GuiControl, - default, OK .
An ampersand (&) may be used in the name button to underline one of its letters. Por exemplo:
In the example above, the letter P will be underlined, which allows the user to press Alt+P as shortcut key. To display a literal ampersand, specify two consecutive ampersands (&&).
If a button lacks an explicit g-label, an automatic label is assumed. For example, if the first GUI window contains an OK button, the ButtonOK label (if it exists) will be launched when the button is pressed. For GUI windows other than the first, the window number is included in front of the button's automatic label; for example: 2ButtonOK .
If the text on the button contains spaces or any of the characters in the set &`r`n`t` , its automatic label omits those characters. For example, a button titled "&Pause" would have an automatic label of ButtonPause. Similarly, a button titled "Save && Exit" would have an automatic label of ButtonSaveExit (the double-ampersand is used to display a single, literal ampersand).
Known limitation: Certain desktop themes might not display a button's text properly. If this occurs, try including - Wrap (minus Wrap) in the button's options. However, this also prevents having more than one line of text.
Description: A small box that can be checked or unchecked to represent On/Off, Yes/No, etc. Example:
The last parameter is a label displayed next to the box, which is typically used as a prompt or description of what the checkbox does. It may include linefeeds (`n) to start new lines. If a width (W) is specified in Options but no rows (R) or height (H), the control's text will be word-wrapped as needed, and the control's height will be set automatically. The checkbox's associated output variable (if any) receives the number 1 for checked, 0 for unchecked, and -1 for gray/indeterminate.
Specify the word Check3 in Options to enable a third state that displays a gray checkmark instead of a black one (the gray state indicates that the checkbox is neither checked nor unchecked). Specify the word Checked or CheckedGray in Options to have the checkbox start off with a black or gray checkmark, respectively. The word Checked may optionally be followed immediately by a 0, 1, or -1 to indicate the starting state. In other words, Checked and Checked%VarContainingOne% are the same.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user clicks or changes the checkbox.
Known limitation: Certain desktop themes might not display a button's text properly. If this occurs, try including - Wrap (minus Wrap) in the button's options. However, this also prevents having more than one line of text.
A Radio button is a small empty circle that can be checked (on) or unchecked (off). Exemplo:
These controls usually appear in radio groups , each of which contains two or more radio buttons. When the user clicks a radio button to turn it on, any others in its radio group are turned off automatically (the user may also navigate inside a group with the arrow keys). A radio group is created automatically around all consecutively added radio buttons. To start a new group, specify the word Group in the Options of the first button of the new group -- or simply add a non-radio control in between, since that automatically starts a new group.
For the last parameter, specify the label to display to the right of the radio button. This label is typically used as a prompt or description, and it may include linefeeds (`n) to start new lines. If a width (W) is specified in Options but no rows (R) or height (H), the control's text will be word-wrapped as needed, and the control's height will be set automatically.
Specify the word Checked in Options to have the button start off in the "on" Estado. The word Checked may optionally be followed immediately by a 0 or 1 to indicate the starting state: 0 for unchecked and 1 for checked. In other words, Checked and Checked%VarContainingOne% are the same.
The radio button's associated output variable (if any) receives the number 1 for "on" and 0 for "off". However, if only one button in a radio group has a variable, that variable will instead receive the number of the currently selected button: 1 is the first radio button (according to original creation order), 2 is the second, and so on. If there is no button selected, 0 is stored.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user turns on the button. Unlike the single-variable mode in the previous paragraph, the g-label must be specified for each button in a radio group for which the label should be launched. This allows the flexibility to ignore the clicks of certain buttons. Finally, a double-click can be detected by checking whether A_GuiEvent contains the word DoubleClick.
Known limitation: Certain desktop themes might not display a button's text properly. If this occurs, try including - Wrap (minus Wrap) in the button's options. However, this also prevents having more than one line of text.
DropDownList (or DDL)
Description: A list of choices that is displayed in response to pressing a small button. In this case, the last parameter is a pipe-delimited list of choices such as Choice1|Choice2|Choice3 . Exemplo:
To have one of the items pre-selected when the window first appears, include two pipe characters after it (e. g. Red|Green||Blue ). Alternatively, include in Options the word Choose followed immediately by the number to pre-select. For example, Choose5 would pre-select the fifth item (as with other options, it can also be a variable such as Choose%Var% ). To change the choice or add/remove entries from the list after the control has been created, use GuiControl.
Specify either the word Uppercase or Lowercase in Options to automatically convert all items in the list to uppercase or lowercase. Specify the word Sort to automatically sort the contents of the list alphabetically (this also affects any items added later via GuiControl). The Sort option also enables incremental searching whenever the list is dropped down; this allows an item to be selected by typing the first few characters of its name.
When the Gui Submit command is used, the control's associated output variable (if any) receives the text of the currently selected item. However, if the control has the AltSubmit property, the output variable will receive the item's position number instead (the first item is 1, the second is 2, etc.).
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user selects a new item.
Use the R or H option to control the height of the popup list. For example, specifying R5 would make the list 5 rows tall, while H400 would set the total height of the selection field and list to 400 pixels. If both R and H are omitted, the list will automatically expand to take advantage of the available height of the user's desktop (however, operating systems older than Windows XP will show 3 rows by default).
To set the height of the selection field or list items, use the CB_SETITEMHEIGHT message as in the example below:
The separator between fields may be changed to something other than pipe (|). For example Gui +Delimiter`n would change it to linefeed and Gui +DelimiterTab would change it to tab (`t).
Description: Same as DropDownList but also permits free-form text to be entered as an alternative to picking an item from the list. Exemplo:
In addition to allowing all the same options as DropDownList above, the word Limit may be included in Options to restrict the user's input to the visible width of the ComboBox's edit field. Also, the word Simple may be specified to make the ComboBox behave as though it is an Edit field with a ListBox beneath it.
When the Gui Submit command is used, the control's associated output variable (if any) receives the text of the currently selected item. However, if the control has the AltSubmit property, the output variable will receive the item's position number instead (the first item is 1, the second is 2, etc.). If either case, if there is no selected item, the output variable will be set to the contents of the ComboBox's edit field.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user selects a new item.
Description: A relatively tall box containing a list of choices that can be selected. In this case, the last parameter is a pipe-delimited list of choices such as Choice1|Choice2|Choice3 . Exemplo:
To have list item(s) pre-selected when the window first appears, include two pipe characters after each (the Multi option is required if more than one item is to be pre-selected). Alternatively, include in Options the word Choose followed immediately by a single item number to pre-select. For example, Choose5 would pre-select the fifth item. To change the choice or add/remove entries from the list after the control has been created, use GuiControl.
When the Gui Submit command is used, the control's associated output variable (if any) receives the text of the currently selected item. However, if the control has the AltSubmit property, the output variable instead receives the item's position number (the first item is 1, the second is 2, etc.).
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user selects a new item. If the user double-clicks an item, the built-in variable A_GuiEvent will contain the string DoubleClick rather than Normal. Also, the variable A_EventInfo will contain the position of the item that was double-clicked (1 is the first item, 2 is the second, etc.).
When adding a large number of items to a ListBox, performance may be improved by using GuiControl, - Redraw, MyListBox prior to the operation, and GuiControl, +Redraw, MyListBox afterward.
ListBox Options.
Multi : Allows more than one item to be selected simultaneously via shift-click and control-click (to avoid the need for shift/control-click, specify the number 8 instead of the word Multi). In this case, Gui Submit stores a pipe delimited list of item-strings in the control's output variable. However, if the AltSubmit option is in effect, Gui Submit stores a pipe-delimited list of item numbers instead. For example, 1|2|3 would indicate that the first three items are selected. To extract the individual items from the string, use a parsing loop such as this example:
The separator between fields may be changed to something other than pipe (|). For example Gui +Delimiter`n would change it to linefeed and Gui +DelimiterTab would change it to tab (`t).
ReadOnly : Prevents items from being visibly highlighted when they are selected (but Gui Submit will still store the selected item).
Sort : Automatically sorts the contents of the list alphabetically (this also affects any items added later via GuiControl). The Sort option also enables incremental searching, which allows an item to be selected by typing the first few characters of its name.
Tn : The letter T may be used to set tab stops, which can be used to format the text into columns. If the letter T is not used, tab stops are set at every 32 dialog units (the width of each "dialog unit" is determined by the operating system). If the letter T is used only once, tab stops are set at every n units across the entire width of the control. For example, Gui, Add, ListBox, vMyListBox t64 would double the default distance between tab stops. To have custom tab stops, specify the letter T multiple times as in the following example: Gui, Add, ListBox, vMyListBox t8 t16 t32 t64 t128 . One tab stop is set for each of the absolute column positions in the list, up to a maximum of 50 tab stops.
0x100 : Include 0x100 in options to turn on the LBS_NOINTEGRALHEIGHT style. This forces the ListBox to be exactly the height specified rather than a height that prevents a partial row from appearing at the bottom. This option also prevents the ListBox from shrinking when its font is changed.
To specify the number of rows of text (or the height and width), see position and sizing of controls.
ListView and TreeView.
Link [v1.1.06+]
Description: A text control that can contain links that can be clicked. Link controls use HTML-like markup language, but they only support the <A> tag. Inside the opening tag, an attribute of the form href="value" or id="value" may be specified. Por exemplo:
If the HREF attribute is set and contains a valid executable command or URL, it is executed as if passed to the Run command. However, an executable command cannot contain double-quote marks. A URL can usually contain percent-encoded characters such as `%22 , but these are interpreted by the user's web browser, not the Link control.
If the control has a g-label such as g MySubroutine , the subroutine is launched whenever a link without a HREF attribute is clicked, or if the command or URL failed to execute. This subroutine may consult the following variables:
A_GuiEvent contains the type of event; currently always the word "Normal". A_EventInfo contains the 1-based index of the link. ErrorLevel contains the value of the link's HREF attribute, if any; otherwise, the value of the link's ID attribute or an empty string.
If the g-label is a function, it can accept the following parameters:
Description: A box that looks like a single-line edit control but instead accepts a keyboard combination pressed by the user. For example, if the user presses Control+Alt+C on an English keyboard layout, the box would display "Ctrl + Alt + C".
When the Gui Submit command is used, the control's associated output variable (if any) receives the hotkey modifiers and name, which are compatible with the Hotkey command. Examples: ^!C , +!Home , +^Down , ^Numpad1 ,!NumpadEnd . If there is no hotkey in the control, the output variable is made blank.
Note : Some keys are displayed the same even though they are retrieved as different names. For example, both ^Numpad7 and ^NumpadHome might be displayed as Ctrl + Num 7.
By default, the control starts off with no hotkey specified. To instead have a default, specify its modifiers and name as the last parameter as in this example: Gui, Add, Hotkey, vChosenHotkey, ^!p.
The only modifiers supported are ^ (Control), ! (Alt), and + (Shift). See the key list for available key names.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user changes the hotkey. Each launch of the g-label also stores the hotkey in control's associated output variable (if any).
Note : The g-label is launched even when an incomplete hotkey is present. For example, if the user holds down the Control key, the g-label is launched once and the output variable contains only a circumflex (^). When the user completes the hotkey, the label is launched again and the variable contains the complete hotkey.
To restrict the types of hotkeys the user may enter, include the word Limit followed by the sum of one or more of the following numbers:
1: Prevent unmodified keys.
2: Prevent Shift-only keys.
4: Prevent Control-only keys.
8: Prevent Alt-only keys.
16: Prevent Shift-Control keys.
32: Prevent Shift-Alt keys.
64: This value is not supported (it will not behave correctly).
128: Prevent Shift-Control-Alt keys.
For example, Limit1 would prevent unmodified hotkeys such as letters and numbers from being entered, and Limit15 would require at least two modifier keys. If the user types a forbidden modifier combination, the Control+Alt combination is automatically and visibly substituted.
The Hotkey control has limited capabilities. For example, it does not support mouse/joystick hotkeys or the Windows key (LWin and RWin). One way to work around this is to provide one or more checkboxes as a means for the user to enable extra modifiers such as the Windows key.
Description: A box that looks like a single-line edit control but instead accepts a date and/or time. A drop-down calendar is also provided. Exemplo:
The last parameter may be one of the following:
(omitted) : When omitted, the locale's short date format is used. For example, in some locales it would look like: 6/1/2005.
LongDate : Uses the locale's long date format. For example, in some locales it would look like: Wednesday, June 01, 2005.
Time : Shows only the time using the locale's time format. Although the date is not shown, it is still present in the control and will be retrieved along with the time in the YYYYMMDDHH24MISS format.
(custom format) : Specify any combination of date and time formats. For example, M/d/yy HH:mm would look like 6/1/05 21:37. Similarly, dddd MMMM d, yyyy hh:mm:ss tt would look like Wednesday June 1, 2005 09:37:45 PM. Letters and numbers to be displayed literally should be enclosed in single quotes as in this example: 'Date:' MM/dd/yy 'Time:' hh:mm:ss tt . By contrast, non-alphanumeric characters such as spaces, tabs, slashes, colons, commas, and other punctuation do not need to be enclosed in single quotes. The exception to this is the single quote character itself: to produce it literally, use four consecutive single quotes (''''), or just two if the quote is already inside an outer pair of quotes.
DateTime Usage.
To have a date other than today pre-selected, include in Options the word Choose followed immediately by a date in YYYYMMDD format. For example, Choose20050531 would pre-select May 31, 2005 (as with other options, it can also be a variable such as Choose%Var% ). To have no date/time selected, specify ChooseNone . ChooseNone also creates a checkbox inside the control that is unchecked whenever the control has no date. Whenever the control has no date, Gui Submit and GuiControlGet will retrieve a blank value (empty string).
The time of day may optionally be present. However, it must always be preceded by a date when going into or coming out of the control. The format of the time portion is HH24MISS (hours, minutes, seconds), where HH24 is expressed in 24-hour format; for example, 09 is 9am and 21 is 9pm. Thus, a complete date-time string would have the format YYYYMMDDHH24MISS.
When specifying dates in the YYYYMMDDHH24MISS format, only the leading part needs to be present. Any remaining element that has been omitted will be supplied with the following default values:
Within the drop-down calendar, the today-string at the bottom can be clicked to select today's date. In addition, the year and month name are clickable and allow easy navigation to a new month or year.
Keyboard navigation: Use the Up/Down arrow keys, NumpadPlus/Minus, and Home/End to increase or decrease the control's values. Use LeftArrow and RightArrow to move from field to field inside the control. Within the drop-down calendar, use the arrow keys to move from day to day; use PageUp/Down to move backward/forward by one month; use Ctrl-PageUp/Down to move backward/forward by one year; and use Home/End to select the first/last day of the month.
When the Gui Submit command is used, the control's associated output variable (if any) receives the selected date and time in YYYYMMDDHH24MISS format. Both the date and the time are present regardless of whether they were actually visible in the control.
If the control has a g-label, the label is launched whenever the user changes the date or time. For each launch, the control's associated output variable (if any) is automatically updated with the currently selected date/time.
DateTime Options.
Range : Restricts how far back or forward in time the selected date can be. After the word Range, specify the minimum and maximum dates in YYYYMMDD format (with a dash between them). For example, Range20050101-20050615 would restrict the date to the first 5.5 months of 2005. Either the minimum or maximum may be omitted to leave the control unrestricted in that direction. For example, Range20010101 would prevent a date prior to 2001 from being selected and Range-20091231 (leading dash) would prevent a date later than 2009 from being selected. Without the Range option, any date between the years 1601 and 9999 can be selected. The time of day cannot be restricted.
Right : Causes the drop-down calendar to drop down on the right side of the control instead of the left.
1 : Specify the number 1 in Options to provide an up-down control to the right of the control to modify date-time values, which replaces the button of the drop-down month calendar that would otherwise be available. This does not work in conjunction with the format option LongDate described above.
2 : Specify the number 2 in Options to provide a checkbox inside the control that the user may uncheck to indicate that no date/time is selected. Once the control is created, this option cannot be changed.
Description: A tall and wide control that displays all the days of the month in calendar format. The user may select a single date or a range of dates. Exemplo:
To have a date other than today pre-selected, specify it as the last parameter in YYYYMMDD format (e. g. 20050531 ). A range of dates may also be pre-selected by including a dash between two dates (e. g. 20050525-20050531 ).
It is usually best to omit width (W) and height (H) for a MonthCal because it automatically sizes itself to fit exactly one month. To display more than one month vertically, specify R2 or higher in Options . To display more than one month horizontally, specify W-2 (W negative two) or higher. These options may both be present to expand in both directions.
The today-string at the bottom of the control can be clicked to select today's date. In addition, the year and month name are clickable and allow easy selection of a new year or month.
Unlike DateTime's drop-down calendar, keyboard navigation is generally not supported in a MonthCal.
When the Gui Submit command is used, the control's associated output variable (if any) receives the selected date in YYYYMMDD format (without any time portion). However, when the multi-select option is in effect, the minimum and maximum dates are retrieved with a dash between them (e. g. 20050101-20050108 ). If only a single date was selected in a multi-select calendar, the minimum and maximum are both present but identical. StringSplit can be used to separate the dates. For example, the following would put the minimum in Date1 and the maximum in Date2: StringSplit, Date, MyMonthCal, - .
If the MonthCal has a g-label, each launch of it updates the control's associated output variable (if any) with the currently selected date or range. By default, the label is launched only when: 1) the user changes the selection; or 2) every two minutes in case a new day has arrived (this behavior is a quirk of the OS). However, if the word AltSubmit is in the control's Options , the g-label is launched more often and the built-in variable A_GuiEvent will contain the word Normal for a change of the date, the number 1 for a click of a date, and the number 2 when the MonthCal releases "mouse capture". For example, if the user double-clicks a new date, the label would be launched five times: Once with Normal, twice with 1, and twice with 2. This can be used to detect double clicks by measuring the time between instances of the number 1.
When specifying dates in the YYYYMMDD format, the MM and/or DD portions may be omitted, in which case they are assumed to be 1. For example, 200205 is seen as 20020501, and 2005 is seen as 20050101.
MonthCal Options.
Multi : Multi-select. Allows the user to shift-click or click-drag to select a range of adjacent dates (the user may still select a single date too). This option may be specified explicitly or put into effect automatically by means of specifying a selection range when the control is created. For example: Gui, Add, MonthCal, vMyCal, 20050101-20050108 . Once the control is created, this option cannot be changed.
Range : Restricts how far back or forward in time the calendar can go. After the word Range, specify the minimum and maximum dates in YYYYMMDD format (with a dash between them). For example, Range20050101-20050615 would restrict the selection to the first 5.5 months of 2005. Either the minimum or maximum may be omitted to leave the calendar unrestricted in that direction. For example, Range20010101 would prevent a date prior to 2001 from being selected and Range-20091231 (leading dash) would prevent a date later than 2009 from being selected. Without the Range option, any date between the years 1601 and 9999 can be selected.
4 : Specify the number 4 in Options to display week numbers (1-52) to the left of each row of days. Week 1 is defined as the first week that contains at least four days.
8 : Specify the number 8 in Options to prevent the circling of today's date within the control.
16 : Specify the number 16 in Options to prevent the display of today's date at the bottom of the control.
Description: A sliding bar that the user can move along a vertical or horizontal track. The standard volume control in the taskbar's tray is an example of a slider. Exemplo:
Specify the starting position of the slider as the last parameter. If the last parameter is omitted, the slider starts off at 0 or the number in the allowable range that is closest to 0.
The user may slide the control by the following means: 1) dragging the bar with the mouse; 2) clicking inside the bar's track area with the mouse; 3) turning the mouse wheel while the control has focus; or 4) pressing the following keys while the control has focus: Arrow keys, Page-up, Page-down, Home, and End.
When the Gui Submit command is used, the control's associated output variable (if any) receives the current numeric position of the slider. The position is also stored in the output variable whenever the control's g-label is launched.
If the slider has a g-label, by default it will be launched only when the user has stopped moving the slider (such as by releasing the mouse button after having dragging it). However, if the word AltSubmit is in the control's Options , the g-label is launched for all slider events and the built-in variable A_GuiEvent will contain one of the following digits or strings:
0: The user pressed the Left-arrow or Up-arrow key.
1: The user pressed the Right-arrow or Down-arrow key.
2: The user pressed the Page-up key.
3: The user pressed the Page-down key.
4: The user moved the slider via the mouse wheel, or finished a drag-and-drop to a new position.
5: The user is currently dragging the slider via the mouse; that is, the mouse button is currently down.
6: The user pressed the Home key to send the slider to the left or top side.
7: The user pressed the End key to send the slider to the right or bottom side.
Normal: The user has finished moving the slider, either via the mouse or the keyboard.
Note : With the exception of mouse wheel movement (#4), the g-label is launched again for the "normal" event even though it was already launched for one of the digit-events above.
Slider Options.
Buddy1 and Buddy2 : Specifies up to two existing controls to automatically reposition at the ends of the slider. Buddy1 is displayed at the left or top side (depending on whether the Vertical option is present). Buddy2 is displayed at the right or bottom side. After the word Buddy1 or Buddy2, specify the variable name of an existing control. For example, Buddy1MyTopText would assign the control whose variable name is MyTopText.
Center : The thumb (the bar moved by the user) will be blunt on both ends rather than pointed at one end.
Invert : Reverses the control so that the lower value is considered to be on the right/bottom rather than the left/top. This is typically used to make a vertical slider move in the direction of a traditional volume control. Note: The ToolTip option described below will not obey the inversion and therefore should not be used in this case.
Left : The thumb (the bar moved by the user) will point to the top rather than the bottom. But if the Vertical option is in effect, the thumb will point to the left rather than the right.
Line : Specifies the number of positions to move when the user presses one of the arrow keys. After the word Line, specify number of positions to move. For example: Line2 .
NoTicks : Omits tickmarks alongside the track.
Page : Specifies the number of positions to move when the user presses the Page-up or Page-down key. After the word Page, specify number of positions to move. For example: Page10 .
Range : Sets the range to be something other than 0 to 100. After the word Range, specify the minimum, a dash, and maximum. For example, Range1-1000 would allow a number between 1 and 1000 to be selected; Range-50-50 would allow a number between -50 and 50; and Range-10--5 would allow a number between -10 and -5.
Thick : Specifies the length of the thumb (the bar moved by the user). After the word Thick, specify the thickness in pixels (e. g. Thick30 ). To go beyond a certain thickness on Windows XP or later, it is probably necessary to either specify the Center option or remove the theme from the control (which can be done by specifying - Theme in the control's options).
TickInterval : Provides tickmarks alongside the track at the specified interval. After the word TickInterval, specify the interval at which to display additional tickmarks (if the interval is omitted, it is assumed to be 1). For example, TickInterval10 would display a tickmark once every 10 positions.
ToolTip : Creates a tooltip that reports the numeric position of the slider as the user is dragging it. To have the tooltip appear in a non-default position, specify one of the following instead: ToolTipLeft or ToolTipRight (for vertical sliders); ToolTipTop or ToolTipBottom (for horizontal sliders).
Vertical : Makes the control slide up and down rather than left and right.
The above options can be changed after the control is created via GuiControl.
Description: A dual-color bar typically used to indicate how much progress has been made toward the completion of an operation. Exemplo:
Specify the starting position of the bar as the last parameter (if omitted, the bar starts off at 0 or the number in the allowable range that is closest to 0). To later change the position of the bar, follow these examples, all of which operate upon a progress bar whose associated variable name is MyProgress:
For horizontal Progress Bars, the thickness of the bar is equal to the control's height. For vertical Progress Bars it is equal to the control's width.
Progress Options.
Cn : Changes the bar's color. Specify for n one of the 16 primary HTML color names or a 6-digit RGB color value. Examples: cRed , cFFFF33 , cDefault . If the C option is never used (or cDefault is specified), the system's default bar color will be used.
BackgroundN : Changes the bar's background color. Specify for n one of the 16 primary HTML color names or a 6-digit RGB color value. Examples: BackgroundGreen , BackgroundFFFF33 , BackgroundDefault . If the Background option is never used (or BackgroundDefault is specified), the background color will be that of the window or tab control behind it.
Range : Sets the range to be something other than 0 to 100. After the word Range, specify the minimum, a dash, and maximum. For example, Range0-1000 would allow a numbers between 0 and 1000; Range-50-50 would allow numbers between -50 and 50; and Range-10--5 would allow numbers between -10 and -5.
-Smooth (minus Smooth): Displays a length of segments rather than a smooth continuous bar. Specifying - Smooth is also one of the requirements to show a themed progress bar on Windows XP or later. The other requirement is that the bar not have any custom colors; that is, that the C and Background options be omitted.
Vertical : Makes the bar rise or fall vertically rather than move along horizontally.
The above options can be changed after the control is created via GuiControl.
Description: A rectangular border/frame, often used around other controls to indicate they are related. In this case, the last parameter is the title of the box, which if present is displayed at its upper-left edge. Exemplo:
By default, a GroupBox's title may have only one line of text. This can be overridden by specifying Wrap in Options.
To specify the number of rows inside the control (or its height and width), see position and sizing of controls.
Description: A large control containing multiple pages, each of which contains other controls. From this point forward, these pages are referred to as "tabs".
There are three types of Tab control:
Tab3 [v1.1.23.00+] : Fixes some issues which affect Tab2 and Tab. Controls are placed within an invisible "tab dialog" which moves and resizes with the tab control. The tab control is themed by default. Tab2 [v1.0.47.05+] : Fixes rare redrawing problems in the original "Tab" control but introduces some other problems. Tab : Retained for backward compatibility because of differences in behavior between Tab2/Tab3 and Tab.
The last parameter above is a pipe-delimited list of tab names. To have one of the tabs pre-selected when the window first appears, include two pipe characters after it (e. g. Red|Green||Blue ). Alternatively, include in Options the word Choose followed immediately by the number to pre-select. For example, Choose5 would pre-select the fifth tab (as with other options, it can also be a variable such as Choose%Var% ). To change the selected tab, add tabs, or remove tabs after the control has been created, use GuiControl.
After creating a Tab control, subsequently added controls automatically belong to its first tab. This can be changed at any time by following these examples:
It is also possible to use any of the examples above to assign controls to a tab or tab-control that does not yet exist (except in the case of the Name method). But in that case, the relative positioning options described below are not supported.
Positioning : When each tab of a Tab control receives its first sub-control, that sub-control will have a special default position under the following conditions: 1) The X and Y coordinates are both omitted, in which case the first sub-control is positioned at the upper-left corner of the tab control's interior (with a standard margin), and sub-controls beyond the first are positioned beneath the previous control; 2) The X+n and/or Y+n positioning options are specified, in which case the sub-control is positioned relative to the upper-left corner of the tab control's interior. For example, specifying x+10 y+10 would position the control 10 pixels right and 10 pixels down from the upper left corner.
V : When the Gui Submit command is used, the control's associated output variable (if any) receives the name of the currently selected tab. However, if the control has the AltSubmit property, the output variable will receive the tab's position number instead (the first tab is 1, the second is 2, etc.).
G : A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user changes to a new tab. If the tab control has both a g-label and an output variable, whenever the user switches to a new tab, the output variable will be set to the previously selected tab name (or number in the case of AltSubmit).
Keyboard navigation : The user may press Control-PageDown/PageUp to navigate from page to page in a tab control; if the keyboard focus is on a control that does not belong to a Tab control, the window's first Tab control will be navigated. Control-Tab and Control-Shift-Tab may also be used except that they will not work if the currently focused control is a multi-line Edit control.
Limits : Each window may have no more than 255 tab controls. Each tab control may have no more than 256 tabs (pages). In addition, a tab control may not contain other tab controls.
Tab3 vs. Tab2 vs. Tab.
Parent window : The parent window of a control affects the positioning and visibility of the control and tab-key navigation order. If a sub-control is added to an existing Tab3 control, its parent window is the "tab dialog", which fills the tab control's display area. Most other controls, including sub-controls of Tab or Tab2 controls, have no parent other than the GUI window itself.
Positioning : For Tab and Tab2, sub-controls do not necessarily need to exist within their tab control's boundaries: they will still be hidden and shown whenever their tab is selected or de-selected. This behavior is especially appropriate for the "buttons" style described below.
For Tab3, sub-controls assigned to a tab before the tab control is created behave as though added to a Tab or Tab2 control. All other sub-controls are visible only within the display area of the tab control.
If a Tab3 control is moved, its sub-controls are moved with it. Tab and Tab2 controls do not have this behavior.
In the rare case that WinMove (or an equivalent DllCall) is used to move a control, the coordinates must be relative to the parent window of the control, which might not be the GUI (see above). By contrast, GuiControl Move takes GUI coordinates and ControlMove takes window coordinates, regardless of the control's parent window.
Autosizing : If not specified by the script, the width and/or height of the Tab3 control are automatically calculated at one of the following times (whichever comes first after the control is created):
The first time the Tab3 control ceases to be the current tab control. This can occur as a result of calling Gui, Tab (with or without parameters) or creating another tab control. The first time Gui, Show is called for that particular Gui.
The calculated size accounts for sub-controls which exist when autosizing occurs, plus the default margins. The size is calculated only once, and will not be recalculated even if controls are added later. If the Tab3 control is empty, it receives the same default size as a Tab or Tab2 control.
Tab and Tab2 controls are not autosized; they receive an arbitrary default size.
Tab-key navigation order : The tab-key navigation order usually depends on the order in which the controls are created. When tab controls are used, the order also depends on the type of tab control:
Tab and Tab2 allow their sub-controls to be mixed with other controls within the tab-key order. Tab2 puts its tab buttons after its sub-controls in the tab-key order. Tab3 groups its sub-controls within the tab-key order and puts them after its tab buttons.
Notification messages (Tab3) : Common and Custom controls typically send notification messages to their parent window. Any WM_COMMAND, WM_NOTIFY, WM_VSCROLL, WM_HSCROLL or WM_CTLCOLOR' messages received by a Tab3 control's tab dialog are forwarded to the GUI window and can be detected by using OnMessage. If the tab control is themed and the sub-control lacks the +BackgroundTrans option, WM_CTLCOLORSTATIC is fully handled by the tab dialog and not forwarded. Other notification messages (such as custom messages) are not supported.
BackgroundTrans has no effect inside a Tab2 control. WebBrowser controls do not redraw correctly. AnimateWindow and possibly other Win32 API calls can cause the tab's controls to disappear.
Activating a GUI window by clicking certain parts of its controls, such as scrollbars, might redraw improperly. BackgroundTrans has no effect if the Tab control contains a ListView. WebBrowser controls are invisible.
Tab Options.
-Background (minus followed by the word background): Overrides the window's custom background color and uses the system's default Tab control color. Specify +Theme - Background to make the Tab control conform to the current desktop theme. However, most control types will look strange inside such a Tab control because their backgrounds will not match that of the tab control. This can be fixed for some control types (such as Text) by adding BackgroundTrans to their options.
Buttons : Creates a series of buttons at the top of the control rather than a series of tabs (in this case, there will be no border by default because the display area does not typically contain controls).
Left/Right/Bottom : Specify one of these words to have the tabs on the left, right, or bottom side instead of the top. See TCS_VERTICAL for limitations on Left and Right.
-Wrap : Prevents the tabs from taking up more than a single row (in which case if there are too many tabs to fit, arrow buttons are displayed to allow the user to slide more tabs into view).
To specify the number of rows of text inside the control (or its height and width), see position and sizing of controls.
Icons in Tabs : An icon may be displayed next to each tab's name/text via SendMessage. This is demonstrated in the forum topic Icons in tabs.
StatusBar [v1.0.44+]
Description: A row of text and/or icons attached to the bottom of a window, which is typically used to report changing conditions. Exemplo:
The simplest use of a status bar is to call SB_SetText() whenever something changes that should be reported to the user. To report more than one piece of information, divide the bar into sections via SB_SetParts(). To display icon(s) in the bar, call SB_SetIcon().
All of the following StatusBar functions operate upon the current thread's default GUI window (which can be changed via Gui, 2:Default ). If the default window does not exist or has no status bar, all SB functions return 0 to indicate the problem.
SB_SetText(NewText [, PartNumber, Style])
Displays NewText in the specified part of the status bar. If PartNumber is omitted, it defaults to 1. Otherwise, specify an integer between 1 and 256. If Style is omitted, it defaults to 0, which uses a traditional border that makes that part of the bar look sunken. Otherwise, specify 1 to have no border or 2 to have border that makes that part of the bar look raised. Finally, up to two tab characters (`t) may be present anywhere in NewText : anything to the right of the first tab is centered within the part, and anything to the right of the second tab is right-justified. SB_SetText() returns 1 upon success and 0 upon failure.
SB_SetParts([Width1, Width2, . Width255])
Divides the bar into multiple sections according to the specified widths (in pixels). If all parameters are omitted, the bar is restored to having only a single, long part. Otherwise, specify the width of each part except the last (the last will fill the remaining width of the bar). For example, SB_SetParts(50, 50) would create three parts: the first two of width 50 and the last one of all the remaining width.
Note : Any parts "deleted" by SB_SetParts() will start off with no text the next time they are shown (furthermore, their icons are automatically destroyed).
Upon success, SB_SetParts() returns a non-zero value (the status bar's HWND). Upon failure it returns 0.
SB_SetIcon(Filename [, IconNumber, PartNumber])
Displays a small icon to the left of the text in the specified part (if PartNumber is omitted, it defaults to 1). Filename is the name of an icon (.ICO), cursor (.CUR), or animated cursor (.ANI) file (animated cursors will not actually be animated in the bar). Other sources of icons include the following types of files: EXE, DLL, CPL, SCR, and other types that contain icon resources. To use an icon group other than the first one in the file, specify its number for IconNumber . For example, SB_SetIcon("Shell32.dll", 2) would use the default icon from the second icon group. If IconNumber is negative, its absolute value is assumed to be the resource ID of an icon within an executable file. SB_SetIcon() returns the icon's HICON upon success and 0 upon failure. The HICON is a system resource that can be safely ignored by most scripts because it is destroyed automatically when the status bar's window is destroyed. Similarly, any old icon is destroyed when SB_SetIcon() replaces it with a new one. This can be avoided via:
[v1.1.23+]: An icon handle can be used instead of a filename. For example, SB_SetIcon("HICON:" handle) .
[v1.1.27+]: Non-icon image files and bitmap handles are supported for Filename . For example, SB_SetIcon("HBITMAP:" handle) .
SB_SetProgress()
Creates and controls a progress bar inside the status bar. This function is available at autohotkey/forum/topic37754.html.
G-Label Notifications.
A g-label such as g MySubroutine may be listed in the control's options. This would cause the MySubroutine label to be launched automatically whenever the user clicks on the bar. This subroutine may consult the built-in variables A_Gui and A_GuiControl. More importantly, it may consult A_GuiEvent , which contains one of the following strings (for compatibility with future versions, a script should not assume these are the only possible values):
Normal : The user left-clicked the bar. The variable A_EventInfo contains the part number (however, the part number might be a very large integer if the user clicks near the sizing grip at the right side of the bar). RightClick : The user right-clicked the bar. The variable A_EventInfo contains the part number. NOTE: GuiContextMenu will not be called for the status bar if it has a g-label. Also, the g-label's RightClick event should be used instead of GuiContextMenu when the script needs to know which part number the user clicked on (A_EventInfo). DoubleClick : The user double-clicked the bar. The variable A_EventInfo contains the part number. R : The user double-right - clicked the bar. The variable A_EventInfo contains the part number.
Font and Color.
Although the font size, face, and style can be set via Gui Font (just like normal controls), the text color cannot be changed. Also, Gui Color is not obeyed; instead, the status bar's background color may be changed by specifying in Options the word Background followed immediately by a color name (see color chart) or RGB value (the 0x prefix is optional). Examples: BackgroundSilver , BackgroundFFDD99 , BackgroundDefault .
Hiding the StatusBar.
Upon creation, the bar can be hidden via Gui, Add, StatusBar, Hidden vMyStatusBar . To hide it sometime after creation, use GuiControl, Hide, MyStatusBar . To show it, use GuiControl, Show, MyStatusBar .
Note : Hiding the bar does not reduce the height of the window. If that is desired, one easy way is Gui, Show, AutoSize .
Styles (rarely used)
Known Limitations.
1) Any control that overlaps the status bar might sometimes get drawn on top of it. One way to avoid this is to dynamically shrink such controls via the GuiSize label. 2) There is a limit of one status bar per window.
The bottom of the TreeView page demonstrates a multipart status bar.
ActiveX [v1.1.03+]
ActiveX components such as the MSIE browser control can be embedded into a GUI window by following this example:
When the control is created, an ActiveX object is stored in the control's associated variable, if it has one. GuiControlGet can also be used to retrieve the object.
To handle events exposed by the object, use ComObjConnect as demonstrated below:
ComObjType can be used to determine the type of object stored in the control's variable.
Custom [v1.1.10+]
Other controls which are not directly supported by AutoHotkey can be also embedded into a GUI window. In order to do so, the Win32 class name must be specified through the Class option in Gui, Add . Exemplos:
AutoHotkey uses the standard Windows control text routines when text is to be retrieved/replaced in the control via Gui, Add or GuiControl/Get .
G-Label Notifications : A g-label such as g MySubroutine may be listed in the control's options in order to capture events coming from the control. This subroutine may consult the built-in variables A_Gui and A_GuiControl. More importantly, it may consult A_GuiEvent , which contains one of the following strings (for compatibility with future versions, a script should not assume these are the only possible values):
Normal : A WM_COMMAND message was received. A_EventInfo contains a control-defined notification code (equivalent to HIWORD(wParam) in C/C++). N : A WM_NOTIFY message was received. A_EventInfo contains a pointer to the control notification structure ( NMHDR ). A 32-bit signed integer value may be returned to the control by assigning it to ErrorLevel (by default, the g-label thread's ErrorLevel is set to zero). Invalid values are treated as zero.
Here is an example that shows how to add and use an IP address control:

Nunca ouviu falar de estratégias de opções binárias? Não tenha medo, BOTS estão aqui!
O caminho para o Santo Graal ou como encontrar uma boa estratégia de negociação de opções binárias.
Falamos muito sobre as estratégias de Opções Binárias, boas ou más, livres ou não, golpes ou legítimas, mas o que exatamente é uma estratégia de negociação e como podemos diferenciar a porcaria do ouro? Como deve ser uma boa estratégia? O assim chamado "Santo Graal" realmente existe? Vou tentar esclarecer as coisas acima, então vamos devagar e começar do começo.
Primeiras coisas primeiro: o que é uma estratégia de opções binárias?
Para encurtar a história, uma estratégia é um conjunto de regras que você segue quando negocia opções binárias ou qualquer outro instrumento financeiro. Mas eu sei que você nem sempre gosta do conto, então vamos nos aprofundar um pouco mais: de acordo com a Wikipedia, “em finanças, uma estratégia de negociação é um plano fixo que é projetado para obter um retorno lucrativo indo longo ou curto nos mercados”.
O desenvolvimento de uma estratégia é composto por 8 etapas, que incluem formulação (definição das regras), tradução dessas regras em forma testável por computador, testes preliminares, otimização, avaliação de desempenho, negociação da estratégia, monitoramento do desempenho e, por fim, refinamento e evolução . É claro que nem todos nós somos capazes de seguir exatamente esses 8 passos (por exemplo, eu não tenho absolutamente nenhuma habilidade de codificação, então não posso colocar minhas estratégias em forma testável por computador), mas as principais etapas / partes devem estar lá. Quais são as principais partes? Bem, de acordo comigo, aqui estão elas: definindo regras claras para negociação (quando eu vou usar chamadas e quando coloca?), Definindo regras claras para a gestão do dinheiro (quanto eu vou arriscar em cada negociação? Quantas negociações posso abrir ao mesmo tempo?), testando a estratégia (backtesting, negociação de papel, negociação demo, forward testing), decidindo quando não negociar (encontre as situações em que sua estratégia executa o pior e evite negociar então).
Mais uma coisa que você deve saber sobre estratégias de negociação: elas são baseadas em análises técnicas e fundamentais (algumas estratégias combinam ambos os aspectos). As estratégias técnicas incluem padrões gráficos, padrões candlestick, indicadores, ação de preços, suporte e resistência, enquanto as estratégias fundamentais estão relacionadas a eventos macroeconômicos e geopolíticos como taxas de juros, dados de emprego, dados de inflação, coletivas de imprensa, discursos de chefes de bancos centrais, Agora que sabemos o que é uma estratégia de opções binárias, vamos ver como deve ser uma boa estratégia.
O que você deve procurar em uma estratégia de opções binárias?
Você já ouviu um cara dizendo algo como: "Ei, qual foi a sua estratégia?" E o outro cara respondeu "Eu fiz um Call on Oil". Existem caras para quem comprar um Call ou Put é uma estratégia. Embora isso não seja literalmente errado, eu não acho que uma estratégia de negociação é limitada a isso e eu nunca poderia olhar dessa maneira. Em vez disso, considero que a estratégia é a razão por trás da minha compra do Call ou Put e tem que conter condições pré-determinadas que precisam ser cumpridas para eu entrar em uma negociação. Deixe-me elaborar sobre isso com o uso do sempre útil, o Sr. Exemplo: Olhe para a figura abaixo para ver o que eu considero uma boa explicação de uma estratégia (clique aqui se você quiser ler todo o artigo da “Guru Fractal”)
Agora esta é uma estratégia real; Eu não estou dizendo que é o melhor, mas pelo menos é explicado completamente e não tem nenhum dos ingredientes de um golpe. Uma imagem vale mais que mil palavras, então a explicação de uma estratégia deve sempre conter pelo menos uma imagem de um sinal válido fornecido por essa estratégia. Além disso, acho que uma estratégia real e honesta deve ter regras claras e claras e não permitir que você adivinhe nada. Uma boa fonte de estratégias é o YouTube, mas… tenha muito cuidado se optar por usar uma estratégia encontrada porque muitos deles são apenas enviados por motivos promocionais, para fazer você investir usando um determinado corretor ou até mesmo comprar um determinado produto. Por fim, acho que uma estratégia sólida deve ter uma estrutura básica semelhante à seguinte:
Exemplo de estrutura da Estratégia de Negociação de Opções Binárias Básicas:
Regras de entrada: Por que devo comprar uma chamada ou uma opção de compra? As razões são praticamente infinitas e variam de estratégia para estratégia, mas eu vou dizer "Compre uma chamada se EMA 17 (médias móveis exponenciais) e EMA 43 cruzarem uma alta e comprar uma Put se elas cruzarem bearish". Este é um exemplo de uma regra de entrada clara e rigorosa, mas espero que você não negocie com base nisso, porque acabei de criar esse exemplo.
Regras de saída: quando devo sair de uma negociação se for contra mim? Qualquer boa estratégia deve dar-lhe a resposta para essa pergunta. Afinal de contas, não podemos entrar no mercado sem pensar no pior cenário possível quando o comércio vai mal. A maioria dos corretores possui ferramentas que permitem fechar um negócio antes do tempo de expiração e sua estratégia deve lhe dizer quando sair e receber de volta parte do valor investido nesse negócio.
Gestão do dinheiro: quanto devo investir em um único negócio e quantas negociações devo abrir ao mesmo tempo? Agora pense sobre isso: se sua conta inteira for $ 1000 e você investir em um único comércio $ 500 (isso significa 50%), apenas dois comércios perdidos acabariam com a conta inteira, mas se você usar uma porcentagem menor para cada negócio, mais chances de permanecer no jogo por mais tempo e sobreviver a uma série de negociações perdidas.
Minha visão sobre como uma estratégia de opções binárias de golpe se parece com & # 8211; Estratégias para Cuidado.
Existem armadilhas para novos comerciantes em todo o mundo e um dos mais perigosos é o esquema Brain Wash Strategy. Você provavelmente encontrou um, mas não sabia. Deixe-me dizer o que parece. Há um site longo onde você só pode rolar para baixo para ler algum lixo interminável e regurgitado sobre quanto dinheiro você pode ganhar praticamente da noite para o dia. Soa familiar? Aqui estão mais algumas dicas. Normalmente, a estratégia apresentada é inventada / criada por um operador muito “bem sucedido”. Um "supertrader" que provavelmente tem milhões de dólares, mas por alguma razão desconhecida quer compartilhar seu segredo comigo (talvez ele tenha um bom coração). Se eu me aventurar mais na página, provavelmente serei informado de que não preciso de nenhum conhecimento do mercado financeiro para ter sucesso com sua estratégia e, se eu ler nas entrelinhas, ele basicamente me diz que não há problema em ser retardado porque ainda fazer dinheiro.
Depois de aparentemente milhares de pergaminhos para baixo eu chego aos Testemunhos onde outras pessoas comuns como eu, me dizem quanto dinheiro eles fizeram ... sim, certo, e eu nasci ontem. Não se deixe enganar por isso, eles são pagos para lhe dizer isso. Finalmente, chego à parte suculenta onde o "Guru & # 8221; me faz uma oferta que não posso recusar. Normalmente, o preço da estratégia é de US $ 99, mas como sou um cara legal e sortudo, posso comprá-lo por apenas US $ 39,99. Mas espere, se eu "agir agora", posso obtê-lo pela mísera quantia de US $ 19,99. Sorte minha! Mas uma questão ainda me incomoda: por que um comerciante tão grande venderia sua estratégia de "impressão de dinheiro" por alguns dólares? Se a estratégia é tão boa, ele poderia apenas colocar alguns negócios e fazer enormes quantias de dinheiro & # 8211; muito mais do que ele faria vendendo-o. Oh espere, eu sei & # 8211; porque é uma farsa e não funciona! Quando alguém lhe disser que é fácil ganhar dinheiro durante a noite no mercado financeiro, basta pressionar o botão "X" no canto superior direito e seguir em frente. Não pague um centavo por qualquer estratégia que se pareça com a que descrevi acima.
Ok, vamos supor que você aceite meu conselho e não pague um centavo por uma estratégia que se parece com a que acabei de descrever. Isso é uma bala esquivada ... ótimo! Mas a "arma" do scammer tem mais de uma bala e deixe-me falar sobre outro truque: aqueles sites de uma página que parecem (e realmente são) cartas de vendas longas, fazem lavagem cerebral em você para depositar dinheiro com o corretor que anunciam. Os anúncios de um determinado corretor aparecem em toda a página, pedindo que você invista com “O melhor corretor de todos os tempos!” Isso é uma porcaria! E na maioria das vezes o corretor anunciado é uma farsa também. Os novatos são presas fáceis para os golpistas experientes e, mesmo que não consigam que os novatos comprem a estratégia, talvez pelo menos eles possam fazer com que depositem algum dinheiro com o corretor anunciado. Se o cara novo também compra a estratégia… bem, dois pelo preço de um… tempo para a festa do golpista, porque você sabe qual é o próximo passo quando o dinheiro é depositado? O buraco negro do reino scam absorve tudo ... e se você tentar se retirar, os problemas começam a aparecer. O dinheiro nunca chegará à sua conta bancária e se você confrontar o corretor sobre isso, você receberá apenas uma explicação estúpida como "Oh, nós sentimos muito, mas o seu banco não aceitou a transferência. # 8221;
Minha pressão sanguínea começa a subir porque eu sei que coisas assim realmente acontecem. Então, eu vou resumir com um último conselho: não compre nada de um site que tenha apenas uma página longa, ele pretende vender uma estratégia mágica que vai fazer você ganhar dinheiro garantido (e rápido), tem um muitos links, pop-ups ou itens para download ou tem alguma das características descritas nesta seção. Além disso, não colabore de forma alguma com um corretor anunciado em um desses sites. É um conselho gratuito, então pegue ou largue, mas acho que você vai se arrepender mais tarde se não aceitar.
Onde encontrar uma boa estratégia de opções binárias?
Existem provavelmente milhares de estratégias de negociação em toda a internet, algumas são boas, outras são ruins e algumas são repugnantemente estúpidas. Mas infelizmente não posso dar-lhe um mapa claro de onde está localizada a estratégia certa, porque cada comerciante tem uma certa mentalidade e zona de conforto. Comece por verificar a estratégia de opções binárias dos melhores novatos do Geek. Se você tirar um comerciante dessa zona, os erros provavelmente acontecerão e é por isso que uma estratégia que funciona bem para um comerciante pode ser desastrosa para outra pessoa. Você pode pensar que sou subjetivo, mas considero o BOTS como o único lugar onde você pode encontrar estratégias boas e claramente explicadas. Uma recomendação a respeito de uma estratégia é boa, mas, no final das contas, você precisa decidir qual estratégia combina com você e com o que se sente mais confortável. Eu gosto de estratégias de acompanhamento de tendências e eu as recomendo, mas eu nunca tentaria convencer ninguém a usar uma estratégia só porque eu gosto dela.
Eu mencionei o Santo Graal no parágrafo de abertura, mas alguns de vocês podem não estar familiarizados com este termo usado para estratégias de negociação: refere-se a uma estratégia que faz dinheiro 100% do tempo, nunca falha e torna você rico, garantido . Isto existe? Não! Desculpe pessoal, mas não existe, então pare de procurá-lo. A boa notícia é que com bastante trabalho, disciplina e perseverança (e provavelmente algumas outras coisas importantes que eu esqueci), você chegará perto do seu próprio Santo Graal. Não é algo facilmente alcançado, mas a verdade é, "Sem dor, sem ganho". # 8221; Existem alguns grandes sites para a educação Forex e sabemos que o comércio Forex e Binário é altamente correlacionado. Para começar com alguma educação básica Forex, eu recomendo um dos meus favoritos de todos os tempos: Babypips. Outra grande fonte é a Forex Factory e, por último, mas não menos importante, o BOTS Forum. Lá você pode encontrar novas estratégias e artigos educacionais quase todos os dias, então certifique-se de verificar regularmente.
A conclusão estratégica.
A importância de uma estratégia confiável é crucial se você for sério em ganhar dinheiro com a negociação. Mas igualmente, ou ainda mais importante, é sua mentalidade e sua abordagem psicológica deste negócio. Meu maior momento “Eureka!” Foi quando percebi que uma boa estratégia não é tudo que você precisa; Você também precisa colocar o trabalho e treinar-se. Sim, o caminho é difícil mas, em última análise, recompensador. Faça o que fizer, certifique-se de evitar fraudes e não dedique seu dinheiro a garotos que prometem a você incrível e fácil de conseguir riqueza. Evite-os a todo custo e pense sobre isso: se você tivesse o Santo Graal das estratégias, você diria a todos? Provavelmente não ... então não assuma que um cara, um autoproclamado "expert", só vai entregá-lo para você por um par de dólares.
será bom se você puder organizar os artigos de estratégias por nível.
E artigo muito informativo para iniciantes. bom trabalho!
Muito obrigado por este artigo!
Eu completei toda a Pré Escola e comecei com o primeiro artigo na Escola Primária (O que é uma Estratégia Binária).
Começa com algo que depende muito de "ADX". O que é isso?
Talvez eu tenha perdido, mas se não for, sendo a primeira coisa na escola primária, já estou perdido?
Não me leve a mal, o que você fez neste site não é nada menos do que incrível!
Eu vejo o seu problema Craig, mas a estratégia sobre o ADX contida no artigo que estamos falando é apenas um exemplo para ver como uma estratégia bem estruturada se parece. Observe que tem uma imagem explicando as entradas e também um resumo claro das regras para entrar em Call ou Put.
Algumas estratégias são confusas e o autor apenas fornece diretrizes, não regras exatas. Então, essa estratégia do Guru Fractal & # 8221; é apenas uma maneira de exemplificar uma estratégia com regras claras. Você pode desconsiderar isso e ler o resto do artigo, se quiser, dessa maneira.
Todo o melhor homem.
Eu tenho bons sinais para oferecer. 2 sinais livres por 2 dias. Então nós discutimos mais.
Guarde-os para você.
& # 8220; Cada comerciante tem uma certa mentalidade e zona de conforto. & # 8221; Aquele que dou 10/10. Obrigado pela sabedoria.
Por favor, aguarde 24-72 horas para rever o seu comentário.
Reservamo-nos o direito de decidir qual comentário será publicado.
Para perguntas sobre corretores - use nossos fóruns.
Para reclamações detalhadas - Por favor, use o nosso sistema de reclamações na página inicial.

No comments:

Post a Comment