- Python 100%
| .idea | ||
| app.py | ||
| readme.md | ||
| requirements.txt | ||
| Streamlit-opis | ||
Portfolio Programistyczne w Pythonie
Aplikacja prezentująca kilka różnych zadań programistycznych w Pythonie z wykorzystaniem Streamlit.
Funkcje aplikacji
- Kalkulator - Prosty kalkulator do podstawowych operacji matematycznych
- Chatbot - Prosty chatbot do odpowiedzi na pytania
- Analiza Danych - Przykład analizy danych z wizualizacją
- Generator Haseł - Generator bezpiecznych haseł z różnymi opcjami
Jak uruchomić
-
Sklonuj repozytorium
-
Utwórz wirtualne środowisko:
python -m venv venv -
aktywuj środowisko: venv\Scripts\activate source venv/bin/activate W zależności oczywiście od systemu
-
Zainstaluj zależności: pip install -r requirements.txt
-
Uruchom aplikację: streamlit run app.py
W sumie ciekawym wyzwaniem byłoby rozwinięcie projektu. W związku z tym daję całościowy opis, tutorial:
Tutorial: Aplikacja Portfolio w Streamlit
📋 Spis treści
Wprowadzenie
Ta aplikacja to interaktywne portfolio programistyczne zbudowane w Streamlit - frameworku Pythona do tworzenia aplikacji webowych. Streamlit pozwala szybko tworzyć interfejsy użytkownika bez znajomości HTML/CSS/JavaScript.
Czym jest Streamlit?
- Framework do tworzenia aplikacji webowych w czystym Pythonie
- Automatycznie odświeża aplikację po zmianach w kodzie
- Zawiera gotowe komponenty UI (przyciski, slidery, wykresy)
- Idealny do prototypowania i prezentacji projektów data science
Wymagania
pip install streamlit pandas numpy
Uruchamianie aplikacji
streamlit run nazwa_pliku.py
Struktura aplikacji
🏗️ Architektura
Aplikacja składa się z kilku kluczowych elementów:
┌─────────────────────────────────────┐
│ Konfiguracja strony │
│ (st.set_page_config) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Nagłówek aplikacji │
│ (show_header) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Menu boczne (Sidebar) │
│ - Kalkulator │
│ - Chatbot │
│ - Analiza Danych │
│ - Generator Haseł │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Wybrana sekcja │
│ (funkcja odpowiadająca sekcji) │
└─────────────────────────────────────┘
Szczegółowy opis kodu
1. Konfiguracja strony
st.set_page_config(
page_title="Moje Portfolio Programistyczne",
page_icon="💻",
layout="wide"
)
Co to robi?
page_title- tytuł w zakładce przeglądarkipage_icon- ikona (emoji lub URL do obrazka)layout="wide"- pełna szerokość ekranu (domyślnie:"centered")
Dlaczego to ważne?
- Musi być pierwszym wywołaniem Streamlit w aplikacji
- Ustawia podstawowe parametry wyglądu
- Wpływa na profesjonalny wygląd aplikacji
2. Funkcja nagłówka
def show_header():
st.title("💻 Moje Portfolio Programistyczne")
st.markdown("""
Witaj w moim portfolio programistycznym!
""")
Komponenty Streamlit:
st.title()- główny tytuł (największa czcionka)st.markdown()- formatowany tekst (obsługuje Markdown)
Inne przydatne funkcje tekstowe:
st.header()- nagłówek sekcjist.subheader()- podtytułst.write()- uniwersalna funkcja do wyświetlania treścist.caption()- mały tekst pomocniczy
3. Sekcja Kalkulator
def calculator_section():
col1, col2 = st.columns(2)
Kluczowe elementy:
Layout w kolumnach
col1, col2 = st.columns(2) # Dwie równe kolumny
# lub
col1, col2, col3 = st.columns([2, 1, 1]) # Kolumny o różnych szerokościach
Komponenty wejściowe
num1 = st.number_input("Pierwsza liczba", value=0.0)
operation = st.selectbox("Operacja", ["Dodawanie", "Odejmowanie"])
Dostępne komponenty:
st.number_input()- pole liczbowest.text_input()- pole tekstowest.selectbox()- lista rozwijanast.multiselect()- wielokrotny wybórst.slider()- suwakst.checkbox()- pole wyborust.radio()- przyciski radio
Przyciski i akcje
if st.button("Oblicz"):
# kod wykonywany po kliknięciu
Ważne: Kod wewnątrz if st.button() wykonuje się tylko gdy przycisk jest kliknięty.
Wyświetlanie komunikatów
st.success("Wynik: 42") # Zielony komunikat sukcesu
st.error("Błąd!") # Czerwony komunikat błędu
st.warning("Uwaga!") # Żółty komunikat ostrzeżenia
st.info("Informacja") # Niebieski komunikat informacyjny
4. Sekcja Chatbot
if 'chat_history' not in st.session_state:
st.session_state.chat_history = []
Co to jest st.session_state?
- Przechowuje dane między kolejnymi uruchomieniami skryptu
- Streamlit wykonuje cały kod od nowa przy każdej interakcji
session_statepozwala zachować stan aplikacji (np. historię czatu)
Przykład użycia:
# Inicjalizacja
if 'counter' not in st.session_state:
st.session_state.counter = 0
# Modyfikacja
if st.button("Zwiększ"):
st.session_state.counter += 1
# Wyświetlanie
st.write(f"Licznik: {st.session_state.counter}")
Interfejs czatu
if prompt := st.chat_input("Napisz coś..."):
# prompt zawiera wiadomość użytkownika
Operator walrus := - przypisuje wartość i zwraca ją jednocześnie.
Wyświetlanie wiadomości
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
st.markdown(response)
Role wiadomości:
"user"- wiadomość użytkownika (prawa strona)"assistant"- odpowiedź bota (lewa strona)
Efekt pisania
message_placeholder = st.empty()
for chunk in response.split():
full_response += chunk + " "
time.sleep(0.05)
message_placeholder.markdown(full_response + "▌")
st.empty() - tworzy kontener, który można dynamicznie aktualizować.
5. Sekcja Analiza Danych
data = pd.DataFrame({
'Data': pd.date_range(start='2023-01-01', periods=100),
'Wartość': np.random.randn(100).cumsum()
})
Wyświetlanie danych
st.dataframe(data.head(10)) # Interaktywna tabela
# lub
st.table(data.head(10)) # Statyczna tabela
Różnica:
st.dataframe()- scrollowanie, sortowanie, pełnoekranowy widokst.table()- prosty, statyczny wyświetlacz
Wykresy
st.line_chart(data, x='Data', y='Wartość')
st.bar_chart(data, x='Kategoria', y='Wartość')
st.scatter_chart(data, x='Data', y='Wartość')
Dostępne wykresy natywne:
st.line_chart()- wykres liniowyst.bar_chart()- wykres słupkowyst.area_chart()- wykres obszarowyst.scatter_chart()- wykres punktowy
Zaawansowane wykresy:
import plotly.express as px
fig = px.line(data, x='Data', y='Wartość', title='Mój wykres')
st.plotly_chart(fig)
Filtrowanie danych
min_date = st.date_input("Data początkowa", data['Data'].min())
filtered_data = data[data['Data'] >= pd.to_datetime(min_date)]
st.date_input() - wybierak daty z kalendarzem.
6. Sekcja Generator Haseł
length = st.slider("Długość hasła", min_value=8, max_value=32, value=12)
use_uppercase = st.checkbox("Użyj dużych liter", value=True)
Generowanie hasła
chars = "abcdefghijklmnopqrstuvwxyz"
if use_uppercase:
chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
password = ''.join(np.random.choice(list(chars), size=length))
Wyświetlanie kodu
st.code(password) # Blok kodu z możliwością kopiowania
7. Menu boczne (Sidebar)
with st.sidebar:
st.header("Menu")
section = st.radio("Wybierz sekcję:", ["Kalkulator", "Chatbot"])
st.sidebar - wszystko wewnątrz bloku with st.sidebar: pojawia się w bocznym panelu.
Alternatywna składnia:
section = st.sidebar.radio("Wybierz sekcję:", [...])
8. Logika routingu
if section == "Kalkulator":
calculator_section()
elif section == "Chatbot":
chatbot_section()
Jak to działa?
- Użytkownik wybiera opcję w
st.radio() - Wartość zapisuje się w zmiennej
section - Odpowiednia funkcja sekcji jest wywoływana
- Tylko wybrana sekcja jest renderowana
Jak rozwijać aplikację
💡 Pomysły na nowe sekcje
1. To-Do List
def todo_section():
st.header("📝 Lista zadań")
if 'todos' not in st.session_state:
st.session_state.todos = []
new_todo = st.text_input("Nowe zadanie")
if st.button("Dodaj"):
st.session_state.todos.append({"task": new_todo, "done": False})
for i, todo in enumerate(st.session_state.todos):
col1, col2 = st.columns([4, 1])
with col1:
done = st.checkbox(todo["task"], key=f"todo_{i}", value=todo["done"])
st.session_state.todos[i]["done"] = done
with col2:
if st.button("Usuń", key=f"del_{i}"):
st.session_state.todos.pop(i)
st.rerun()
2. Konwerter jednostek
def converter_section():
st.header("🔄 Konwerter jednostek")
conversion_type = st.selectbox("Typ konwersji",
["Temperatura", "Długość", "Waga"])
if conversion_type == "Temperatura":
value = st.number_input("Wartość")
from_unit = st.selectbox("Z:", ["Celsius", "Fahrenheit", "Kelvin"])
to_unit = st.selectbox("Na:", ["Celsius", "Fahrenheit", "Kelvin"])
# Logika konwersji...
3. Timer/Stoper
def timer_section():
st.header("⏱️ Timer")
if 'start_time' not in st.session_state:
st.session_state.start_time = None
col1, col2 = st.columns(2)
with col1:
if st.button("Start"):
st.session_state.start_time = time.time()
with col2:
if st.button("Stop"):
st.session_state.start_time = None
if st.session_state.start_time:
elapsed = time.time() - st.session_state.start_time
st.metric("Czas", f"{elapsed:.2f}s")
time.sleep(0.1)
st.rerun()
4. Wczytywanie plików
def file_upload_section():
st.header("📂 Analiza pliku CSV")
uploaded_file = st.file_uploader("Wybierz plik CSV", type=['csv'])
if uploaded_file is not None:
df = pd.read_csv(uploaded_file)
st.dataframe(df)
st.line_chart(df)
5. Kalkulator BMI
def bmi_calculator():
st.header("⚖️ Kalkulator BMI")
col1, col2 = st.columns(2)
with col1:
weight = st.number_input("Waga (kg)", min_value=1.0, value=70.0)
with col2:
height = st.number_input("Wzrost (cm)", min_value=1.0, value=170.0)
if st.button("Oblicz BMI"):
bmi = weight / ((height/100) ** 2)
st.metric("Twoje BMI", f"{bmi:.2f}")
if bmi < 18.5:
st.info("Niedowaga")
elif bmi < 25:
st.success("Waga prawidłowa")
elif bmi < 30:
st.warning("Nadwaga")
else:
st.error("Otyłość")
🎨 Ulepszenia wizualne
1. Motywy kolorystyczne
# W pliku .streamlit/config.toml
[theme]
primaryColor="#FF4B4B"
backgroundColor="#0E1117"
secondaryBackgroundColor="#262730"
textColor="#FAFAFA"
font="sans serif"
2. Własne style CSS
st.markdown("""
<style>
.big-font {
font-size: 30px !important;
font-weight: bold;
}
</style>
""", unsafe_allow_html=True)
st.markdown('<p class="big-font">Duży tekst!</p>', unsafe_allow_html=True)
3. Ikony i emotikony
st.header("📊 Statystyki")
st.metric("Użytkownicy 👥", "1,234", "+12%")
st.metric("Sprzedaż 💰", "5,678 zł", "+23%")
4. Karty informacyjne
col1, col2, col3 = st.columns(3)
with col1:
st.info("ℹ️ Informacja")
with col2:
st.success("✅ Sukces")
with col3:
st.warning("⚠️ Uwaga")
🚀 Zaawansowane funkcje
1. Pasek postępu
progress_bar = st.progress(0)
for i in range(100):
time.sleep(0.01)
progress_bar.progress(i + 1)
st.success("Gotowe!")
2. Spinner podczas ładowania
with st.spinner("Przetwarzam dane..."):
time.sleep(3) # Symulacja długiej operacji
st.success("Gotowe!")
3. Expandery (rozwijane sekcje)
with st.expander("Kliknij, aby rozwinąć"):
st.write("Ukryta treść")
st.image("obraz.jpg")
4. Zakładki (tabs)
tab1, tab2, tab3 = st.tabs(["📈 Wykres", "📊 Dane", "🔍 Info"])
with tab1:
st.line_chart(data)
with tab2:
st.dataframe(data)
with tab3:
st.write("Informacje o danych")
5. Formularze
with st.form("my_form"):
name = st.text_input("Imię")
age = st.number_input("Wiek", min_value=0)
submitted = st.form_submit_button("Wyślij")
if submitted:
st.write(f"Witaj, {name}! Masz {age} lat.")
Dlaczego formularze?
- Zbierają wszystkie dane przed wysłaniem
- Tylko jeden przycisk "Submit" odświeża aplikację
- Lepsza wydajność przy wielu polach
6. Cachowanie danych
@st.cache_data # Dla danych (DataFrame, listy)
def load_data():
# Długa operacja wczytywania
return pd.read_csv("large_file.csv")
@st.cache_resource # Dla obiektów (połączenia DB, modele ML)
def load_model():
return load_ml_model()
# Dane wczytają się tylko raz!
data = load_data()
📦 Integracja z zewnętrznymi API
Przykład: API pogodowe
import requests
def weather_section():
st.header("🌤️ Pogoda")
city = st.text_input("Miasto", "Warszawa")
if st.button("Sprawdź pogodę"):
api_key = "TWOJ_KLUCZ_API"
url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
temp = data['main']['temp']
desc = data['weather'][0]['description']
col1, col2 = st.columns(2)
with col1:
st.metric("Temperatura", f"{temp}°C")
with col2:
st.write(f"Opis: {desc}")
else:
st.error("Nie udało się pobrać danych")
💾 Zapisywanie i wczytywanie danych
1. JSON
import json
# Zapisywanie
def save_data():
with open('data.json', 'w') as f:
json.dump(st.session_state.todos, f)
# Wczytywanie
def load_data():
try:
with open('data.json', 'r') as f:
st.session_state.todos = json.load(f)
except FileNotFoundError:
st.session_state.todos = []
2. CSV
# Eksport do CSV
@st.cache_data
def convert_df_to_csv(df):
return df.to_csv(index=False).encode('utf-8')
csv = convert_df_to_csv(data)
st.download_button(
label="📥 Pobierz CSV",
data=csv,
file_name='dane.csv',
mime='text/csv'
)
Najlepsze praktyki
✅ Do zrobienia
-
Używaj
session_statedla stanówif 'counter' not in st.session_state: st.session_state.counter = 0 -
Cachuj kosztowne operacje
@st.cache_data def expensive_computation(): # ... -
Organizuj kod w funkcje
def section_name(): st.header("Tytuł") # logika sekcji -
Waliduj dane wejściowe
if num2 != 0: result = num1 / num2 else: st.error("Nie można dzielić przez zero!") -
Używaj
st.columns()dla layoutucol1, col2 = st.columns(2)
❌ Czego unikać
-
Nie umieszczaj
st.set_page_config()w środku kodu- Musi być na początku!
-
Nie używaj zmiennych globalnych bez
session_state# ❌ ŹLE counter = 0 if st.button("+"): counter += 1 # Nie zadziała! # ✅ DOBRZE if 'counter' not in st.session_state: st.session_state.counter = 0 if st.button("+"): st.session_state.counter += 1 -
Nie wykonuj ciężkich operacji bez cachowania
# ❌ ŹLE - wczyta plik przy każdej interakcji data = pd.read_csv("huge_file.csv") # ✅ DOBRZE @st.cache_data def load_data(): return pd.read_csv("huge_file.csv") -
Nie twórz nieskończonych pętli z
st.rerun()# ❌ ŹLE while True: st.rerun() # Zawiesi aplikację!
Deployment (wdrożenie)
Streamlit Cloud (za darmo!)
- Wypchnij kod na GitHub
- Wejdź na share.streamlit.io
- Połącz z repo GitHub
- Kliknij "Deploy"
Wymagania
Stwórz plik requirements.txt:
streamlit
pandas
numpy
Podsumowanie
Kluczowe koncepty:
- 🔄 Reactive model - aplikacja uruchamia się od nowa przy każdej interakcji
- 💾 Session State - zachowywanie danych między uruchomieniami
- 📦 Komponenty - gotowe elementy UI (przyciski, wykresy, etc.)
- ⚡ Cachowanie - optymalizacja wydajności
Kolejne kroki:
- Eksperymentuj z różnymi komponentami
- Dodaj własne sekcje
- Połącz z API lub bazą danych
- Wdroż na Streamlit Cloud
- Podziel się swoim projektem!
Przydatne zasoby:
Powodzenia w tworzeniu aplikacji! 🚀