Python для начинающих
1.06K subscribers
283 photos
3 videos
232 files
61 links
Python для начинающих
Download Telegram
Привет! Сегодня копнем в сторону автоматики — поговорим о том, как использовать Ansible и Python для автоматизации системных задач. Ansible сам по себе мощный инструмент, но иногда хочется чуть больше гибкости — тут на помощь и приходит Python. Совместно они превращаются в универсальный швейцарский нож DevOps'а.

🎯 Зачем это вообще нужно?

Представим типичный сценарий: у вас есть десяток серверов, на которых нужно установить nginx, обновить пакеты, разложить конфиги. Можно, конечно, вручную, но это скучно и долго. Ansible позволяет описать всё это в виде playbook'ов — вы просто нажимаете "старт", и магия происходит сама. Но если нужна логика посложнее — Python готов помочь.

📦 Установка Ansible и библиотек

Начнем с подготовки:

pip install ansible
pip install ansible-runner


ansible-runner — это модуль, который позволяет управлять Ansible-скриптами напрямую из Python.

🛠 Простой playbook

Давайте создадим playbook, который обновляет систему и устанавливает htop.

Файл: update_install.yml

- hosts: all
become: true
tasks:
- name: Update apt cache
apt:
update_cache: yes

- name: Install htop
apt:
name: htop
state: present


Запуск playbook из Python

Теперь напишем скрипт, который запустит этот playbook прямо из Python.

import ansible_runner

def run_playbook():
result = ansible_runner.run(private_data_dir='.', playbook='update_install.yml')
print("Status:", result.status)
print("RC:", result.rc)

for e in result.events:
print(e.get('stdout', ''))

run_playbook()


Важно, чтобы рядом лежал файл inventory с описанием хостов.

Файл: inventory

[servers]
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa


🔁 Генерация динамического инвентори на Python

Вместо статического файла можно сгенерировать список хостов прямо из Python:

import json

inventory = {
"all": {
"hosts": ["192.168.1.10", "192.168.1.11"],
"vars": {
"ansible_user": "ubuntu",
"ansible_ssh_private_key_file": "~/.ssh/id_rsa"
}
}
}

with open("inventory.json", "w") as f:
json.dump(inventory, f)


Запуск с таким инвентори:

result = ansible_runner.run(
private_data_dir='.',
playbook='update_install.yml',
inventory='inventory.json'
)


🚀 Бонус: передача переменных из Python

Нужно передать параметры в playbook? Не проблема:

extra_vars = {
"package_name": "nginx"
}

ansible_runner.run(
private_data_dir='.',
playbook='install_pkg.yml',
extravars=extra_vars
)


А в самом playbook:

- name: Install package
hosts: all
become: true
tasks:
- name: Install {{ package_name }}
apt:
name: "{{ package_name }}"
state: present


🔥 Вывод

Вместе Ansible и Python открывают ворота в мир мощной и гибкой автоматизации. Хотите запустить плейбук после триггера в Django или по расписанию через Celery? Просто запускайте нужный скрипт. Это отличная пара для тех, кто предпочитает программировать инфраструктуру, а не кликать по консоли.

С вами был Иван. Пиши код и автоматизируй всё вокруг!
🔥2
Работа с протоколом SNMP для управления сетевыми устройствами.
Привет! Сегодня мы окунемся в мир сетей — разберемся, как с помощью Python управлять сетевыми устройствами через протокол SNMP. Если тебе кажется, что это сложно — спешу успокоить: всё на удивление просто, особенно если использовать правильные библиотеки.

SNMP (Simple Network Management Protocol) — это протокол, который позволяет считывать информацию о состоянии устройств в сети и даже управлять ими. Чаще всего его используют для мониторинга роутеров, свитчей, принтеров и серверов.

Для работы с SNMP в Python существует отличная библиотека — pysnmp. Она поддерживает все версии протокола и предоставляет простой интерфейс для запросов.

Установим её:

pip install pysnmp


Разберем простой пример: считаем системное имя (sysName) устройства.

from pysnmp.hlapi import *

iterator = getCmd(
SnmpEngine(),
CommunityData('public', mpModel=0), # SNMPv1/v2c
UdpTransportTarget(('192.168.1.1', 161)),
ContextData(),
ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysName', 0))
)

errorIndication, errorStatus, errorIndex, varBinds = next(iterator)

if errorIndication:
print(f"Error: {errorIndication}")
elif errorStatus:
print(f"{errorStatus.prettyPrint()} at {errorIndex}")
else:
for varBind in varBinds:
print(f"{varBind[0].prettyPrint()} = {varBind[1].prettyPrint()}")


