Programando em Python no PyCharm

O PyCharm cria automaticamente um virtual environment para o seu projeto (venv).

ATENÇÃO! DEIXE O PIP NA VERSÃO 9.0.3! NÃO ATUALIZE!

Para instalar pacotes

File -> Settings -> Project : Nome do seu projeto -> Project Interpreter -> Clique no + verde à direita da janela

O PyCharm no Windows pode baixar os pacotes em suas últimas versões.

É preciso instalar o pacote virtualenv

[code language="batch"] pip install virtualenv [/code]

Manipulando venv no Windows

[code] C:\Users\Tito\PycharmProjects\NetworkMonitor\venv\Scripts\activate.bat easy_install -U pip easy_install -U setuptools [/code]

Para atualizar no windows é preciso entrar no VENV e fazer

[code] easy_install -U pip [/code]

Distribuindo seu código

https://packaging.python.org/tutorials/packaging-projects/

Usando o PEX (Exe de Python)

Discussão no Redit https://www.reddit.com/r/Python/comments/5rey4a/distributing_a_virtualenv_and_all_dependencies_as/

Pipenv https://pipenv.readthedocs.io/en/latest/

Como dar nome aos pacotes, classes, etc? Convenção de nomes no Python.

Nome do pacote: caixabaixa (de preferência sem underscore) Nome dos arquivos: caixa_baixa Nome das classes: NomeDaClasse

Modelo de estrutura de projeto

[code] /meu_programa /meu_programa __init__.py setup.py LICENSE README.md [/code]

Exemplo de setup.py

[code language="python"]

import setuptools

with open("README.md", "r") as fh: long_description = fh.read()

setuptools.setup( name="meu_programa", version="0.0.1", author="Johnny Wow", author_email="[email protected]", description="Software para fazer algo", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/pypa/sampleproject", packages=setuptools.find_packages(), classifiers=[ "Programming Language :: Python :: 3", "Operating System :: OS Independent", ], ) [/code]

Declarando tipos em Python (Python 3.6 a diante)

A partir do Python 3.6 é possível declarar tipos no Python. O compilador em si não realiza verificações, mas as IDEs podem usar isso para facilitar os trabalhos. Aqui vai um tutorial.

Modelo de main em Python

[code language="python"] def main(): print("Hello World!")

if __name__ == "__main__": main() [/code]

Listen/Notify com PostgreSQL no Python

Enviando uma notificação no PostgreSQL

[code language="sql"] --O esqueleto da notificação é NOTIFY nome_do_canal, mensagem (também chamado de payload) NOTIFY canal_usuario, 'oi, você recebeu uma notificação do canal_usuário.'; --Também da pra enviar notificações assim: SELECT pg_notify('canal_usuario','oi, você recebeu uma notificação do canal_usuário.'); [/code]

Recebendo uma notificação no Python 3.6 com psycopg2

[code language="python"]

import select import psycopg2 import psycopg2.extensions import logging from threading import Thread from threading import RLock from values_monitor.config import DatabaseConfig import values_monitor.monitor_state

class PostgreSQLConnection:

def __init__(self, database_config: DatabaseConfig, ): self.database_config = database_config self.logger = logging.getLogger('PostgreSQLConnection') self.logger.debug(database_config.database) self.logger.debug(database_config.host) self.conn = None self.readLock: RLock self.writeLock: RLock

def connect(self): try: self.conn = psycopg2.connect( host=self.database_config.host, port=self.database_config.port, dbname=self.database_config.database, user=self.database_config.user, password=self.database_config.password ) self.conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) except psycopg2.Error as e: self.logger.error("Error while creating database connection.") self.logger.error(e)

def get_version(self): with self.conn.cursor() as cur: cur.execute("SELECT version();") result = cur.fetchall() self.logger.debug(result)

def __listen(self, channel: str, operation): seconds_step = 120 with self.conn.cursor() as cur: cur.execute("LISTEN "+channel+";") self.logger.info("Listening for notifications in channel {}.".format(channel)) seconds_passed = 0 while True: if select.select([self.conn], [], [], seconds_step) == ([], [], []): seconds_passed += seconds_step self.logger.debug("{} seconds passed without a notification at channel {}." .format(seconds_passed, channel)) else: self.conn.poll() seconds_passed = 0 while self.conn.notifies: notify = self.conn.notifies.pop(0) self.logger.info("Notify received! Content is:") self.logger.info(notify) operation(notify)

def listen_as_thread(self, channel: str, operation): thread = Thread(target=self.__listen, args=(channel, operation), name='pg_listen_'+channel) thread.start()

[/code]

Referências

PostgreSQL Wiki Presentation https://wiki.postgresql.org/images/7/77/Psycopg-2010-stuttgart.pdf

Documentação oficial psycopg2 http://initd.org/psycopg/docs/advanced.html

Exemplo de Listen/Notify no Python com psycopg2 https://gist.github.com/dtheodor/126fc329960a714f1945

Exemplo de Listen/Notify no Python com psycopg2 https://github.com/nickdmoore/pg_channels/blob/master/pg_channels/__init__.py

Threads em Python

A biblioteca mais moderna para lidar com threads em python é a threading.

O python é bem flexível para criar threads.

Mas no Python temos um detalhe, as threads não são capazes de usar todos os cores  do processador. Para processamentos pesados, utilizar o numpy ou o multiprocessing.

Tutorial curto e bom http://alissonmachado.com.br/python-threads/

Tutorial completo https://www.tutorialspoint.com/python/python_multithreading.htm

Tutorial mais longo https://cadernodelaboratorio.com.br/2017/12/18/threads-em-python-3/

Documentação oficial do threading https://docs.python.org/3.4/library/threading.html

Python RESTful Web Server + Flask + Requests

https://www.bogotobogo.com/python/python-REST-API-Http-Requests-for-Humans-with-Flask.php

Colocando o Flask em Produção com Waitress

O Flask vêm com um web server integrado, mas ele não é recomendado para ambientes de produção. Uma das recomendações é usar o waitress.

http://gr33ndata.blogspot.com/2012/01/waitress-flask.html

Algumas opções de outros servidores em python https://quintagroup.com/cms/python/web-server http://flask.pocoo.org/docs/1.0/deploying/

Programação funcional em Python

https://docs.python.org/3/howto/functional.html

Agendador de tarefas avançado no Python

Imagine que de tempos em tempos você queria que seu programa chame uma função.

Se você só precisa a função seja chamada de x em x tempos (tipo 30 em 30 segundos, 1 em 1 hora, 3 em 3 dias...), você pode usar o threading.Timer, biblioteca padrão do Python.

Mas se você quer agendar algo de forma mais avançada? Tipo agendar uma tarefa em determinados dias da semana? Abaixo mostro algumas soluções

Biblioteca APScheduler

É a biblioteca mais avançada, implementa scheduling baseado em date, interval e cron. Confira a documentação oficial.

[code language="python"] from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.date import DateTrigger from apscheduler.triggers.cron import CronTrigger from apscheduler.triggers.interval import IntervalTrigger

interval_trigger = IntervalTrigger(seconds=5) scheduler.add_job(print, trigger=interval_trigger, args=['Hello, this was printed by an interval based job.'])

date_trigger = DateTrigger(run_date='2018-11-19 21:15:00', timezone='UTC') scheduler.add_job(print, trigger=date_trigger, args=['Hello, this was printed by a date based job.'])

cron_trigger = CronTrigger(year=2018, month=11, second=20, start_date='2018-10-01', end_date='2018-11-19 19:41:00', timezone='America/Sao_Paulo') scheduler.add_job(print, cron_trigger, args=['Hello, this was printed by a cron based job.'])

# But you can also add jobs after the schedule has started.

scheduler.start() [/code]

O APScheduler usa os seguintes conceitos:

  • scheduler
  • executor
  • job store

No código fonte existem as seguintes classes:

base

É a classe abstrata que todas as outras classes de job store implementam

memory

Banco em memória, não implementa persistência

mongodb

Persiste no MongoDB

redis

Persiste no Redis

rethinkdb

Persiste no Redis

sqlalchemy

Persiste em qualquer banco suportado pelo SQLAlchemy

zookeper

Persiste no Zookeper

  • trigger

Atenção, se você for rodar muitos schedules, é preciso aumentar o número de ThreadPoolExecutors e ProcessPoolExecutors.

Criando um histórico dos

Banco de dados em memória e persistente no Python com PyDbLite

É um banco de dados bem simples, que utiliza dicionários como base e permite indexação dos campos via hash.

https://pydblite.readthedocs.io/en/latest/pythonengine.html

You should also read:

Fazendo os prints do Python aparecerem no systemctl status

fazer todos os prints passarem o parâmetro flush=True [code language="python"] import functools print = functools.partial(print, flush=True) [/code] https://stackoverflow.com/questions/230751/how-to-flush-output-of-print-function https://fhackts.wordpress.com/2014/11/27/systemd-journal-not-showing-python-3-print/