mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-16 15:40:12 +01:00
Adjusted logging across the files
This commit is contained in:
parent
1c7436f33d
commit
76277f876c
12 changed files with 228 additions and 160 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -2,7 +2,12 @@
|
|||
*.json
|
||||
*.log
|
||||
*.txt
|
||||
!requirements.txt
|
||||
test.py
|
||||
.mypy_cache/
|
||||
__pycache__/
|
||||
test.py
|
||||
main.spec
|
||||
!requirements.txt
|
||||
__pycache__/
|
||||
build/
|
||||
csv_files/
|
||||
dist/
|
||||
logs/
|
||||
|
|
@ -29,6 +29,7 @@ Typical usage example:
|
|||
# Standard library imports
|
||||
import functools
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast
|
||||
|
||||
|
|
@ -72,12 +73,35 @@ from settings import (
|
|||
)
|
||||
from type_definitions import CardLibraryDF, CommanderDF, LandDF
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
# Create logs directory if it doesn't exist
|
||||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/builder_utils.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
# Type variables for generic functions
|
||||
T = TypeVar('T')
|
||||
DataFrame = TypeVar('DataFrame', bound=pd.DataFrame)
|
||||
|
|
|
|||
44
card_info.py
44
card_info.py
|
|
@ -1,44 +0,0 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import inquirer.prompt # type: ignore
|
||||
import pandas as pd # type: ignore
|
||||
import pprint
|
||||
|
||||
from fuzzywuzzy import fuzz, process # type: ignore
|
||||
from IPython.display import display
|
||||
|
||||
pd.set_option('display.max_colwidth', None)
|
||||
pd.set_option('display.expand_frame_repr', True)
|
||||
pd.options.mode.chained_assignment = None
|
||||
|
||||
def get_card_info():
|
||||
question = [
|
||||
inquirer.Text(
|
||||
'card_prompt',
|
||||
message='Enter a card name:'
|
||||
)
|
||||
]
|
||||
answer = inquirer.prompt(question)
|
||||
card_choice = answer['card_prompt']
|
||||
|
||||
df = pd.read_csv('csv_files/cards.csv', low_memory=False)
|
||||
fuzzy_card_choice = process.extractOne(card_choice, df['name'], scorer=fuzz.ratio)
|
||||
fuzzy_card_choice = fuzzy_card_choice[0]
|
||||
filtered_df = df[df['name'] == fuzzy_card_choice]
|
||||
columns_to_keep = ['name', 'colorIdentity', 'colors', 'manaCost', 'manaValue', 'type', 'keywords', 'power', 'toughness', 'text']
|
||||
filtered_df = filtered_df[filtered_df['layout'].str.contains('reversible_card') == False]
|
||||
filtered_df = filtered_df[filtered_df['availability'].str.contains('arena') == False]
|
||||
filtered_df.drop_duplicates(subset='name', keep='first', inplace=True)
|
||||
filtered_df = filtered_df[columns_to_keep].astype('string')
|
||||
columns_to_keep = ['name', 'colorIdentity', 'colors', 'manaCost', 'manaValue', 'type', 'keywords', 'power', 'toughness']
|
||||
filtered_df_no_text = filtered_df[columns_to_keep]
|
||||
filtered_df_no_text.dropna(how='all', axis=1, inplace=True)
|
||||
df_dict = filtered_df.to_dict('list')
|
||||
|
||||
pprint.pprint(df_dict, sort_dicts=False)
|
||||
|
||||
|
||||
pprint.pprint(filtered_df_no_text)
|
||||
pprint.pprint(filtered_df['text'])
|
||||
|
||||
#get_card_info()
|
||||
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
import logging
|
||||
import math
|
||||
import numpy as np
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
from functools import lru_cache
|
||||
|
|
@ -20,7 +21,7 @@ from settings import (
|
|||
COMMANDER_CSV_PATH, FUZZY_MATCH_THRESHOLD, MAX_FUZZY_CHOICES, FETCH_LAND_DEFAULT_COUNT,
|
||||
COMMANDER_POWER_DEFAULT, COMMANDER_TOUGHNESS_DEFAULT, COMMANDER_MANA_COST_DEFAULT,
|
||||
COMMANDER_MANA_VALUE_DEFAULT, COMMANDER_TYPE_DEFAULT, COMMANDER_TEXT_DEFAULT,
|
||||
THEME_PRIORITY_BONUS, THEME_POOL_SIZE_MULTIPLIER,
|
||||
THEME_PRIORITY_BONUS, THEME_POOL_SIZE_MULTIPLIER, DECK_DIRECTORY,
|
||||
COMMANDER_COLOR_IDENTITY_DEFAULT, COMMANDER_COLORS_DEFAULT, COMMANDER_TAGS_DEFAULT,
|
||||
COMMANDER_THEMES_DEFAULT, COMMANDER_CREATURE_TYPES_DEFAULT, DUAL_LAND_TYPE_MAP,
|
||||
CSV_READ_TIMEOUT, CSV_PROCESSING_BATCH_SIZE, CSV_VALIDATION_RULES, CSV_REQUIRED_COLUMNS,
|
||||
|
|
@ -89,12 +90,34 @@ except ImportError:
|
|||
logging.warning("Scrython is not installed. Price checking features will be unavailable."
|
||||
)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
# Create logs directory if it doesn't exist
|
||||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/deck_builder.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
pd.set_option('display.max_columns', None)
|
||||
pd.set_option('display.max_rows', None)
|
||||
|
|
@ -480,9 +503,7 @@ class DeckBuilder:
|
|||
self.fill_out_deck()
|
||||
|
||||
# Process and organize deck
|
||||
self.card_library.to_csv(f'{CSV_DIRECTORY}/test_deck_presort.csv', index=False)
|
||||
self.organize_library()
|
||||
self.card_library.to_csv(f'{CSV_DIRECTORY}/test_deck_preconcat.csv', index=False)
|
||||
|
||||
# Log deck composition
|
||||
self._log_deck_composition()
|
||||
|
|
@ -496,8 +517,9 @@ class DeckBuilder:
|
|||
self.commander_to_top()
|
||||
|
||||
# Save final deck
|
||||
self.card_library.to_csv(f'{CSV_DIRECTORY}/test_deck_done.csv', index=False)
|
||||
self.full_df.to_csv(f'{CSV_DIRECTORY}/test_all_after_done.csv', index=False)
|
||||
FILE_TIME = time.strftime("%Y%m%d-%H%M%S")
|
||||
DECK_FILE = f'{self.commander}_{FILE_TIME}.csv'
|
||||
self.card_library.to_csv(f'{DECK_DIRECTORY}/{DECK_FILE}', index=False)
|
||||
|
||||
except Exception as e:
|
||||
raise DeckBuilderError(f"Failed to initialize deck building: {str(e)}")
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, List, Optional, Tuple, Union
|
||||
|
||||
import inquirer.prompt
|
||||
|
|
@ -28,13 +29,35 @@ from exceptions import (
|
|||
PriceValidationError
|
||||
)
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
# Create logs directory if it doesn't exist
|
||||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/input_handler.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
|
||||
class InputHandler:
|
||||
"""Handles user input operations with validation and error handling.
|
||||
|
|
|
|||
47
main.py
47
main.py
|
|
@ -1,3 +1,10 @@
|
|||
"""Command-line interface for the MTG Python Deckbuilder application.
|
||||
|
||||
This module provides the main menu and user interaction functionality for the
|
||||
MTG Python Deckbuilder. It handles menu display, user input processing, and
|
||||
routing to different application features like setup, deck building, card info
|
||||
lookup and CSV file tagging.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
# Standard library imports
|
||||
|
|
@ -15,26 +22,34 @@ import deck_builder
|
|||
import setup
|
||||
import tagger
|
||||
|
||||
"""Command-line interface for the MTG Python Deckbuilder application.
|
||||
|
||||
This module provides the main menu and user interaction functionality for the
|
||||
MTG Python Deckbuilder. It handles menu display, user input processing, and
|
||||
routing to different application features like setup, deck building, card info
|
||||
lookup and CSV file tagging.
|
||||
"""
|
||||
# Create logs directory if it doesn't exist
|
||||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler(),
|
||||
logging.FileHandler('logs/main.log', mode='a', encoding='utf-8')
|
||||
]
|
||||
)
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = os.path.join(LOG_DIR, 'main.log')
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
# Menu constants
|
||||
MENU_SETUP = 'Setup'
|
||||
|
|
@ -93,6 +108,8 @@ def run_menu() -> NoReturn:
|
|||
"""
|
||||
logger.info("Starting MTG Python Deckbuilder")
|
||||
Path('csv_files').mkdir(parents=True, exist_ok=True)
|
||||
Path('deck_files').mkdir(parents=True, exist_ok=True)
|
||||
Path('logs').mkdir(parents=True, exist_ok=True)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
|
|
|||
44
main.spec
44
main.spec
|
|
@ -1,44 +0,0 @@
|
|||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['C:\\Users\\Matt\\mtg_python\\mtg_python_deckbuilder\\main.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='main',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='main',
|
||||
)
|
||||
|
|
@ -36,6 +36,31 @@ from settings import (
|
|||
)
|
||||
from type_definitions import PriceCache
|
||||
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/price_check.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
class PriceChecker:
|
||||
"""Class for handling MTG card price checking and validation.
|
||||
|
||||
|
|
@ -64,12 +89,6 @@ class PriceChecker:
|
|||
self.max_card_price: float = max_card_price
|
||||
self.max_deck_price: float = max_deck_price
|
||||
self.current_deck_price: float = 0.0
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
@lru_cache(maxsize=PRICE_CACHE_SIZE)
|
||||
def get_card_price(self, card_name: str, attempts: int = 0) -> float:
|
||||
|
|
@ -116,7 +135,7 @@ class PriceChecker:
|
|||
|
||||
except scrython.foundation.ScryfallError as e:
|
||||
if attempts < MAX_PRICE_CHECK_ATTEMPTS:
|
||||
logging.warning(f"Retrying price check for {card_name} (attempt {attempts + 1})")
|
||||
logger.warning(f"Retrying price check for {card_name} (attempt {attempts + 1})")
|
||||
return self.get_card_price(card_name, attempts + 1)
|
||||
raise PriceAPIError(card_name, {"error": str(e)})
|
||||
|
||||
|
|
@ -125,7 +144,7 @@ class PriceChecker:
|
|||
|
||||
except Exception as e:
|
||||
if attempts < MAX_PRICE_CHECK_ATTEMPTS:
|
||||
logging.warning(f"Unexpected error checking price for {card_name}, retrying")
|
||||
logger.warning(f"Unexpected error checking price for {card_name}, retrying")
|
||||
return self.get_card_price(card_name, attempts + 1)
|
||||
raise PriceAPIError(card_name, {"error": str(e)})
|
||||
|
||||
|
|
@ -184,10 +203,10 @@ class PriceChecker:
|
|||
results[card_name] = price
|
||||
except Exception as e:
|
||||
errors.append((card_name, e))
|
||||
logging.error(f"Error checking price for {card_name}: {e}")
|
||||
logger.error(f"Error checking price for {card_name}: {e}")
|
||||
|
||||
if errors:
|
||||
logging.warning(f"Failed to get prices for {len(errors)} cards")
|
||||
logger.warning(f"Failed to get prices for {len(errors)} cards")
|
||||
|
||||
return results
|
||||
|
||||
|
|
@ -198,10 +217,10 @@ class PriceChecker:
|
|||
price: Price to add to current deck total
|
||||
"""
|
||||
self.current_deck_price += price
|
||||
logging.debug(f"Updated deck price to ${self.current_deck_price:.2f}")
|
||||
logger.debug(f"Updated deck price to ${self.current_deck_price:.2f}")
|
||||
|
||||
def clear_cache(self) -> None:
|
||||
"""Clear the price cache."""
|
||||
self.price_cache.clear()
|
||||
self.get_card_price.cache_clear()
|
||||
logging.info("Price cache cleared")
|
||||
logger.info("Price cache cleared")
|
||||
|
|
@ -788,6 +788,7 @@ TYPE_TAG_MAPPING = {
|
|||
}
|
||||
|
||||
CSV_DIRECTORY = 'csv_files'
|
||||
DECK_DIRECTORY = 'deck_files'
|
||||
|
||||
# Color identity constants and mappings
|
||||
|
||||
|
|
|
|||
31
setup.py
31
setup.py
|
|
@ -54,15 +54,30 @@ from exceptions import (
|
|||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler(),
|
||||
logging.FileHandler('logs/setup.log', mode='w', encoding='utf-8')
|
||||
]
|
||||
)
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/setup.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
def check_csv_exists(file_path: Union[str, Path]) -> bool:
|
||||
"""Check if a CSV file exists at the specified path.
|
||||
|
|
|
|||
|
|
@ -53,15 +53,30 @@ from type_definitions import CardLibraryDF
|
|||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler(),
|
||||
logging.FileHandler('logs/setup_utils.log', mode='a', encoding='utf-8')
|
||||
]
|
||||
)
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/setup_utils.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
# Type definitions
|
||||
class FilterRule(TypedDict):
|
||||
|
|
|
|||
31
tagger.py
31
tagger.py
|
|
@ -44,15 +44,30 @@ PATTERN_GROUPS = {
|
|||
if not os.path.exists('logs'):
|
||||
os.makedirs('logs')
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler(),
|
||||
logging.FileHandler('logs/tagger.log', mode='w', encoding='utf-8')
|
||||
]
|
||||
)
|
||||
# Logging configuration
|
||||
LOG_DIR = 'logs'
|
||||
LOG_FILE = f'{LOG_DIR}/tagger.log'
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_LEVEL = logging.INFO
|
||||
|
||||
# Create formatters and handlers
|
||||
formatter = logging.Formatter(LOG_FORMAT)
|
||||
|
||||
# File handler
|
||||
file_handler = logging.FileHandler(LOG_FILE, mode='w', encoding='utf-8')
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Stream handler
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
### Setup
|
||||
## Load the dataframe
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue