Реализация учета товаров с помощью Python

Раздел: Приложения на Python -> Бизнес-приложения

Обзор подходов к созданию программы учета на Python

Наиболее эффективное решение для малого бизнеса или личного использования - консольное приложение с базой данных SQLite. Оно не требует установки сервера, легко переносится и позволяет хранить данные в одном файле. Пример реализации включает инициализацию таблицы, добавление, просмотр и удаление записей.


import sqlite3

def init_db():
    conn = sqlite3.connect('inventory.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS items
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  name TEXT NOT NULL,
                  quantity INTEGER,
                  price REAL)''')
    conn.commit()
    conn.close()

def add_item(name, quantity, price):
    conn = sqlite3.connect('inventory.db')
    c = conn.cursor()
    c.execute("INSERT INTO items (name, quantity, price) VALUES (?,?,?)", (name, quantity, price))
    conn.commit()
    conn.close()

def list_items():
    conn = sqlite3.connect('inventory.db')
    c = conn.cursor()
    for row in c.execute("SELECT * FROM items"):
        print(row)
    conn.close()

Python программа учета (программа учета на python)

Пояснения: функция init_db создает таблицу, если её нет. add_item использует параметризованный запрос для защиты от SQL-инъекций. list_items выводит все строки.

Типичные ошибки: забывают закрывать соединение, что приводит к блокировке файла. Также возможны ошибки при вводе нечисловых данных в поля quantity и price. Решение - использовать обработку исключений try/except и встроенные проверки типов.

Возникающие проблемы: при многопользовательском доступе SQLite может выдавать ошибку 'database is locked'. Рекомендуется использовать WAL-режим или переходить на клиент-серверные СУБД. Ещё одна трудность - миграции схемы данных. Для простых проектов достаточно удалить и создать таблицу заново, но лучше применять библиотеку Alembic.

Как сделать программу учета без базы данных, используя JSON-файлы?

Если нужно быстро прототипировать или не хочется работать с SQL, можно хранить данные в JSON. Файл легко читать и редактировать вручную, но он не поддерживает конкурентный доступ и сложные запросы.


import json

DATA_FILE = 'inventory.json'

def load_data():
    try:
        with open(DATA_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        return []

def save_data(data):
    with open(DATA_FILE, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

def add_item(name, quantity, price):
    data = load_data()
    new_id = max([item['id'] for item in data], default=0) + 1
    data.append({'id': new_id, 'name': name, 'quantity': quantity, 'price': price})
    save_data(data)

Проблемы: при частых записях возможно повреждение файла. Для обеспечения целостности данных лучше использовать временный файл и переименование. JSON не подходит для больших объёмов (более 10-20 тысяч записей) из-за полной загрузки в память.

Ошибки: если файл повреждён, json.load вызовет исключение. Решение - резервное копирование и проверка валидности перед загрузкой.

Как создать оконное приложение учета на Python с Tkinter?

Для пользователей, предпочитающих графический интерфейс, подойдёт Tkinter. Примерный код включает окно со списком и формой добавления.


import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3

class InventoryApp:
    def __init__(self, root):
        self.root = root
        self.root.title('Учет товаров')
        self.tree = ttk.Treeview(root, columns=('name','qty','price'), show='headings')
        self.tree.heading('name', text='Наименование')
        self.tree.heading('qty', text='Количество')
        self.tree.heading('price', text='Цена')
        self.tree.pack(fill=tk.BOTH, expand=True)
        btn_add = tk.Button(root, text='Добавить', command=self.open_add_window)
        btn_add.pack(pady=5)
        self.load_data()
    def load_data(self):
        conn = sqlite3.connect('inventory.db')
        for row in conn.execute('SELECT name, quantity, price FROM items'):
            self.tree.insert('', tk.END, values=row)
        conn.close()
    def open_add_window(self):
        # окно для добавления
        pass

Проблемы: Tkinter требует цикл событий, сложно делать асинхронные операции. Для больших таблиц Treeview становится медленным, рекомендуется использовать виртуальный режим.

Типичная ошибка - забыть обновить виджет после изменения данных. Решение: после каждой операции добавлять метод refresh, очищающий и перезаполняющий Treeview.

Как реализовать учет через веб-интерфейс на Flask?

Для доступа с разных устройств без установки ПО удобно веб-приложение. Основные маршруты: список товаров, форма добавления и удаления.


from flask import Flask, render_template, request, redirect, url_for
import sqlite3

app = Flask(__name__)

@app.route('/')
def index():
    conn = sqlite3.connect('inventory.db')
    items = conn.execute('SELECT * FROM items').fetchall()
    conn.close()
    return render_template('index.html', items=items)

@app.route('/add', methods=['POST'])
def add():
    name = request.form['name']
    qty = int(request.form['quantity'])
    price = float(request.form['price'])
    conn = sqlite3.connect('inventory.db')
    conn.execute('INSERT INTO items (name, quantity, price) VALUES (?,?,?)', (name, qty, price))
    conn.commit()
    conn.close()
    return redirect(url_for('index'))

Проблемы: необходимо настроить сервер, обеспечить безопасность (CSRF, валидация). Для продакшена требуется WSGI-сервер (Gunicorn, uWSGI).

Ошибки: неправильная обработка типов данных из формы, незакрытые соединения приводят к зависанию. Рекомендуется использовать контекстные менеджеры (with).

Расширенные примеры консольного учета с отчетами и фильтрацией

Добавим возможность формировать отчет по сумме товаров на складе и поиск по названию.

Пример

import sqlite3
from datetime import datetime

def get_total_value():
    conn = sqlite3.connect('inventory.db')
    cursor = conn.execute('SELECT SUM(quantity*price) FROM items')
    total = cursor.fetchone()[0] or 0
    conn.close()
    return total

def search_items(keyword):
    conn = sqlite3.connect('inventory.db')
    cursor = conn.execute('SELECT * FROM items WHERE name LIKE ?', (f'%{keyword}%',))
    results = cursor.fetchall()
    conn.close()
    return results

def get_low_stock(threshold=5):
    conn = sqlite3.connect('inventory.db')
    cursor = conn.execute('SELECT * FROM items WHERE quantity < ?', (threshold,))
    results = cursor.fetchall()
    conn.close()
    return results

# Пример вызова:
print('Общая стоимость:', get_total_value())
print('Поиск "мыло":', search_items('мыло'))
print('Товары с остатком менее 5:', get_low_stock())
Общая стоимость: 25430.5
Поиск "мыло": [(1, 'мыло хозяйственное', 10, 50.0), (4, 'мыло жидкое', 3, 120.0)]
Товары с остатком менее 5: [(2, 'зубная паста', 2, 150.0)]

Расширенный пример для Tkinter: добавление графика и экспорт в CSV

В графическом приложении можно отобразить круговую диаграмму по категориям (если добавить поле category). Для упрощения покажем экспорт всех данных в CSV.

Пример

import csv
import sqlite3
from tkinter import filedialog

def export_to_csv():
    filepath = filedialog.asksaveasfilename(defaultextension='.csv')
    if not filepath:
        return
    conn = sqlite3.connect('inventory.db')
    items = conn.execute('SELECT * FROM items').fetchall()
    conn.close()
    with open(filepath, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(['id','name','quantity','price'])
        writer.writerows(items)
    messagebox.showinfo('Экспорт', 'Данные экспортированы')

Расширенный пример для Flask: добавление REST API и сортировки

Реализуем JSON-интерфейс для внешних программ и возможность сортировки товаров по цене.

Пример

from flask import jsonify, request

@app.route('/api/items')
def api_items():
    sort_by = request.args.get('sort', 'name')
    order = request.args.get('order', 'asc')
    allowed_sort = {'name','price','quantity'}
    if sort_by not in allowed_sort:
        sort_by = 'name'
    if order not in ('asc','desc'):
        order = 'asc'
    conn = sqlite3.connect('inventory.db')
    items = conn.execute(f'SELECT * FROM items ORDER BY {sort_by} {order}').fetchall()
    conn.close()
    # преобразовать в список словарей
    result = [{'id':r[0],'name':r[1],'quantity':r[2],'price':r[3]} for r in items]
    return jsonify(result)

Результат вызова GET /api/items?sort=price&order=desc:

[
  {"id": 1, "name": "мыло", "quantity": 10, "price": 50.0},
  {"id": 4, "name": "шампунь", "quantity": 2, "price": 200.0}
]

Программа учета на Python - comments

En
Python программа учета (python)