====== Язык программирования Python ======
* [[https://habr.com/ru/articles/277679/|Пишем shell скрипты на Python и можно ли заменить им Bash]]
===== Виртуальная среда Python =====
* [[https://blog.sedicomm.com/2021/06/29/chto-takoe-venv-i-virtualenv-v-python-i-kak-ih-ispolzovat/|Что такое venv и virtualenv в Python, и как их использовать]]
* [[https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/|Install packages in a virtual environment using pip and venv]]
* [[https://habr.com/ru/articles/593529/|Poetry — прекрасная альтернатива pip (шпаргалка)]]
* [[https://habr.com/ru/articles/828016/|UV. Обзор пакетного менеджера Python]]
# python3 -V
# apt install python3-venv
$ python3 -m venv ~/venv1
$ source ~/venv1/bin/activate
(venv1) $ which python
(venv1) $ which ansible
(venv1) $ deactivate
===== Интерактивная оболочка REPL (Read-Eval-Print Loop) =====
(venv1) # python
* [[https://ru.wikipedia.org/wiki/IPython]]
(venv1) # pip install ipython
* [[https://jupyter.org/try-jupyter/notebooks/?path=notebooks/Intro.ipynb|try-jupyter/notebooks]]
* [[https://matplotlib.org/stable/tutorials/pyplot.html|Pyplot tutorial]]
===== Web приложение =====
* [[https://webadventures.ru/sravnenie-wsgi-serverov-uvicorn-i-gunicorn/|Сравнение WSGI-серверов:uvicorn и Gunicorn]]
==== Flask Gunicorn ====
* [[#Виртуальная среда Python]]
* [[https://habr.com/ru/articles/750312/|Python декораторы на максималках. Универсальный рецепт по написанию и аннотированию от мала до велика]]
* [[https://www.workroom-productions.com/serving-a-directory-with-flask/|Publishing a Directory with Flask]]
* [[https://python.ivan-shamaev.ru/run-install-deploy-flask-web-app-docker-dockerfile-compose/|Создание Web-приложения Flask и деплой с помощью Docker Compose & Dockerfile]]
* [[https://blog.miguelgrinberg.com/post/running-your-flask-application-over-https|Running Your Flask Application Over HTTPS]]
* [[https://docs.python.org/3/library/configparser.html|configparser — Configuration file parser]]
(venv1) :~$ pip install Flask
(venv1) :~$ mkdir -p pywebd/; cd $_
(venv1) :~/pywebd$ cat app.py
from flask import Flask, send_from_directory
import os
import configparser
config = configparser.ConfigParser()
config.read('/etc/pywebd/pywebd.conf')
if 'PYWEBD_DOC_ROOT' in os.environ:
pywebd_doc_root = os.environ.get('PYWEBD_DOC_ROOT')
else:
pywebd_doc_root = config['default']['DocumentRoot']
app = Flask(__name__)
@app.route('/')
def index():
return send_from_directory(pywebd_doc_root, 'index.html')
@app.route('/')
def sendstuff(path):
print(path)
return send_from_directory(pywebd_doc_root, path)
if __name__ == "__main__":
if 'PYWEBD_PORT' in os.environ: pywebd_port = os.environ.get('PYWEBD_PORT')
else: pywebd_port = config['default']['Listen']
app.run(host="0.0.0.0", port=pywebd_port, debug=True)
# app.run(ssl_context=('/etc/pywebd/pywebd.crt', '/etc/pywebd/pywebd.key'), debug=True, host='0.0.0.0', port=pywebd_port)
# mkdir -p /etc/pywebd/
# cat /etc/pywebd/pywebd.conf
[default]
DocumentRoot = /var/www/
Listen = 4080
# #cp /root/wild.crt /etc/pywebd/pywebd.crt
# #cp /root/wild.key /etc/pywebd/pywebd.key
* [[Средства программирования shell#Ресурсы Web сервера на shell]]
(venv1) :~/pywebd$ #export PYWEBD_PORT=4443
(venv1) :~/pywebd$ #export PYWEBD_DOC_ROOT=/var/www/html/
(venv1) :~/pywebd$ #PYWEBD_PORT=4443 PYWEBD_DOC_ROOT=/var/www/html/ python app.py
(venv1) :~/pywebd$ python app.py
(venv1) :~/pywebd$ pip freeze | tee requirements.txt
(venv1) :~/pywebd$ #pip install gunicorn
(venv1) :~/pywebd$ #gunicorn app:app --bind 0.0.0.0:8000
==== FastAPI Uvicorn ====
* [[https://python-poetry.org/docs/basic-usage/]]
* [[https://habr.com/ru/articles/593529/|Poetry — прекрасная альтернатива pip (шпаргалка)]]
server# ###docker run -ti --rm --name pywebd2 python:3.11-alpine sh
/ # ### pip install poetry
server# apt install python3-poetry; export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring #https://stackoverflow.com/questions/74438817/poetry-failed-to-unlock-the-collection
/ # poetry new pywebd2
/ # cd pywebd2
/pywebd2 # poetry add fastapi dotenv uvicorn ###gunicorn
/pywebd2 # more pyproject.toml
/pywebd2 # cat app.py
from fastapi import FastAPI
from dotenv import load_dotenv
import os
CONST_VER = "ver1.1"
hostname = os.uname().nodename
load_dotenv()
pywebd_message = os.environ.get('PYWEBD_MESSAGE')
app = FastAPI()
@app.get("/")
async def home():
return {"data": f"{pywebd_message} from {hostname} app {CONST_VER}"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
/pywebd2 # cat .env
PYWEBD_MESSAGE="Hello World!!!"
* [[https://tproger.ru/articles/testiruem-na-python-unittest-i-pytest-instrukcija-dlja-nachinajushhih|Тестируем на Python: unittest и pytest. Инструкция для начинающих]]
* [[https://habr.com/ru/articles/349860/|Регулярные выражения в Python от простого к сложному. Подробности, примеры, картинки, упражнения]]
* [[https://regex101.com/|Online Regular expression tester with syntax highlighting]]
/pywebd2 # cat tests/test_ver_format.py
import app, re
assert re.match(r'^ver\d+\.\d+$', app.CONST_VER),"Incorrect VER format"
/pywebd2 # poetry run python3 -m unittest
/pywebd2 # #export PYWEBD_MESSAGE="Another message"
/pywebd2 # poetry run python3 app.py
/pywebd2 # poetry run uvicorn app:app --reload --host 0.0.0.0 --port 4080
* [[https://github.com/benoitc/gunicorn/issues/2154|TypeError: __call__() missing 1 required positional argument: 'send']]
/pywebd2 # ###poetry run gunicorn app:app --bind 0.0.0.0:6080 -k uvicorn.workers.UvicornWorker
===== Zabbix LLD приложение =====
* [[https://askubuntu.com/questions/244378/running-python-file-in-terminal|Running Python File in Terminal]]
* [[https://pythonworld.ru/moduli/modul-subprocess.html|Модуль subprocess]]
* [[https://habr.com/ru/articles/488112/|Понимание итераторов в Python]]
* [[https://www.geeksforgeeks.org/python-find-dictionary-matching-value-in-list/|Find dictionary matching value in list - Python]]
* [[https://docs-python.ru/tutorial/vstroennye-funktsii-interpretatora-python/funktsija-next/|Функция next() в Python, следующий элемент итератора]]
gate# apt install python3-xmltodict/stable
gate# cat /etc/zabbix/dhcp-pools.py
#!/usr/bin/env python3
# Example usage:
# ./dhcp-pools.py
# ./dhcp-pools.py LAN1 defined|used
from sys import argv
import subprocess, xmltodict, json
p = subprocess.Popen("/usr/bin/dhcpd-pools -f x", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
o = xmltodict.parse(output)
#print (o)
if len(argv)==1:
r=[]
for i in o['dhcpstatus']['shared-network']:
s={}
s["{#POOLNAME}"]=i['location']
r.insert(1,s)
print(json.dumps(r))
else:
LANNAME=argv[1]
USDEF=argv[2]
res = next((sub for sub in o['dhcpstatus']['shared-network'] if sub['location'] == LANNAME), None)
print(res[USDEF])
===== Zabbix API приложение =====
* [[https://www.zabbix.com/documentation/current/en/manual/api]]
* [[https://sbcode.net/zabbix/zabbix-api-python-example/]]
* [[https://forum.checkmk.com/t/rest-api-python-question-how-to-use-variables-in-json-post-in-key-and-value/34652]]
(venv1) server:~# pip install requests
(venv1) server:~# cat zab_set_map_name.py
#!/usr/bin/env python3
import requests
import json
from sys import argv
if len(argv) != 3 :
print("You must set argument!!!\nExample: python zab_set_map_name.py 2 \"ISP 1\"")
quit()
MAPID = argv[1]
MAPNAME = argv[2]
ZABBIX_API_URL = "http://127.0.0.1/zabbix/api_jsonrpc.php"
UNAME = "Admin"
PWORD = "zabbix"
print("\nLogin user {} to Zabbiz API".format(UNAME))
r = requests.post(ZABBIX_API_URL,
json={
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"username": UNAME,
"password": PWORD},
"id": 1
})
print(json.dumps(r.json(), indent=4, sort_keys=True))
AUTHTOKEN = r.json()["result"]
#print("Rename Map with ID", MAPID, "to", MAPNAME)
print(f"Rename Map with ID {MAPID} to {MAPNAME}")
r = requests.post(ZABBIX_API_URL,
headers={'Authorization': 'Bearer ' + AUTHTOKEN},
json={
"jsonrpc": "2.0",
"method": "map.update",
"params": {
"sysmapid": MAPID,
"name": MAPNAME
},
"id": 2
})
print(json.dumps(r.json(), indent=4, sort_keys=True))
print("\nLogout user")
r = requests.post(ZABBIX_API_URL,
headers={'Authorization': 'Bearer ' + AUTHTOKEN},
json={
"jsonrpc": "2.0",
"method": "user.logout",
"params": {},
"id": 2,
})
print(json.dumps(r.json(), indent=4, sort_keys=True))
(venv1) server:~# chmod +x zab_set_map_name.py
(venv1) server:~# ./zab_set_map_name.py 2 "ISP 1"
===== CRUD Rest API приложение =====
* [[https://dev.to/francescoxx/python-crud-rest-api-using-flask-sqlalchemy-postgres-docker-docker-compose-3kh4|Python CRUD Rest API using Flask, SQLAlchemy, Postgres, Docker, Docker Compose]]
===== Дополнительные материалы =====
* [[https://pypi.org/project/ansible-output-parser/]]
* [[https://www.cyberciti.biz/faq/python-run-external-command-and-get-output/]]
* [[https://selectel.ru/blog/tutorials/how-to-develop-fastapi-application/]]
==== Доступ к каталогу по http ====
* [[https://gist.github.com/SeanPesce/af5f6b7665305b4c45941634ff725b7a|SeanPesce/https_server.py]]
dir$ python3 -m http.server 80
==== Черновик ====