Virtual Environments Pt. 2A – Virtualenv

This is Part 2A of my series on virtual environments, which covers virtualenv, a Python specific package for managing virtual environments. If you are new to virtual environments, I suggest checking out Part 1 of the series, which covers virtual environment basics.  This guide will cover how to do the following with the virtualenv package:

  1. Installation
  2. Creating new environments
  3. Use and management
  4. Exporting
  5. Importing

This guide ends with a comprehensive example that incorporates most of the steps covered in the article.  Note that the version numbers you see locally may differ from my own; this is normal.  Different versions of python and pip may download different package versions.



Installation

virtualenv is a widely used virtual environment manager for Python.  The latest stable package can be installed through pip via:

$ pip install virtualenv


Creating New 
Environments

Creating a new virtual environment is a simple process.  Open a blank folder in the directory of your choosing and enter the following:

$ virtualenv my_venv

Using this command will create a new folder called my_venv which contains everything needed to run an isolated version of python.  Virtual environment name restrictions following standard file/directory name restrictions.  The word venv is usually used as a suffix for the environment name to clearly indicate purpose.

Using and Managing Current Environments

Virtual environments must be activated before use.  The method for activating virtual environments differs slightly depending on which OS you are using:

$ source my_venv/bin/activate #Linux & Mac
$ my_venv\Scripts\activate #Windows

Note the differences between slash direction, path, and whether or not the source keyword is used.

Activating will alter your command line by inserting (my_venv) to the left of the line itself.  Below are examples of an activated virtual environment for terminal and windows command prompt.

(my_venv) jhart@home$  #Linux $ Mac terminal
(my_venv) C:\Users\jhart #Windows cmd prompt

You can continue to use the terminal normally during this time.  You can deactivate the environment using the following command (same for all operating systems):

$ deactivate

Note that closing the terminal will also deactivate it.

While your virtual environment is active, pip can still be used to install packages.  The packages installed will match versions compatible with whatever version of Python is installed to the activated environment.  All installed packages to the are contained to the your virtual environment’s folder.

Deleting the environment doesn’t require any command at all; simply delete the folder created by the virtualenv command.


Custom Python Version

By default, your virtual environment’s python interpreter is the same version as your main python interpreter.  To change this, you can do the following:

$ virtualenv my_venv -python=python2.7

-python=python2.7 will result in python 2.7 being installed.  You main python install won’t be affected in any way, and any version of Python can be installed to a virtual environment.


Exporting 
Environments

Importing and exporting virtualenv environment is done through pip, not virtualenv.
To export a virtual environment, activate the environment of interest and enter the following into the terminal:

$ pip freeze > requirements.txt

This will create a text document called requirements in whatever directory the terminal is currently active in.  The file name isn’t limited to “requirements”, but it should be something descriptive if it will be shared with others.  The only stipulation is that it must be a .txt file.

If my_venv was the active virtual environment during the export process, this would create a blank document because only the default packages ( pip, setuptools, and wheel) were installed to it during initial generation process.  To output all installed packages, including the three defaults, enter the following:

$ pip freeze > requirements.txt --all

The --all flag tells pip to also include pip, setuptools, and wheel in addition to all other installed packages.  Executing that command locally gives me a document with the following:

pip==9.0.1
setuptools==36.2.1
wheel==0.29.0

 

Importing Requirements

The setup for importing a requirements file matches that of exporting a requirements file.  Activate the target virtual environment and enter the following:

$ pip install -r requirements.txt

The -r flag in the above command tells pip to install the requirements listed in the file requirements.txt.  Anything listed in that file will be installed via pip to the active environment.  If no environment is activated, pip will install everything yto your main Python environment.

You can read more about pip freeze here.


Comprehensive Example

To wrap up virtualenv, lets make another virtual environment, and use a new requirements.txt file from my_venv as the basis.   Before creating a new environment, lets install some actual python packages to my_venv prior to the export process.

$ source my_venv/bin/activate   #Linux activation method
$ pip install Splinter          #Install Splinter package
$ pip install pyperclip         #Install pyperclip package
$ pip freeze > requirements.txt #Export package requirements
$ deactivate                    #Deactivate environment

If there were no errors, requirements.txt should contain the following

pyperclip==1.5.27
selenium==3.4.3
splinter==0.7.5

Now, lets create a new virtual environment called new_venv. Once this new environment is created, we can try importing the  requirements.txt file.

$ virtualenv new_venv               #Create new environment
$ source new_venv/bin/activate      #Linux activation method
$ pip install -r requirements.txt   #Install package requirements
$ pip list                          #List installed packages

If the import process was successful, pip list should output the following:

pip (9.0.1)
pyperclip (1.5.27)
selenium (3.4.3)
setuptools (36.2.1)
splinter (0.7.5)
wheel (0.29.0)

Performing all these steps accomplishes the following tasks, all of which make up fundamental virtual environment management practices:

  1. Creation
  2. Activation
  3. Package installation
  4. Exporting environment requirements
  5. Importing environment requirements


Wrapping Up

If you are interested in alternative method of implementing virtual enviroments, you can check out Part 2B (upcomming), which covers the conda utility.  Unlike virtualenv and pip, which are limited to Python, conda can be used by any programming language.

Virtual Environments Pt. 1 – An Overview

post4

Isn’t collaboration great?  Whether you are a part of a community driven open-source project, or an over-worked design team whose souls have long since been crushed, you can be proud of being part of something bigger!

While development work often falls between these two extremes, package and extended library management is a constant to always be mindful of.  Although personal projects grant free reign to enact every bad programming practice your fingers can muster, subjecting contributors and co-workers to your wrath is not without consequence.

Managing packages and keeping track of dependencies becomes increasingly difficult as a project grows in size.  While introductory programming resources and texts often do a great job of covering programming concepts, areas related to project organization, and working in a development environment as whole, often don’t fit within the context of what is being taught.  Some aspects of these topics really can’t be taught, but can only be learned through experience.  There’s nothing mystical about this subject; it’s just made up of concepts that are hard to quantify in a clearly structured way.

This series on virtual environments aims to introduce the more technical concepts related to project management.  The importance of this topic is defined is only defined by the needs of the project you are a part of, and my intent is to express the importance of these concepts and utilities by conveying their usefulness.  This topic, however is only a small part of the whole; even though effective project management goes well beyond package and dependency management, it’s a part of the process, and incidentally, the topic of this post.

Overview

Virtualization, at it’s core, is the process of emulating something physical in a non-physical way.  Virtual machines, for example, create an instance of an operating system that runs off of virtualized hardware.  While this virtual hardware is derived from the physical components that make up your computer, its implementation is achieved through virtualization process.  In that respect, virtualization can be thought of as the process that makes something virtual.

Unfortunately, this explanation isn’t very clear because the term “virtual” has become almost synonymous with “computer”.   Personally, I like to think of virtual environments as a container that holds a workspace of sorts.  While the virtualization process itself varies depending on the context of the virtual environment, the purpose of a virtual environment doesn’t really change.  Similar to virtual machines, which operate alongside a pre-established OS,  a programming virtual environment can operate alongside a pre-established development environment.

This series is split into three sections:

  • Part 1 provides an overview of virtual environments, along with practical applications as well
  • Part 2A covers virtualenv, a Python specific tool used to implement virtual environments.
  • Part 2B covers Conda, a language independent tool that is both a package manager, and a virtual environment manager.

While all three parts were originally in one single article, it length became problematic. The problem wasn’t the information itself; the issue was putting it all in one place.  Parts 1 and 2A are being released together, and part 2B will be released as soon as it’s finished.



Collaboration and Project Management

Python’s already extensive library can be expanded through thousands of user made libraries and packages.  Many projects incorporate at least one of these packages, which in turn creates a dependency.  While keeping track of all dependencies specific to a project is a problem, it’s not the problem.

Every package has a version number,  and most packages are continually updated.   While updates are usually beneficial, changes to a package can create conflicts with other packages and/or Python itself .   Git may address file consistency across multiple contributors, but how do you address consistency across multiple development environments as well?  For most projects with more than a single contributer, the following are important considerations:

  1. Everyone is developing and testing code using the same version of Python
  2. Everyone has all external package dependencies installed
  3. Those external packages are the correct version

Keeping track of that manually is not only error prone, but unmaintainable depending on how many external libraries are required.  An even bigger concern is accounting for completely unrelated libraries that are part of a contributor’s system that might also introduce compatibility issues.  An additional consideration, for open-source projects at least; contributors can’t be expected to limit their only development environment to the scope of one project.

Under the Hood

A Python virtual environment, at the most basic level, will include some version of Python, pip, and setuptools.  These environments function alongside a user’s main python environment, allowing for different Python versions and packages to be installed alongside each other.   A Python 2 virtual environment will work just fine in a system with only Python 3 installed.  Virtual environments must be explicitly activated, so they only “take over” when instructed to do so.