В этом скрипте мы запрашиваем объект sysName.0, который представляет имя хоста. Обрати внимание: указывается IP-адрес устройства и SNMP-комьюнити. Здесь мы используем community public, распространённое значение по умолчанию — но лучше использовать свою для безопасности.

Теперь пример посложнее: соберем список интерфейсов.

from pysnmp.hlapi import *

for (errorIndication,
errorStatus,
errorIndex,
varBinds) in nextCmd(SnmpEngine(),
CommunityData('public'),
UdpTransportTarget(('192.168.1.1', 161)),
ContextData(),
ObjectType(ObjectIdentity('IF-MIB', 'ifDescr')),
lexicographicMode=False):
if errorIndication:
print(f"Error: {errorIndication}")
break
elif errorStatus:
print(f"{errorStatus.prettyPrint()} at {errorIndex}")
break
else:
for varBind in varBinds:
print(f"{varBind[0]} = {varBind[1]}")


Функция nextCmd выполняет последовательный опрос — это удобно, когда нужно пройти по дереву OID'ов, например, чтобы получить список интерфейсов.

А теперь — изюминка! Через SNMP можно не только читать данные, но и изменять параметры. Например, выключить интерфейс. Но для этого нужно использовать права на запись, а значит подбирать правильное community и понимать последствия.

Вот пример с setCmd:

from pysnmp.hlapi import *

errorIndication, errorStatus, errorIndex, varBinds = next(
setCmd(SnmpEngine(),
CommunityData('private'), # community с правами записи
UdpTransportTarget(('192.168.1.1', 161)),
ContextData(),
ObjectType(ObjectIdentity('IF-MIB', 'ifAdminStatus', 2), Integer(2))) # 2 = down
)

if errorIndication:
print(f"Error: {errorIndication}")
elif errorStatus:
print(f"{errorStatus.prettyPrint()} at {errorIndex}")
else:
print("Interface disabled successfully")


Осторожно: этим можно на самом деле отключить интерфейс маршрутизатора! Так что всегда проверяй документацию и тестируй в безопасной среде.

На этом всё. SNMP — мощный инструмент в арсенале Python-программиста, особенно если ты работаешь с сетевым оборудованием. Надеюсь, теперь ты смотришь на сетевые протоколы без страха — скорее с азартом исследователя.

Увидимся в следующих постах!
— Иван
👍2
Работа с текстом: использование модуля textwrap для форматирования строк
📦 Python для начинающих: форматируем текст как профи с помощью textwrap

Привет! С вами Иван, и сегодня я расскажу про один из тех модулей стандартной библиотеки Python, который редко упоминают, но который может прилично упростить жизнь — особенно, если вы работаете с текстами. Речь пойдет о модуле textwrap. Он помогает красиво разносить текст по строкам, контролировать ширину текста, оформлять вывод — всего лишь парой строк кода.

Представьте, что вы делаете консольный словарь, новостной бот или пишете отчет в текстовый файл. Текст должен хорошо читаться, особенно в терминале. Вот тут в игру вступает textwrap.

Начнем с простого:

import textwrap

sample_text = "Python is a powerful high-level programming language known for its readability and versatility."

wrapped = textwrap.fill(sample_text, width=40)
print(wrapped)


Результат будет такой:

Python is a powerful high-level
programming language known for its
readability and versatility.


Функция fill возвращает строку, где длинный текст красиво "перенесен" на несколько строк, каждая — не длиннее 40 символов. Если больше — строки будут обрезаться и переноситься.

Теперь представим, что вы хотите получить список строк, чтобы, например, написать их в файл построчно. Тогда подойдет метод wrap:

lines = textwrap.wrap(sample_text, width=30)
for line in lines:
print(line)


Результат:

Python is a powerful high-
level programming language
known for its readability and
versatility.


Но это еще не всё! Бывали ли у вас случаи, когда нужно было красиво оформить блок текста с отступом или добавить префикс к каждой строке, например, "> " для цитаты? Вот как это делается:

quote = textwrap.fill(sample_text, width=50, initial_indent="> ", subsequent_indent="> ")
print(quote)


Получим:

> Python is a powerful high-level programming
> language known for its readability and
> versatility.


А ещё есть текстовая "обрезка". Не всегда хочется показывать пользователю весь текст. Иногда достаточно одного абзаца. Вот как можно аккуратно "усечь" строку до нужного количества символов с добавлением троеточия:

short = textwrap.shorten(sample_text, width=50, placeholder="...")
print(short)


Вывод:

Python is a powerful high-level programming...


textwrap — это простой, но мощный способ сделать текст более читаемым и привлекательным прямо из консоли. Особенно он полезен, если вы оформляете сообщения, вывод или простые отчеты в текстовые файлы. Не стоит недооценивать, насколько визуальная чистота и читаемость важны даже в командной строке.

На этом всё. Форматируйте с умом — и пиши красиво, даже в консоли! 👨‍💻

– Иван.
👍1
Как извлекать метаданные из изображений с помощью PIL
Как извлекать метаданные из изображений с помощью PIL
Привет! Сегодня разберёмся, как с помощью библиотеки PIL (а точнее — её форка Pillow) извлекать метаданные из изображений. Возможно, ты удивишься, но внутри фотографии может скрываться целая история: модель камеры, геолокация съёмки, ориентация, дата и даже настройки экспозиции. Эта информация называется EXIF (Exchangeable Image File Format). Так что давай копнём глубже!

📸 Что такое EXIF?

Многие изображения, особенно сделанные на смартфоны или цифровые камеры, содержат EXIF-метаданные. Они встраиваются внутрь JPEG-файлов и могут включать:

- Дату и время съёмки
- Геолокацию (если включена на устройстве)
- Параметры камеры (ISO, диафрагма, выдержка)
- Модель устройства

Для извлечения этой информации, мы будем использовать библиотеку Pillow.

📦 Установка Pillow

Если у тебя ещё не установлена Pillow, пора это исправить:

pip install pillow


🔍 Пример 1: Извлекаем EXIF

from PIL import Image
from PIL.ExifTags import TAGS

def get_exif_data(image_path):
image = Image.open(image_path)
exif_data = image._getexif()

if not exif_data:
return {}

readable_exif = {}
for tag, value in exif_data.items():
tag_name = TAGS.get(tag, tag)
readable_exif[tag_name] = value
return readable_exif

metadata = get_exif_data("example.jpg")

for key, value in metadata.items():
print(f"{key}: {value}")


В этой функции мы используем _getexif(), чтобы достать "сырой" словарь с числовыми тегами. Затем мы красиво преобразуем их в читаемые названия с помощью словаря TAGS.

🗺 Пример 2: Достаём координаты

EXIF может содержать GPS-информацию, но она закодирована хитро. Примерно так выглядит выделение широты и долготы:

from PIL.ExifTags import GPSTAGS

def get_gps_info(exif_data):
gps_info = exif_data.get("GPSInfo")
if not gps_info:
return None

gps_data = {}
for key in gps_info:
name = GPSTAGS.get(key, key)
gps_data[name] = gps_info[key]
return gps_data

gps = get_gps_info(metadata)
print(gps)


Чтобы перевести координаты в привычный вид (десятичные градусы), нужно будет ещё немного математики — но это тема для отдельного поста.

💡 Полезные советы

- Не все изображения содержат EXIF. Лучше проверяй, что _getexif() не вернул None.
- Некоторые поля, особенно GPS, могут не присутствовать даже если они поддерживаются.
- Для более продвинутой работы с GPS или редактирования EXIF-данных рекомендую посмотреть сторону библиотеки piexif.

📌 Заключение

Pillow даёт простой способ заглянуть в "паспорт" изображения. Если ты занимаешься обработкой фото, создаёшь галереи или строишь приложения с геометками — умение читать EXIF точно тебе пригодится.

На сегодня всё, с тобой был Иван. Программируй с интересом!
Создание диаграмм и графиков с использованием Plotly Express
💡 Python для начинающих: создаем диаграммы и графики с Plotly Express

Привет! Я — Иван, и сегодня в нашем блоге мы познакомимся с одной из самых визуально приятных и мощных библиотек для создания интерактивных графиков в Python — Plotly Express.

Если вы устали от статичных графиков из matplotlib и хотите добавить немного “вау”-эффекта в свои визуализации, Plotly Express вас точно не разочарует. Прост в использовании, эффектен с первого взгляда — идеальный инструмент для тех, кто только начинает погружаться в анализ данных.

📦 Установка

Для начала нужно установить Plotly (если ещё не установлено):

pip install plotly


📊 Первая диаграмма — разброс на макс

Представим, что у нас есть простой датафрейм с ростом и весом людей. Построим график рассеяния:

import plotly.express as px
import pandas as pd

