Practical Way to Get Started With Python
Using the Files and Logs method.
No matter the what the use case is, Python can always be utilized to solve the problem statement. Maybe, not in the most efficient way but it does solve your problem. And the best part is, it's one of the easiest Programming language to learn in today's date. And here's how you can get started with it in the most practical way possible.
One can skim through the internet trying to find ways to learn Python and most of the articles/tutorial/courses you find will tell you how to use Python's constructs, conditional statements, iterations, OOP concepts, a few libraries like NumPy, Pandas etc. and that's a really good starting point. But the question always lies, WHAT NEXT?
This article talks about what to do next to implement the basics of Python and getting comfortable with the language.
Start with a small project to read a file from filesystem and log all the events happening inside the code.
All those who want to explore on their own may now close this tab and move ahead with googling "How to read a file in Python?" or "How to log events in Python?". Others who would like a guiding hand, may follow along this article.
1. Reading files in Python.
We'll start by reading a simple text file. For starters create a text file manually and paste the loren ipsum statement into it.
Now to read this file, we need 2 objects:
- Path to this file
- IO object to perform read operation.
From a bunch of filesystem libraries available in Python, I find pathlib
the most intuitive. You might like to explore more on similar libraries as well.
Python Objects , just like Oceans, are fun when you start exploring them at their depths. Here are the 2 ways to explore them.
from pathlib import Path
file_path = Path.cwd() / 'loren_ipsum.txt'
with open(file_path, 'r') as text_file:
file_data = text_file.read()
print(file_data)
Let's see what's happening here.
We import Path module from pathlib package. Path.cwd()
's __str__()
implementation returns the string representation of pathlib object for current working directory. / 'loren_ipsum.txt'
uses the operator overloading concept to append the text file name in the path.
Using the context manager with
we then open()
the text file as text_file
object in reading ('r')
mode. And then we print the data. Pretty easy stuff, right?
Obtaining resources using
with
is generally a good idea because then you won't have to worry about releasing those resources.
Now we move to the logging part.
- Logging in Python
It's quite easy to implement basic logging functionality in Python. All you need to do is import logging
package, set logging configurations using logging.basicConfig()
method and start logging events using logging.info('Event Here')/logging.warning('Warning Here')
etc. methods.
Here's how it looks like:
import logging
logging.basicConfig(
filename="applog.log",
datefmt="%d-%m-%Y %H:%M:%S",
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s %(message)s"
)
logging.debug("This is a DEBUG MESSAGE")
logging.info("This is a INFO MESSAGE")
logging.warning("This is a WARNING MESSAGE")
logging.critical("This is a CRITICAL MESSAGE")
We'll take a advanced step and configure logging in detail to understand underlying concepts.
We'll start with importing logging package as usual
import logging
Logging package basically requires 4 objects to work.
- Logger Object: Logger is never instantiated directly but through a module-level function called
getLogger(logger_name)
. It exposes interfaces which application code can directly consume. If no logger is defined, the default logger, Root Logger, will be used.
logger = logging.getLogger("newLogger")
- Handlers: Handlers is also never instantiated directly. There are mostly 2 kinds of handlers used, one being the
StreamHandler
which outputs logs directly into the console window and the other beingFileHandler
which outputs the logs in a file
console_handler = logger.StreamHandler()
- Log Level: Logging in general, concerns with 5 kinds of message namely, DEBUG, INFO, ERROR, WARNING and CRITICAL.
Both Logger and Handler requires log level to be specified to them. Level for Logger determines the type of logs to be collected by the logger. Level for Handler determines the type of logs to be displayed by the handler.
Example:
If I set logger level to ERROR
, then logger will only collect ERROR
, WARNING
and CRITICAL
logs but not DEBUG
and INFO
logs. And then if I set handler level to WARNING
then handler will be display WARNING
and CRITICAL
logs and ERROR
logs will be ignored.
logger.setLevel(logging.DEBUG)
console_handler.setLevel(logging.DEBUG)
- Formatter: Formatter object takes in, what will be format of logs being displayed on console or written into the log file, as an argument.
One of the most generic format of a log would be:
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
Now all we need to attach this formatter to the handler and then attach the handler to the logger
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
Here we are done with setting up the logging in our application.
Now we can put all the code together which would look something like this:
from pathlib import Path
import pretty_errors
import logging
app_name = "Logging APP"
logger = logging.getLogger(app_name)
logger.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
try:
logger.info("Locating File...")
file_path = Path.cwd() / 'loren_ipsum.txt'
except FileNotFoundError as e:
logger.error(f"Locating File Unsuccessful: Error:: {e}")
raise e
logger.info("File Located!")
logger.info("Opening File")
with open(file_path, 'r') as text_file:
logger.info("Reading File")
file_data = text_file.read()
logger.info("Content of the File is read")
logger.info("File Closed!")
logger.info("Execution Complete")
print(file_data)
Once you run the program, you'll get this output on your screen:
2021-03-13 16:01:04,442 - Logging APP - INFO - This is a info message
2021-03-13 16:01:04,443 - Logging APP - INFO - Locating File...
2021-03-13 16:01:04,443 - Logging APP - INFO - File Located!
2021-03-13 16:01:04,443 - Logging APP - INFO - Opening File
2021-03-13 16:01:04,444 - Logging APP - INFO - Reading File
2021-03-13 16:01:04,444 - Logging APP - INFO - Content of the File is read
2021-03-13 16:01:04,444 - Logging APP - INFO - File Closed!
2021-03-13 16:01:04,445 - Logging APP - INFO - Execution Complete
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Once you have understood how to write this code, you can go ahead and read more about the objects of logging
library in depth.
Reading configuration files and logging events are two major components of every application you develop. This mechanism is omnipresent. Once you are comfortable with reading files and logging, consider yourself a notch better than yesterday at any enterprise.