This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
язык_программирования_python [2025/05/24 17:53] val [Zabbix API приложение] |
язык_программирования_python [2025/06/16 14:58] (current) val [FastAPI Uvicorn] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Язык программирования Python ====== | ====== Язык программирования Python ====== | ||
+ | * [[https://habr.com/ru/articles/277679/|Пишем shell скрипты на Python и можно ли заменить им Bash]] | ||
===== Виртуальная среда Python ===== | ===== Виртуальная среда Python ===== | ||
* [[https://blog.sedicomm.com/2021/06/29/chto-takoe-venv-i-virtualenv-v-python-i-kak-ih-ispolzovat/|Что такое venv и virtualenv в 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/|https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/]] | + | * [[https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/|Install packages in a virtual environment using pip and venv]] |
- | * [[https://www.workroom-productions.com/serving-a-directory-with-flask/|Publishing a Directory with Flask]] | + | |
+ | * [[https://habr.com/ru/articles/593529/|Poetry — прекрасная альтернатива pip (шпаргалка)]] | ||
+ | * [[https://habr.com/ru/articles/828016/|UV. Обзор пакетного менеджера Python]] | ||
<code> | <code> | ||
+ | # python3 -V | ||
# apt install python3-venv | # apt install python3-venv | ||
Line 19: | Line 24: | ||
</code> | </code> | ||
+ | |||
+ | ===== Интерактивная оболочка REPL (Read-Eval-Print Loop) ===== | ||
+ | |||
+ | <code> | ||
+ | (venv1) # python | ||
+ | </code> | ||
+ | |||
+ | * [[https://ru.wikipedia.org/wiki/IPython]] | ||
+ | |||
+ | <code> | ||
+ | (venv1) # pip install ipython | ||
+ | </code> | ||
+ | |||
+ | * [[https://jupyter.org/try-jupyter/notebooks/?path=notebooks/Intro.ipynb|try-jupyter/notebooks]] | ||
+ | * [[https://matplotlib.org/stable/tutorials/pyplot.html|Pyplot tutorial]] | ||
===== Web приложение ===== | ===== 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://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://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]] | * [[https://docs.python.org/3/library/configparser.html|configparser — Configuration file parser]] | ||
- | |||
- | * [[#Виртуальная среда Python]] | ||
<code> | <code> | ||
Line 37: | Line 64: | ||
import os | import os | ||
import configparser | 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 = Flask(__name__) | ||
Line 50: | Line 85: | ||
if __name__ == "__main__": | if __name__ == "__main__": | ||
- | config = configparser.ConfigParser() | ||
- | config.read('/etc/pywebd/pywebd.conf') | ||
- | # pywebd_port = os.environ.get('PYWEBD_PORT',config['default']['Listen']) | ||
- | # pywebd_doc_root = os.environ.get('PYWEBD_DOC_ROOT',config['default']['DocumentRoot']) | ||
- | if 'PYWEBD_PORT' in os.environ: | ||
- | pywebd_port = os.environ.get('PYWEBD_PORT') | ||
- | else: | ||
- | pywebd_port = config['default']['Listen'] | ||
- | if 'PYWEBD_DOC_ROOT' in os.environ: | ||
- | pywebd_doc_root = os.environ.get('PYWEBD_DOC_ROOT') | ||
- | else: | ||
- | pywebd_doc_root = config['default']['DocumentRoot'] | ||
- | app.run(host="0.0.0.0", port=pywebd_port, debug=True) | + | if 'PYWEBD_PORT' in os.environ: pywebd_port = os.environ.get('PYWEBD_PORT') |
- | # app.run(ssl_context=('/etc/pywebd/pywebd.crt', '/etc/pywebd/pywebd.key'), debug=True, host='0.0.0.0', port=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) | ||
</code><code> | </code><code> | ||
# mkdir -p /etc/pywebd/ | # mkdir -p /etc/pywebd/ | ||
Line 89: | Line 114: | ||
(venv1) :~/pywebd$ pip freeze | tee requirements.txt | (venv1) :~/pywebd$ pip freeze | tee requirements.txt | ||
+ | |||
+ | (venv1) :~/pywebd$ #pip install gunicorn | ||
+ | (venv1) :~/pywebd$ #gunicorn app:app --bind 0.0.0.0:8000 | ||
</code> | </code> | ||
- | ===== CRUD Rest API приложение ===== | ||
+ | ==== FastAPI Uvicorn ==== | ||
- | * [[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://python-poetry.org/docs/basic-usage/]] |
+ | * [[https://habr.com/ru/articles/593529/|Poetry — прекрасная альтернатива pip (шпаргалка)]] | ||
+ | |||
+ | <code> | ||
+ | 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 | ||
+ | </code><code> | ||
+ | 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) | ||
+ | </code><code> | ||
+ | /pywebd2 # cat .env | ||
+ | </code><code> | ||
+ | PYWEBD_MESSAGE="Hello World!!!" | ||
+ | </code> | ||
+ | |||
+ | * [[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]] | ||
+ | |||
+ | <code> | ||
+ | /pywebd2 # cat tests/test_ver_format.py | ||
+ | </code><code> | ||
+ | import app, re | ||
+ | |||
+ | assert re.match(r'^ver\d+\.\d+$', app.CONST_VER),"Incorrect VER format" | ||
+ | </code><code> | ||
+ | /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 | ||
+ | </code> | ||
+ | * [[https://github.com/benoitc/gunicorn/issues/2154|TypeError: __call__() missing 1 required positional argument: 'send']] | ||
+ | <code> | ||
+ | /pywebd2 # ###poetry run gunicorn app:app --bind 0.0.0.0:6080 -k uvicorn.workers.UvicornWorker | ||
+ | </code> | ||
+ | |||
+ | ===== 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, следующий элемент итератора]] | ||
+ | <code> | ||
+ | gate# apt install python3-xmltodict/stable | ||
+ | |||
+ | gate# cat /etc/zabbix/dhcp-pools.py | ||
+ | </code><code> | ||
+ | #!/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]) | ||
+ | </code> | ||
===== Zabbix API приложение ===== | ===== 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]] | ||
+ | | ||
<code> | <code> | ||
(venv1) server:~# pip install requests | (venv1) server:~# pip install requests | ||
- | (venv1) server:~# cat zab_get_problem.py | + | (venv1) server:~# cat zab_set_map_name.py |
</code><code> | </code><code> | ||
+ | #!/usr/bin/env python3 | ||
+ | |||
import requests | import requests | ||
import json | 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" | ZABBIX_API_URL = "http://127.0.0.1/zabbix/api_jsonrpc.php" | ||
Line 109: | Line 263: | ||
PWORD = "zabbix" | PWORD = "zabbix" | ||
+ | print("\nLogin user {} to Zabbiz API".format(UNAME)) | ||
r = requests.post(ZABBIX_API_URL, | r = requests.post(ZABBIX_API_URL, | ||
json={ | json={ | ||
Line 123: | Line 278: | ||
AUTHTOKEN = r.json()["result"] | AUTHTOKEN = r.json()["result"] | ||
- | print(AUTHTOKEN) | + | #print("Rename Map with ID", MAPID, "to", MAPNAME) |
+ | print(f"Rename Map with ID {MAPID} to {MAPNAME}") | ||
- | # Retrieve a list of problems | ||
- | print("\nRetrieve a list of problems") | ||
r = requests.post(ZABBIX_API_URL, | r = requests.post(ZABBIX_API_URL, | ||
headers={'Authorization': 'Bearer ' + AUTHTOKEN}, | headers={'Authorization': 'Bearer ' + AUTHTOKEN}, | ||
json={ | json={ | ||
- | "jsonrpc": "2.0", | + | "jsonrpc": "2.0", |
- | "method": "problem.get", | + | "method": "map.update", |
- | "params": {}, | + | "params": { |
- | "id": 2, | + | "sysmapid": MAPID, |
+ | "name": MAPNAME | ||
+ | }, | ||
+ | "id": 2 | ||
}) | }) | ||
print(json.dumps(r.json(), indent=4, sort_keys=True)) | print(json.dumps(r.json(), indent=4, sort_keys=True)) | ||
- | #Logout user | ||
print("\nLogout user") | print("\nLogout user") | ||
r = requests.post(ZABBIX_API_URL, | r = requests.post(ZABBIX_API_URL, | ||
Line 151: | Line 307: | ||
print(json.dumps(r.json(), indent=4, sort_keys=True)) | print(json.dumps(r.json(), indent=4, sort_keys=True)) | ||
</code><code> | </code><code> | ||
- | (venv1) server:~# python3 zab_get_problem.py | + | (venv1) server:~# chmod +x zab_set_map_name.py |
+ | |||
+ | (venv1) server:~# ./zab_set_map_name.py 2 "ISP 1" | ||
</code> | </code> | ||
+ | |||
+ | |||
+ | ===== 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 ==== | ==== Доступ к каталогу по http ==== | ||
Line 163: | Line 331: | ||
</code> | </code> | ||
+ | ==== Черновик ==== | ||