data = pd.DataFrame({
'height_cm': [160, 165, 170, 175, 180, 185],
'weight_kg': [55, 60, 65, 72, 80, 90],
'gender': ['female', 'female', 'male', 'male', 'male', 'female']
})

fig = px.scatter(data,
x='height_cm',
y='weight_kg',
color='gender',
title='Height vs Weight')
fig.show()


Что круто: график интерактивный. Можно навести курсор на точку и увидеть значения. А ещё можно приближать, выделять область и даже сохранять изображение в PNG без усилий.

📈 Линии? Не вопрос!

Допустим, у нас есть рост населения по годам. Построим линейную диаграмму:

df = pd.DataFrame({
'year': [2015, 2016, 2017, 2018, 2019, 2020],
'population': [7.2, 7.4, 7.5, 7.6, 7.7, 7.8]
})

fig = px.line(df, x='year', y='population', title='World Population Over Time')
fig.show()


Одной строкой — и дашборд готов

Вместо десятка строк кода ты получаешь красивую интерактивную визуализацию буквально двумя-тремя строчками. И это особенно полезно при быстрой работе с данными — будь то исследовательский анализ (EDA) или презентация результата.

📚 Несколько дополнительных идей

- px.bar — строит столбчатые диаграммы
- px.pie — для круговых диаграмм
- px.histogram — удобно строить распределения
- px.box — boxplot без боли

Каждая из функций поддерживает такие параметры, как color, size, symbol, facetrow и facetcol — они позволяют легко группировать и сравнивать данные по категориям без сложных манипуляций.

🧙‍♂️ Заключение

Plotly Express — это мощь и простота в одном флаконе. Если ты начинаешь свой путь в анализе данных и хочешь делать визуализации, которые впечатляют — дай этой библиотеке шанс. Начни с простого scatter, поиграй со стилями... и ты не заметишь, как она станет любимой частью твоего стека.

До встречи в следующем посте! 🐍
👍2
Разработка приложений для автоматизации задач с помощью pyautogui
Привет, друзья! С вами Иван.

Сегодня я хочу рассказать о весьма интересной библиотеке в Python — pyautogui. Это настоящая палочка-выручалочка, если вы задумали автоматизировать скучные, однообразные операции за компьютером: клики, прокрутки, нажатия клавиш. Звучит как магия? В каком-то смысле — да. Но магия здесь вполне осязаемая и практичная.

Библиотека pyautogui позволяет управлять мышью и клавиатурой так, будто это делает человек. Она отлично подойдёт для создания мини-утилит, которые автоматизируют, например, повторяющиеся шаги в рабочем процессе: заполнение форм, открытие и сохранение файлов, сортировка электронных писем… список можно продолжать.

Установить pyautogui можно так:

pip install pyautogui


⚙️ Пример 1 — Автоматическое открытие калькулятора и ввод операций:

Представим, что у вас Windows, и вы хотите запустить калькулятор и выполнить в нём простую операцию: ввести «123 + 456». Вот как это можно реализовать (пример под Windows):

import pyautogui
import time
import subprocess

subprocess.Popen("calc.exe") # Запускаем калькулятор
time.sleep(2) # Ждём, пока откроется окно

pyautogui.write('123')
pyautogui.press('+')
pyautogui.write('456')
pyautogui.press('enter')


Удивительно просто, правда? Вы будто нажимаете клавиши сами, но делает это скрипт.

🖱️ Пример 2 — Автокликер:

Вы играете или регулярно работаете с интерфейсом, где нужно часто кликать по определённой области экрана? Не проблема:

import pyautogui
import time

time.sleep(3) # У вас есть 3 секунды, чтобы навести курсор
for i in range(10):
pyautogui.click()
time.sleep(0.5)


Этот скрипт делает 10 кликов мышью с полсекундной задержкой. Особенно удобно, если вам нужно 100 раз подтвердить однотипное действие (например, в старой ERP-системе).

📸 Пример 3 — Поиск элемента на экране:

pyautogui умеет искать изображения на экране — это значит, что вы можете не просто “тыкать в координаты”, а находить кнопки и управлять GUI умно:

import pyautogui
import time

location = pyautogui.locateOnScreen('submit_button.png', confidence=0.8)
if location:
pyautogui.click(location)
else:
print("Button not found!")


Функция locateOnScreen ищет фрагмент изображения на экране. Это даёт гибкость: автоматизация не привязана к жёстким координатам и будет работать даже при сдвиге окон.

🛑 Немного предосторожностей:

