python
print(“З Новим Роком!”)
Привіт усім!
Ласкаво просимо назад до ще одного челенджу з хмарних технологій / DevOps! Я ТАК радий почати цей 30-денний хмарний челендж від LinkedIn, щоб ще більше розширити свою базу знань та портфоліо.
Цей проект буде розділений на кілька частин, кожна з яких буде будуватися на попередній.
Мета: Сьогодні я створюю трекер погоди, який зберігає свої дані в S3. Для відстеження погоди я буду використовувати сайт під назвою “Openweathermap.org”.
У мене вже є обліковий запис AWS і налаштоване середовище у VsCode.
Почнемо!
Отже, перше, що я зроблю — створю файли та директорії, щоб усе було належно організовано та підписано.
Директорія, в якій я працюватиму, називатиметься GetYouAJob
, а всередині цієї директорії я створю ще одну під назвою weather-dashboard-demo
. Всередині цієї директорії я зроблю ще одну підкатегорію під назвою src
для мого вихідного коду, tests
для даних, які я тестуватиму в майбутніх частинах цього проекту, і data
для даних, які будуть використовуватись як локальне сховище для тестування під час розробки.
Я також створю файл __init__.py
, який зробить директорію src
пакетом Python, що дозволить мені імпортувати різні файли та модулі з цієї директорії.
Файли, які я створю, це weather_dashboard.py
, щоб зберігати фактичний код, та requirements.txt
, щоб зберігати мої залежності. Також я створю файл .env
, щоб зберігати змінні середовища для кращої безпеки моїх облікових даних.
Команди:
mkdir weather-dashboard-demo
cd weather-dashboard-demo
mkdir src tests data
touch src/__init__.py src/weather_dashboard.py
Далі я додам дані в кожну директорію та файли відповідно.
Для файлу requirements.txt я додам такі залежності: boto3==1.26.137
, python-dotenv==1.0.0
, requests==2.28.2
, використовуючи команду echo:
echo "boto3==1.26.137" >> requirements.txt
echo "python-dotenv==1.0.0" >> requirements.txt
echo "requests==2.28.2" >> requirements.txt
Boto3 — це набір інструментів для розробки, який використовується для взаємодії з ресурсами AWS. Python-dotenv використовується для зчитування змінних з файлу .env
та додавання їх до середовища. В основному, він полегшує керування секретами, обліковими даними та конфігураціями без необхідності хардкодити їх у коді (робить це більш безпечним).
Залежність requests дозволяє коду виконувати HTTP-запити, обробляти дані відповіді та полегшує роботу з API та веб-сервісами.
Виправлення помилок: Коли я працював над цим проектом і намагався встановити залежності з файлу requirements.txt, у мене виникла проблема, де було написано, що "python не знайдений, запустіть без аргументів, щоб встановити з налаштувань Microsoft"
(я намагався встановити pip, але не зрозумів, що Python ще не було встановлено), тому я встановив Python, а потім встановив менеджер пакетів pip:
Тепер, коли Python встановлено, я можу встановити менеджер пакетів за допомогою:
python -m ensurepip --upgrade
і встановити мої залежності за допомогою:
pip install -r requirements.txt
Ура, все встановлено!
Менеджер пакетів pip використовується для встановлення залежностей та додавання зовнішніх бібліотек, таких як python-dotenv
або requests
, необхідних для мого коду.
Файл requirements.txt
потрібен, щоб інші могли відтворити моє середовище за допомогою команди pip install -r requirements.txt
.
Навіть із встановленим Python, pip гарантує, що я можу розширити функціональність за допомогою додаткових інструментів та бібліотек.
Далі я перенаправлю файли, які хочу ігнорувати, до файлу .gitignore
.
text
Файл .gitignore вказує git ігнорувати файли або директорії, які містяться всередині, щоб все, що в ньому, залишалося приватним, безпечним, не відслідковуваним і не відправлялося в віддалений репозиторій.
text
Я поклав свій .env файл, pycache/ папку та файли з розширенням **.zip* туди.
Файл .env містить мої облікові дані для середовища, папка pycache/ зберігає скомпільовані Python файли (.pyc
файли), щоб пришвидшити виконання програми, а файл з розширенням **.zip* зберігає кілька файлів і директорій в одному — стиснувши їх, щоб було зручніше зберігати... ці файли можуть бути досить великими, тому я додам їх до файлу .gitignore.
Команди:
echo ".env" >> .gitignore
echo "__pycache__/" >> .gitignore
echo "*.zip" >> gitignore
Тепер я перейду на сайт Open Weather Map, щоб створити обліковий запис і згенерувати свої облікові дані для API.
Далі я додам свої облікові дані до файлу .env:
Примітка: Це чутливі дані, тому, якщо ви вирішите повторити цей проєкт, обов'язково не діліться ними у своїх скріншотах.
Тепер я додам свій код до файлу weather_dashboard.py.
Ось код, який я використав:
import os
import json
import boto3
import requests
from datetime import datetime
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
class WeatherDashboard:
def __init__(self):
self.api_key = os.getenv('OPEN_WEATHER_API_KEY')
self.bucket_name = os.getenv('AWS_BUCKET_NAME')
self.s3_client = boto3.client('s3')
def create_bucket_if_not_exists(self):
"""Create S3 bucket if it doesn't exist"""
try:
# Simpler creation for us-east-1
print(f"Creating bucket {self.bucket_name}")
self.s3_client.create_bucket(Bucket=self.bucket_name)
print(f"Successfully created bucket {self.bucket_name}")
except NoCredentialsError:
print('Error: No AWS credentials found.')
except Exception as e:
print(f"Error creating bucket: {e}")
def fetch_weather(self, city):
"""Fetch weather data from OpenWeather API"""
base_url = "http://api.openweathermap.org/data/2.5/weather"
params = {
'q': city,
'appid': os.getenv('OPEN_WEATHER_API_KEY')
}
try:
response = requests.get(base_url, params=params)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching weather data: {e}")
return None
def save_to_s3(self, weather_data, city):
"""Save weather data to S3 bucket"""
if not weather_data:
return False
timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
file_name = f"weather-data/{city}-{timestamp}.json"
try:
weather_data['timestamp'] = timestamp
self.s3_client.put_object(
Bucket=self.bucket_name,
Key=file_name,
Body=json.dumps(weather_data),
ContentType='application/json'
)
print(f"Successfully saved data for {city} to S3")
return True
except Exception as e:
print(f"Error saving to S3: {e}")
return False
def main():
dashboard = WeatherDashboard()
# Create bucket if one doesn't exist
dashboard.create_bucket_if_not_exists()
cities = ["Philadelphia", "Seattle", "New York"]
for city in cities:
weather_data = dashboard.fetch_weather(city)
if weather_data:
print(f"Conditions: {weather_data.get('weather', [{}])[0].get('description', 'No data')}")
# Saves data to S3
dashboard.save_to_s3(weather_data, city)
success = dashboard.save_to_s3(weather_data, city)
if success:
print(f"Weather data for {city} saved to S3!")
else:
print(f"Failed to fetch weather data for {city}")
if __name__ == "__main__":
main()
def save_to_s3(self, weather_data, city):
"""Save weather data to S3 bucket"""
if not weather_data:
return False
# Create a timestamp for the filename
timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
file_name = f"weather-data/{city}-{timestamp}.json"
try:
# Add timestamp to the data
weather_data['timestamp'] = timestamp
text
# Завантаження на S3
self.s3_client.put_object(
Bucket=self.bucket_name,
Key=file_name,
Body=json.dumps(weather_data),
ContentType='application/json'
)
print(f"Дані для {city} успішно збережено на S3")
return True
except Exception as e:
print(f"Помилка при збереженні на S3: {e}")
return False
main()
Я спробую пояснити це поступово.
Цей перший блок коду використовується для імпорту різних модулів, щоб я міг використовувати більше функціональностей Python, бібліотек та можливостей у своєму проєкті.
import os
: Дозволяє взаємодіяти з операційною системою (наприклад, з шляхами до файлів, змінними середовища).import json
: Дозволяє працювати з даними у форматі JSON.import boto3
: Дозволяє доступ до AWS сервісів, таких як S3.import requests
: Допомагає надсилати HTTP запити для отримання даних з вебсайтів, таких як Weather Map.from datetime import datetime
: Надання інструментів для роботи з датами та часом.from dotenv import load_dotenv
: Завантажує змінні з файлу.env
для безпечної конфігурації.
Ця частина коду завантажує змінні середовища для погодного API, присвоює значення правильним атрибутам, зчитує API-ключ, зчитує назву S3 бакету, а потім створює з'єднання з S3:
Це створює S3 бакет, якщо він не існує, і виводить повідомлення про успіх або помилку, залежно від того, що відбувається в блоці try:
Цей код отримує погоду з вебсайту Open Weather Map, повертає дані для міст, зазначених у функції main, використовує API-ключ для авторизації запиту до вебсайту та виводить помилку, якщо виникла проблема:
Цей код завантажує дані на S3 з часовою міткою, створює унікальне ім’я для файлу з часом і містом, а потім виводить результати успішного збереження, якщо немає помилок:
Цей блок коду створює об'єкт WeatherDashboard, перевіряє, чи існує S3 бакет, перебирає список міст (["Philadelphia", "Seattle", "New York"]
), отримує та зберігає дані про погоду, виводить поточну погоду і зберігає дані на S3 бакет — фактично викликається функція для запуску всього процесу.
І останнє, але не менш важливе, name == "main" дозволяє коду виконуватись лише при безпосередньому запуску:
Я виконаю команду weather_dashboard.py
:
Я перевіряю консоль, щоб переконатись, що все було створено правильно:
Здається, що дані про погоду були успішно збережені в бакеті для Нью-Йорка, Філадельфії та Сіетла!
Тепер я можу зробити коміт і відправити свій код на git:
Успішно відправлено на git!
text
Це завершення #DevOpsAllStarChallenge!
До наступного разу — залишайтеся з нами для наступної частини!!
Посилання на GitHub : https://github.com/brianarorie/30daydevopschallenge.git
Перекладено з: Creating An API To Fetch Data From A Weather App & Storing It To S3