Activating a virtual environment invokes a configuration change (of sorts) that temporarily alters the path variables related to the Python interpreter.  When I activate a virtual environment, I’m not so much creating a new process, I’m just pointing my system to an isolated version of Python.  While different tools create virtual environment in different ways, the result is a folder containing copies of, or links to the required version of Python, along with any external dependencies.

When a virtual environment is activated, any installed packages are installed to only that environment.  Because each environment is effectively isolated from all other environments, they can be quickly created, deleted, or changed to suit a project’s needs. The utilities used to manage virtual environments allow users to define working environments for specific projects.  This allows contributors to easily create isolated environments that match the working environments established by project authors.

While being able to share a working development environment is extremely beneficial, use case extends to other areas as well.  For example, virtual environments could be created to test the following:

  1. Addition or removal of packages and libraries
  2. Version compatibility between packages
  3. Checks against older/newer versions of Python

The process of actually defining a development environment for all project contributors is accomplished by exporting the names of all installed packages (and their version numbers) to a  .txt or ​.yaml file.  Contributors can download this file and use a local package manager to read the contents and automatically install all dependencies to a local environment.

Creating a virtual environment is handled by an environment manager, while importing and exporting environments are handled by a package manager.  Part-2A and Part-2B discuss the utilities used to either create or import/export a virtual environment.  A python specific solution can be accomplished through it’s package manager pip, along with virtualenv package.  A language-independent approach can be achieved through conda, which manages both packages and virtual environments.  Part 2A and 2B cover using virtualenv and conda in respect to the following:

  1. Installation
  2. Creating environments
  3. Using and managing environments

 

Links to those articles can be found here as those articles become available:

 

 

All About Context (and file handling)

git-snippet

While this post will cover context managers in Python, I’d like to first address a statement made in my introductory post:

My goal here isn’t to teach programming, there are much better resources out there for that.

Well lets just…

My goal here isn’t to teach programming, there are much better resources out there for that.

My intention behind that statement was to express that I wouldn’t be covering the fundamentals of programming as a whole, because there are much better resources for that.  Based on the evidence, I did a terrible job of expressing those intentions clearly. I doubt anyone ever intends to paint themselves into a corner, but thankfully, strikethrough and shame heals all.

In theory, leading someone to believe they won’t be taught new programming concepts, and then later teaching programming concepts isn’t terrible.  At the very least, it’s always good practice to admit to mistakes, regardless of how incredibly specific or mundane.  I also wanted to stretch this introductory section out a bit more, and this was the best I could come up with.  Anyway, let’s talk about context managers!


Context Managers

While context managers are applicable to operations outside of file handling, file open/close procedures are a common use case, and examples utilizing such operations provide a good introduction.  Although examples in this post are Python specific, the concepts covered can be related to other languages as well;  in C# for example, the using statement behaves like a context manager.  Additional information on context managers in Python, including other applications, can be found in this excellent article by Jeff Knupp.

The technical definition, along with the meaning behind ‘context manager’ can be found in Python’s official documentation in regards to the with statement:

context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code.

While the technical definition explains what context managers do fundamentally, what they do in practice comes down to the following two operations (in the order they appear):

  1. Taking control of a resource
  2. Releasing control of that resource

A better explanation of context managers is covered through one of their primary uses; file handling.

File Handling

Expanding on the definition provided in the previous section, context managers can be thought of as a means of handling operations that are performed in pairs.  In Python, context managers are often used to handle file open and file close operations. While not using a context manager for file handling doesn’t mean your code won’t work, it’s something to be avoided.  The following python code will perform as expected:


file = open('insecure_password_storage.txt', 'w')
file.write('12345')
file.close()

Although opening and closing a file in this manner works, problems occur if an exception is raised prior to the call to file.close().  A failure to reach this call introduces the following possibilities:

  1. Some implementations of Python will handle this close at a later point via automatic garbage collection, but allowing the loss of explicit control over that file isn’t a good practice.
  2. Python might not release control of the file at all, limiting manipulation of that file until control is released.
  3. Data may not be correctly flushed to the file itself if that file was opened in write/read-write mode

This method of file handling introduces too much uncertainty and instability to a program.  Forgetting to add a file.close(), or even a simple syntax error can introduce any of the above problems.   Errors are always a possibility, especially during testing, and more focus should be placed on solving the cause of an error rather than worrying about the external effects of that error.  Accounting for those errors can be achieved with the following:


file = open('insecure_password_storage.txt', 'w')
try:
    file.write('12345) # closing apostrophe missing
finally:
    file.close()

By leaving the apostrophe off the file.write(), at runtime,  python will raise an exception.  The addition of the finally clause acts as a cleanup action; even if Python throws an exception, anything under the finally block executes; in this case, the file.close() operation.

This method of file handling acts as a context manager, and was the primary method of opening/closing a file prior to the addition of the with statement in Python 2.5. Although the try-finally approach handles exceptions raised prior to file closure, missing calls to  file.close()  aren’t accounted for.

It’s easy to forget to add a piece of code (unless I’m the only one who does it, then just play along).  I personally don’t like having to remember to close a file using the method above considering the consequences of not doing it (that sounds better than ‘I like being lazy’ at least).  To achieve the same effect as a try-finally approach, but with the added benefit of writing less code, use the with statement:


# File write operation
with open('insecure_password_storage.txt', 'w') as file:
    file.write('12345') 

The with statement in the above code replaces the functionality of the try-finally approach.  Apart from the syntax difference, the biggest change is the exclusion of  file.close().  The with statement acts as a context manager, so any file opened under the with block closes at the end of the block.  Just like the try-finally method, even if Python raises an exception prior to the file being closed, the with statement ensures the resource is released.  Read operations utilizing a with statement operate in the same manner:


# File read operation
with open('insecure_password_storage.txt', 'r') as file:
    my_passwords = file.readlines()

The with block always handles any indented code under it, so the contents of a file can be stored inside of a variable and used outside the block. Although examples have covered basic file read/write calls, any operation that need to be performed on an open file can be performed using a with statement.  A file.close() method never needs to be included in the with statement, and it shouldn’t as the with statement was intended to handle operations like this.

Final Thoughts

Use the with statement method for file open/close operations; doing so will improve your code’s stability, and it will avoid introducing file system problems on top of code errors.   At the very least, you are cutting out an entire line of code from every file operation; that’s a 33% decrease!

Those looking for information on the underlying methods behind the with statement can find more information here.

Ohh, and don’t store your passwords in text files.

Books, Things, and more Books

code2

So you’ve decided to give programming a go, or maybe try out a new language, or, maybe you are a seasoned developer who is going  wrip this post and my feelings apart.  In any case,  let’s talk about Python! 

While many wonderful things can be found across the internet, finding something useful can be a challenge.  While sites like Codecademy, Code School, Udacity, and a number of other online resources provide a more modern means of learning how to program (often at no or little cost), throwing in more traditional methods on top of that can be extremely beneficial.

While the manner in which you learn something new is entirely up to you, I’ve found in many cases that the process itself is accomplished through multiple methods.  For me, and many others, reading books/guides, practice exercises (from books or websites), and larger projects will provide the most complete coverage.  Over the next few weeks, I will share resources and practices that I’ve found helpful.  While most of my focus will be Python related, the future section on practice exercises and projects can be applied to any language.  Today, I cover beginner-to-intermediate text-based resources.

Comprehensive Texts

The books in this section are suited for people with no programming experience, or those looking to just learn the Python syntax.  While each book contains valuable information for intermediate level programmers as well, know that the initial chapters of all my recommendations cover basic python/programming concepts.  Noteworthy and additional topics of interest are noted for each book.

Title:   Python Crash Course (Eric Matthes)
Links: Homepage | Sample Chapter
Cost:   Paid – Ebook and Hardcopies available

Additional Topics: Unit Tests, Django, Git, Data Science, Pygame, Web Scraping
Considerations:  String formatting not covered.


Python Crash Course (PCC) covers everything from basic data types all the way to object oriented programming.  While reading about a new concept is great, putting it into practice is often essential to internalizing that subject.  While practice exercises in general are great, PCC’s exercises are included throughout each chapter, as opposed to just at the end of the chapter. While these exercises are more compact than normal end-chapter problems, they do force you put the concepts covered into practice more frequently.  The problem sets also do a great job of dividing the various concepts presented in each chapter into manageable subsections.

The book is divided into two parts; part 1 deals with fundamental programming concepts while part 2 covers three large projects: building a game using Pygame, utilizing data science tools, and building a website (with user login and forum posting) using Django. These projects put into practice all the skills covered in the first half of the book, and each step is guided by the author.  The smaller in-chapter exercises found in part 1 of the book are still present in part 2; although the author guides each step of the project, multiple opportunities are given to apply these concepts without direction.

While the book is not free, it can be found for around $25, which is extremely reasonable.  The large projects offered in the second half of the book more than make up for the cost.

 

Title:   Automate the Boring Stuff with Python (Al Sweigart)
Links: Homepage | Sample Chapter
Cost:   Free online, paid hardcopy/ebook available

Additional Topics:  Regular Expressions, Debugging, Web Scraping, Task Automation
Considerations: Object oriented programming and string formatting not covered.


Automate the Boring Stuff with Python (AtBS) is one of the most recommended beginner books for Python.  Every chapter focuses on examples and exercises aimed at real world application.  AtBS’s biggest asset is how it developes a new programmers ability to apply the concepts they learn to relatable environments (everything from organizing files to automating keyboard/mouse actions).  While many learning resources already do this, AtBS provides much more focus on this practice than what is standard.

Although early chapters focus fundamental Python/programming concepts, as the title of the book suggests, there is a strong focus on task automation.  The author is a big fan of it, and he actually wrote many of the modules used throughout various chapters.  AtBS is an example of utilizing a variety of resources when learning a new subject.  Although it will core Python concepts, object oriented programming is not covered.  The online version is entirely free and you will learn about areas of Python not typically covered in other texts.

In terms of practical exercises, early chapters include various problem sets that cover fundamental concepts of the chapter, while later chapters include more involved problems, or large projects.  While not as frequent as PCC’s in-chapter exercises, important concepts found throughout each section are still put into practice.

 

Title:   Python 101 (Michael Driscoll)
Links: Homepage | Sample Chapter
Cost:   Free online, option to donate to author available

Additional Topics: Decorators, Building Executables & Packages, Virtualenv, many more
Considerations: Not as many practice exercises as PCC or AtBS


In addition to covering basic Python concepts, Python 101 (101) also details a number of extended library modules and packages, and a variety of other topics across 40+ chapters.  Although the chapters are numerous in number, they are concise and well organized.   The value of 101 is that it will introduce you to a wide array of modules and practices not typically covered by other texts.  While this may sound like a pocket reference, it’s not; each chapter contains numerous examples and explanations of each step.

Because of the number of topics covered, additional concepts worth mentioning are: string formatting, the SQLAlchemy and sqlite modules, the threading and subprocess modules, and sections on debugging and testing.  If you want a list of all topics covered, you can find the table of contents here.  After chapter 11 (Object Oriented Programming), the rest of the book can be viewed in almost any order.  The only downside of 101 is that  few exercises are explicitly given, however, the example problems themselves give a strong indication of what specific concepts can be used for.
 

A Note on String Formatting


If you are a beginner, or if you haven’t heard of string formatting before (the .format() method in python), this section applies to you.  If this is your first time reading about programming, for reference, strings are just sequences of characters.  This sentence is a string, for example.

I started with both Python Crash Course and Automate the Boring Stuff, and while they are great, string concatenation is the only method taught as a means of formatting text that will be displayed on screen.  While PCC mentions an alternative method, it’s mentioned briefly on two pages in the second half of the book. For reference, when I’m talking about about string concatenation, I mean this:

print('Hello' + 'World!') #Displays: Hello World!

or this, which  accomplishes the same thing

print('Hello', 'World!') #Displays: Hello World!

In Python, you can use the ‘+’,  sign,  or you  can separate characters/variables with a comma to combine words/ variables together.  Sometimes, it’s needed, but for printing some kind of output to the screen, string formatting is a better (and faster) method.  For example, If we had multiple names we wanted to print, and those names were stored in variables, using the above method would require this:

first_guest = 'Jenny'
second_guest = 'Bob'
third_guest = 'Lisa'

# Jenny, Bob, and Lisa are coming to the party.
print(first_guest + ', ' + second_guest + ', and ' + third_guest + ' are coming to the party.')

This makes the code hard to read and error prone, all of which is exacerbated as more words or variables are added .  An alternate method would be using string formatting via the .format() method, like so:

first_guest = 'Jenny'
second_guest = 'Bob'
third_guest = 'Lisa'

# Jenny, Bob, and Lisa are coming to the party.
print('{}, {}, and {} are coming to the party.'.format(first_guest, second_guest, third_guest))

The extremely over-simplified difference is that curly brackets ‘{}’ are placeholders for variable or expression names, and the .format() method contains the variable/expressions (separated by commas) in the order they are to appear in the sentence.  Much more can be accomplished with .format() than can be covered here; more information, along with great examples and explanations can be found in this comprehensive guide.

The above link also provides examples of the old method of string formatting in python (which essentially behaves like C’s printf() function).  There is an even newer method of string formatting, literal string interpolation (or f’strings’), that provides an additional method of string formatting.  It’s only supported in Python 3.5+, and although there aren’t as many guides on it, it’s worth looking into at some point.

String concatenation isn’t inherently bad when used in the right cases; however, when printing text to the screen, typically, some type of string formatting will save time and make code more readable.  In the defense of both PCC and AtBS, string concatenation is an easier way of teaching how  words, characters, and variables can be combined.  The notion of ‘adding’ parts of a string together is much more intuitive.  By all means, if you are just starting out, and this is a confusing concept, go with whatever makes sense first, you can always come back later; this is by no means a priority.

 

Final Thoughts


There is a difference between asking “what book should I start with” and “what book should I use” in regards to learning something new.  In terms of programming, there is rarely a case where a single resource will give all the practice and information necessary to fully harness the features of a language.  While some texts are extremely well written and thorough, utilizing only a single resource prevents one from getting the insight of a different individual solving problems their own way.

By no means am I suggesting that read all these books need to be read to become good at Python, or programming in general; you don’t.  Reading these books has shown me the value in learning to solve a problem in multiple ways, and they have provided unique contexts I would have never experienced otherwise.  There are dozens, if not hundreds of books on Python alone, and this small list doesn’t represent the best out of that set; in addition to being extremely helpful early on, they sparked my interest, conveyed concepts clearly, and are still useful today.

With that in mind, if you have any resources that you found particularly useful, feel free to share; additional perspectives for myself, and for anyone who comes across them is always nice.

Now, on the topic of awkward and forced transitions, that’s all I got. Tune in next time for some intermediate-to-advanced level resources, and texts that didn’t really fit in the context of this guide!

Kicking the Tires


Last hope

To say programming is hard isn’t the whole truth. Programming, by itself, is challenging; you get a problem set and you try to solve it, you start a project and try to implement your ideas. The act of just programming, that is, coming up with computational solutions to a problem, is an easier process than the subject of programming as a whole. Programming is hard because it involves so many different elements not covered by traditional textbooks and guides. In some cases, entire books are devoted to single text editors, and once you throw in IDEs, version control, best practices and coding styles, and a list of other concepts related to software development in general, it can be hard to know which area to focus on next.

While much of this information comes naturally in time, it can be overwhelming at first. It was for me. It still is for me. My biggest problem when I started learning to program was trying to figure out what was the best thing to use for this other thing. Trying to search for answers like often leads to a group of people saying “this is the best” while another group will proclaim “no, this is better!”  Unfortunately, the disagreement of what’s ‘the best’ doesn’t lend well to certainty in a choice. There is no best choice, and there really isn’t even a best answer, but, there is often a better answer.

Until recently, I never considered writing about my experiences related to anything, let alone programming. I’ve been answering questions and providing suggestions online for the last 10 years across various venues, and for the most part, I never knew if anyone read what I had to say, let alone know if that information was helpful.  But, recently, a committed and enthusiastic classmate of mine found what I had to say helpful, and she told me it was worth sharing with others. While I’ve never expected or needed any kind positive feedback, it was by far one of the nicest things anyone’s ever said to me (thank you, Marianna).  It reminded me there was a point to all this, so, per her advice, I’ve started this blog to share experiences and information that I feel other people would find useful in some way.

I’ll warn you now and say that the feedback I’ve received over the years, the few times I actually received some, can all be summarized as ‘TL;DR’. While I’ve taken steps to make my writing more concise, as you can see from the creeping length of this post, I’m still not that good at expressing myself in a succinct manner. While I feel the subject matter of these posts will lend well to lengthier discussions, I still can’t seem to let go of my soap box, and digressions still seem to hide around every corner. For the most part, however, the details provided will be relevantprobably.

While my area of study has largely been Python related, and although initial postings will detail information related to that, I will cover my experiences with other languages and general programming concepts as well. My goal here isn’t to teach programming, there are much better resources out there for that. This site serves as means for me to talk about experiences and concepts that aren’t really covered by traditional guides, and the subjects detailed here won’t all be related other than the fact they all deal with programming in one way or another. Even if few (or no one) ends up reading this, it will at least serve as a more visually appeasing means of cataloguing resources for personal reference later (cramping everything into an excel sheet isn’t very eye catching).

Anyway, as you will soon find out, I don’t know how to conclude my point gracefully, so this is me explicitly ending it. If you find any of this intriguing, or you just enjoy watching my awkward attempts at closing, I hope to provide new posts weekly.