- pyautogui не знает, что делает ваша система. Он просто нажимает и кликает.
- Будьте осторожны с автоматическим вводом: можно случайно отправить ненужную почту или удалить файл.
- Хотите резко остановить выполнение? Используйте сочетание клавиш Ctrl + C или установите failsafe:

pyautogui.FAILSAFE = True


Если курсор мыши резко увести в верхний левый угол экрана — выполнение остановится.

⏹️ Заключение

pyautogui — простой путь в мир автоматизации пользовательского интерфейса. Он особенно полезен для начинающих, чтобы понять, «как думает компьютер», и почувствовать силу Python в реальных задачах. Подходит для мелких рутин, ежедневных кликов и даже базового тестирования GUI.

Желаю вам меньше рутинных задач и больше интересных скриптов!
👍4
Как подключаться к REST API и обрабатывать JSON-ответы
Как подключаться к REST API и обрабатывать JSON-ответы
REST API и Python: работаем с JSON как профи

Привет! Сегодня мы окунемся в одну из самых востребованных тем — как с помощью Python подключаться к REST API и работать с JSON-ответами.

В мире, где всё общается со всем через интернет, умение "разговаривать" с другими сервисами через их API — почти что суперсила. Показываю, как включить эту суперсилу.

Начнем с самого популярного инструмента для HTTP-запросов в Python — библиотеки requests.

Установи её, если ещё не установлена:

pip install requests


Теперь — практика. Допустим, ты хочешь получить список фактов о котах (почему бы и нет?). Есть открытое API: https://catfact.ninja

Пример простого GET-запроса:

import requests

url = 'https://catfact.ninja/fact'
response = requests.get(url)

if response.status_code == 200:
data = response.json()
print(f"Random cat fact: {data['fact']}")
else:
print(f"Error: {response.status_code}")


Здесь мы:

1. Отправляем GET-запрос.
2. Получаем результат в формате JSON.
3. Извлекаем нужное поле (fact) и выводим его.

А теперь давай усложним задачу. Есть API, которое возвращает список пользователей: https://jsonplaceholder.typicode.com/users

Получим их и выведем имена:

import requests

url = 'https://jsonplaceholder.typicode.com/users'
response = requests.get(url)

if response.ok:
users = response.json()
for user in users:
print(f"{user['name']} - {user['email']}")
else:
print("Failed to fetch users.")


Как видишь, response.json() — это просто Python-словарь или список. Не нужно парсить вручную, всё уже удобно преобразовано.

Иногда API требует параметры. Пример — получить 5 случайных фактов о котах:

import requests

url = 'https://catfact.ninja/facts'
params = {'limit': 5}
response = requests.get(url, params=params)

if response.ok:
facts = response.json()['data']
for fact in facts:
print(f"- {fact['fact']}")
else:
print("Something went wrong...")


Обращай внимание: параметр params добавляет query string к URL автоматически.

📌 Несколько полезных советов:

- Проверяй response.status_code или response.ok, чтобы понимать, всё ли прошло хорошо.
- Используй try-except вокруг response.json(), если не уверен, что ответ в формате JSON.
- Заголовки (headers) можно передавать через параметр headers, если API требует авторизации или определённого контента.

В следующий раз разберем, как отправлять POST-запросы и авторизовываться через токены. А пока — подключайся к миру REST API, и пусть JSON будет с тобой!
👍2
Введение в модуль collections: где и как использовать deque
Привет! Меня зовут Иван, и сегодня мы заглянем в один из скрытых уголков стандартной библиотеки Python — модуль collections, а точнее, познакомимся с универсальным инструментом deque. Если вы до сих пор используете list там, где нужна очередь или стек — самое время изменить подход!

🔁 Что такое deque?

deque расшифровывается как “double-ended queue” — двусторонняя очередь. Это структура данных, в которую можно эффективно добавлять и удалять элементы как с начала, так и с конца. На практике deque особенно полезна в тех случаях, где list начинает “тормозить”.

Создается просто:

from collections import deque

dq = deque()


По умолчанию deque бесконечен, но можно установить максимальную длину:

dq = deque(maxlen=5)


📌 В чем преимущество deque?

Добавление и удаление с концов deque выполняется за O(1). Для сравнения, у list это O(n) при удалении с начала списка. Почувствуйте разницу, когда работаете с большими объёмами данных.

🧪 Пример 1: реализация очереди

Представим, что мы моделируем очередь из пользователей. С list это будет невыгодно, а вот deque идеально подходит:

from collections import deque

queue = deque()

queue.append("user1")
queue.append("user2")
queue.append("user3")

# Первый зашёл, первый вышел
first_in_line = queue.popleft()
print(first_in_line) # user1


append() — добавить в конец, popleft() — забрать с начала. Идеальная очередь!

🌀 Пример 2: реализация стека

Хочешь стек вместо очереди? Пожалуйста!

stack = deque()

stack.append("task1")
stack.append("task2")

# Последний зашёл, первый вышел
last_task = stack.pop()
print(last_task) # task2


Всё как в классике. append + pop для работы как со стеком.

🔄 Пример 3: ограниченная история (максимальная длина)

Представим историю последних действий пользователя:

history = deque(maxlen=3)

history.append("login")
history.append("view_page")
history.append("edit_profile")
history.append("logout") # login будет удален

print(history) # deque(['view_page', 'edit_profile', 'logout'])


Это очень удобно — не нужно вручную следить за перерасходом памяти.

🚀 Немного магии: вращение

deque умеет вращаться:

items = deque([1, 2, 3, 4])
items.rotate(1)
print(items) # deque([4, 1, 2, 3])

items.rotate(-2)
print(items) # deque([2, 3, 4, 1])


Раз — и вы переместили данные вперед или назад. Применимо, например, к круглым буферам или игровым очередям.

🎯 Когда использовать deque?

- Если нужна очередь или стек — берите deque.
- Если часто работаете с началом списка — deque сэкономит много времени.
- Если нужно ограничить размер структуры — maxlen вам в помощь.

Ну и бонус — deque поддерживает почти все методы list’а: count(), remove(), extend(), но всё работает быстрее за счёт оптимизированного внутреннего устройства.

На этом всё! Надеюсь, deque стал для вас чуть ближе. Он не так популярен, как list, но в своём деле вне конкуренции. Попробуйте его в деле — и не захочется возвращаться.
👍3
Советы по структурированию и организации Python-кода
🧱 Делим и властвуем: как организовать код на Python, чтобы не расползся по углам

Каждому новичку рано или поздно приходится столкнуться с "монстром" — огромным скриптом на 500 строк, в котором логика размазана по всему файлу как масло по бутерброду. Чтобы не оказаться его автором, нужно с самого начала прививать себе привычку писать чисто, читаемо и — главное — структурировано.

🎯 Разделяй задачи

Золотое правило: одна функция — одна задача. Если функция делает и запрос, и обработку, и вывод — бей тревогу. Раздели её на части.

Пример нехорошего подхода:

def process_user_data():
data = get_data_from_api()
cleaned = clean_data(data)
save_to_db(cleaned)


Лучше так:

def fetch_data():
# запрос к API
pass

def clean_data(data):
# обработка данных
pass

def store_data(data):
# сохранение в БД
pass

def main():
data = fetch_data()
cleaned = clean_data(data)
store_data(cleaned)


Такой подход упрощает тестирование, переиспользование и понимание логики.

📦 Разбивай на модули

Если в проекте больше одного файла, используй модули. Группируй код по смыслу: один файл отвечает за работу с базой, другой — за API, третий — за бизнес-логику.

Например:
/project
main.py
db_handler.py
api_client.py
utils.py


В db_handler.py храним функции работы с БД:

def save_user(user_obj):
pass

def get_user_by_id(user_id):
pass


А в api_client.py — всё, что касается внешнего API:

def fetch_posts():
pass

def fetch_comments():
pass


🧰 Не забывай про __init__.py

Если ты оформляешь папку как пакет, добавляй файл __init__.py. Он говорит Python: "это модуль, здесь всё по-взрослому". Даже если он пустой.

📚 Создавай README

Это не шутка. Если даже в небольшом проекте ты сам спустя 2 недели забудешь, как оно работает, представь, каково будет другим. Краткий README.md с описанием структуры проекта и запуском — спасение.

🚨 Защищай точку входа

Магическая конструкция if __name__ == "__main__": спасает от автоматического запуска кода при импорте модуля.

def main():
...

if __name__ == "__main__":
main()


👏 И напоследок

Структура — это скелет проекта. Чем крепче и логичнее он выстроен, тем проще развивать код и находить в нем ошибки. Даже если ты пока пишешь скрипты на 100 строк — начни делать это по-взрослому. И увидишь, как Python перестанет казаться хаотичным — он станет инструментом, где порядок рождает мощь.

На связи,
Иван — программист, который когда-то тоже писал один файл на 800 строк.
👍2
Как получить и обработать данные о погоде с помощью OpenWeatherMap API