The Evolution of Python: Powering AI and Enterprise Solutions

David Pitt AI, Development Technologies, Programming, Python Leave a Comment

Parts of this blog, including the code examples and architecture frameworks, were generated using Keyhole Software’s EnterpriseGPT web client—an open-source tool that empowers organizations to deploy user-friendly chatbot solutions with ease. Interested in exploring further? Contact our team, and we’d be happy to provide credentials for you to try it out.

The Rise of Python and Other Languages

We’ve seen many programming languages come onto the scene over the years. Java and C# used to be the new kids on the block 20 years ago, and now they’re the old stalwart languages. The personal computer revolution of the 1980s was the genesis for this, allowing everyone to have a general-purpose computer in their homes and businesses. This spurred alarmingly fast digital automation that is still alive today. Those that remember, think of the initial floppy disk-installed apps to the current diskless web applications we have today.

With this revolution, the knowledge barrier of developing operating systems and computer languages was lowered. If tools like these had been proprietary, the programming landscape would look quite different today. Open-source utilities like YACC, or Yet Another Compiler Compiler, allowed developers to create parsers and played a key role in advancing software development.

Not everyone knows what YACC is, so here’s a quick description from EnterpriseGPT, the Web Based ChatGPT client application Keyhole has developed:

“YACC, short for Yet Another Compiler Compiler, is a computer science utility that serves as a parser generator. It aids in the creation of parsers for syntax analysis in software development by specifying a formal grammar in the form of context-free grammar rules. With YACC, developers define the grammar rules for their language and associate semantic actions written in C code to be executed when parsing specific language constructs. YACC then generates a C code parser that can parse input according to the specified grammar rules, making it an essential tool for building compilers, interpreters, and other language processing systems.”

Over the years, newer languages have been introduced. Many are UI browser-based languages such as Angular, Vue.js, and React. Others were built for lower-level and middleware-type applications, like GoLang, Dart, and Rust, which were designed to compete with the C language. Speaking of, C has been around for a long time! It was invented in 1972 by Bell Labs employee Dennis Ritchie.

Typically language popularity follows a curve. Folks start to adopt the new language gradually at first, it begins to gain momentum until it reaches a point, plateaus, then slowly declines and falls off as newer, shinier languages are released. However, there is one language that has not followed this trajectory: Python.

The History of Python

Python is not a new language; it has been around for quite some time. Developed by Guido van Rossum in the 1980s, Python saw its first release in 1991. Its simple syntax and interpreted runtime have made it incredibly versatile, serving a wide range of purposes from automating scripting tasks to handling the complex mathematics required for AI applications today.

Its flexibility and quick spin-up time have long been attractive to developers, making it a popular choice for enterprise application development. Over the years, Python quietly became a go-to solution for many organizations, including us here at Keyhole Software.

In the past 5 years, we have seen a growing demand for Python expertise from our clients. To keep up with demand, we’ve brought experienced Python developers onto the team. We’ve also had many developers learn the language after years of experience with other stacks. I spoke with one of our senior consultants whose primary skill set was Java, and he shared how easily he transitioned to Python

Like JavaScript, Python is an interpreted language, meaning there’s no compilation step. You write your program instructions in a human-readable text file and execute them directly using the Python interpreter. Similarly, JavaScript programs are run by browser-based interpreters or standalone environments like Node.js.

With this foundation in mind, let’s explore the basics of Python and then move into a discussion about application architecture frameworks that support enterprise computing.

Understanding Python’s Structure

The following basic elements of Python were produced with the help of Keyhole Software’s EnterpriseGPT web client.

Variables

Python stores data values.

# Variable declaration and assignment
name = "Alice"
age = 30

# Print variables
print(f"My name is {name} and I am {age} years old.")

Data Types

Python supports standard data types, such as floats, integers, strings, and lists.

# Integer and float
x = 10
y = 5.5

# String
name = "Bob"

# List
numbers = [1, 2, 3]

# Dictionary
person = {"name": "Charlie", "age": 25}

Control Structures

Python supports application control flow, conditional logic, and looping.

# If-else statement
x = 10

if x > 5:
    print("x is greater than 5")
else:
    print("x is 5 or less")

# For loop
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# While loop
count = 0
while count < 5:
    print(count)
    count += 1

Code Blocks

Code blocks are defined using indentation, typically 4 spaces.

i = 0
while i < 5 
   if i == 4
       print(i)   

Functions

Reusable blocks of code, such as functions, enhance efficiency.

def greet(name):
    return f"Hello, {name}!"

result = greet("David")
print(result)

Classes and Objects

Python’s object-oriented nature allows developers to define classes and create objects.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        return f"Hello, my name is {self.name} and I am {self.age} years old."

# Create an object of the Person class
person = Person("Eve", 28)
print(person.greet())

Modules

Logic and functions can be partitioned into separate files.

# Import the module
import mymodule

# Use the function and variable from the module
result = mymodule.greet("Alice")
print(result)
print(mymodule.my_variable)

As you can see, the structure of Python is very simple. Although I’m not sure about the indentation for code blocks, it does make things cleaner and easier to read.

The previous examples provide a very basic introduction to the language structure and its elements. Now, let’s explore some built-in libraries to demonstrate how Python efficiently handles common tasks.

File I/O

Python allows you to read and write files.

#Read file

with open("input.txt", "r") as file:
    data = file.read()
    print(data)

#Write file	

with open("output.txt", "w") as file:
    file.write("Hello, World!")

Exception Handling

The sys module provides access to system error messages.

import sys

try:
    # Code that might raise an exception
except Exception as e:
    print("An error occurred:", e, file=sys.stderr)

JSON

You can work with JSON using the json module.

# Decode JSON and write to a file
import json

data = {"name": "Charlie", "age": 35}

with open("data.json", "w") as file:
    json.dump(data, file)
#Write JSON
import json

data = {"name": "Charlie", "age": 35}

with open("data.json", "w") as file:
    json.dump(data, file)


# Read JSON

import json 

with open("data.json", "r") as file:
    data = json.load(file)
    print(data)

Threads

Python has thread support and can synchronize running threads and create daemon threads.

import threading

# Define a subclass of Thread
class MyThread(threading.Thread):
    def run(self):
        print("Hello from a thread!")

# Instantiate and start the thread
thread = MyThread()
thread.start()

Network Programming

You can create, connect, and get access to sockets with the Python socket module.

#Open a Server Socket

import socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(1)

print("Server listening on port 12345")

client_socket, address = server_socket.accept()
data = client_socket.recv(1024)
print("Received data from client:", data.decode())

client_socket.close()
server_socket.close()

# Access socket with a client

import socket

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))

data = "Hello, server!"
client_socket.sendall(data.encode())

client_socket.close()

HTTP

You can access HTTP urls with GET/POST/DELETE using the request module.

 import requests

response = requests.get("https://jsonplaceholder.typicode.com/posts/1")
print(response.status_code)
print(response.json())

Enterprise Python

Now that we’ve covered the basics, let’s dive into how Python can be leveraged for Enterprise development. We define enterprise development as web applications designed to handle a significant number of concurrent users–typically in the hundreds or low thousands. These web apps are usually built by teams of developers, making a consistent application architecture essential to ensuring seamless collaboration. The following sections will describe architecture elements required for a robust enterprise application architecture. We utilized Keyhole’s EnterpriseGPT interface to enumerate popular frameworks that support the application architecture.

API Layer

Enterprise web applications often consist of a server-side API, with the user interface delivered via a browser-based application built on popular JavaScript frameworks like React.js, Angular, or Vue.js. While other frameworks exist, these tend to dominate the landscape. The first element in this process is selecting a framework that supports API implementation–there are a number of options available.

Keyhole Question:

“What are the most popular Python server side API frameworks?”

EnterpriseGPT Response:

Some of the most popular Python server-side API frameworks that are widely used
for developing web APIs are:

1. DJANGO REST FRAMEWORK:

Django REST framework is a powerful and flexible toolkit for building Web APIs
using Django. It provides serializers, viewsets, authentication, permissions,
and other functionalities that make it easier to create RESTful APIs.

2. FASTAPI:

FastAPI is a modern web framework for building APIs with Python. It is based on
standard Python type hints and provides auto-generated interactive API
documentation. FastAPI is known for its high performance and ease of use.

3. FLASK:

Flask is a lightweight and flexible micro-framework for building web
applications and APIs in Python. While it is not specifically designed for
building APIs, Flask’s simplicity and extensibility make it a popular choice for
developing APIs.

4. FALCON:

Falcon is a minimalist web framework for building high-performance APIs. It is
known for its speed and efficiency, making it a great choice for
performance-sensitive applications and APIs.

5. TORNADO:

Tornado is a web framework and asynchronous networking library that is
well-suited for building real-time applications, long-lived connections, and
APIs that require high performance.

6. SANIC:

Sanic is a web framework built on top of uvloop and asyncio that aims to be fast
and efficient. It is designed for building asynchronous web APIs and
applications.

7. BOTTLE:

Bottle is a simple and lightweight micro-framework for building web APIs in
Python. It is known for its minimalist approach and ease of use.

Each of these frameworks has its own set of features, strengths, and use cases.
Depending on the requirements of your project, you can choose the one that best
fits your needs in terms of performance, ease of use, scalability, and community
support.

Data Access

Accessing and persisting data is also something that is required of almost all enterprise applications. Most enterprises persist data into some kind of relational database, NoSQL datastores are also utilized, but they are not as prevalent as relational databases. The best practice is to use an object relational mapping (ORM) framework to map Python classes definitions to relational tables. The ORM framework makes persisting and reading transparent.

Keyhole Question:

“Most popular data access frameworks in Python”

EnterpriseGPT Response:

Some of the most popular data access frameworks and libraries in Python for
working with databases and data storage include:

1. SQLALCHEMY:

SQLAlchemy is a powerful and widely used SQL toolkit and Object-Relational
Mapping (ORM) library for Python. It allows developers to interact with
relational databases using Python classes, providing high-level abstractions for
database operations.

2. DJANGO ORM:

Django ORM is the built-in Object-Relational Mapping (ORM) system provided by
the Django web framework. It simplifies the interaction with databases in Django
applications, enabling developers to work with database tables using Python
classes and methods.

3. PEEWEE:

Peewee is a small and simple ORM library for Python that supports various
database backends including SQLite, PostgreSQL, and MySQL. It has a clean and
expressive API for interacting with databases.

4. PANDAS:

Pandas is a powerful data manipulation and analysis library in Python that
provides data structures like DataFrame for working with structured data. It
offers tools for reading and writing data from various sources including CSV
files, databases, and more.

5. PYMONGO:

PyMongo is the official Python driver for MongoDB, a popular NoSQL database.
PyMongo provides a flexible API for interacting with MongoDB databases from
Python, enabling data access and manipulation in Python applications.

6. REDIS-PY:

Redis-py is a Python client for Redis, an in-memory data structure store used as
a database, cache, and message broker. Redis-py allows Python applications to
interact with Redis databases and utilize its features such as caching and
pub/sub messaging.

7. PSYCOPG2:

Psycopg2 is a PostgreSQL adapter for Python. It provides support for connection
pooling, executing SQL commands, and working with PostgreSQL databases using
Python applications.

These data access frameworks and libraries in Python offer a wide range of
capabilities for interacting with various types of databases, making data
manipulation, storage, and retrieval easier and more efficient for Python
developers.

Dependency Injection

Interestingly there really are not any popular dependency injection frameworks in the Python ecosystem. Dependency injection (DI) is a main architectural pattern in and built into Java Spring and .NET frameworks, they are a fundamental part of these frameworks. However you can implement your own simple DI pattern, like we did in the old days, or use a third party DI library.

Keyhole Question:

“Dependency injection frameworks in Python”

EnterpriseGPT Response:

Dependency injection frameworks help manage object dependencies in an
application and make it easier to create and manage objects with complex
dependencies. While Python doesn’t have popular dependency injection frameworks
like those in some other languages, you can achieve dependency injection in
Python using libraries and patterns. Here are some approaches in Python:

1. CONSTRUCTOR INJECTION:

You can pass dependencies as constructor parameters when creating instances of
classes. This is a common approach in Python for achieving dependency injection.

pythonCopy Code

class A:
    def __init__(self, b):
        self.b = b

class B:
    pass

b_instance = B()
a_instance = A(b_instance)

2. PROPERTY INJECTION:

You can set dependencies as attributes of objects after instantiation.

pythonCopy Code

class A:
    def __init__(self):
        pass

a_instance = A()
a_instance.b = B()

3. THIRD-PARTY LIBRARIES:

While Python doesn’t have dedicated DI frameworks, you can leverage existing
third-party libraries like injector, python-inject, or pinject that provide DI
features in Python.

EXAMPLE WITH INJECTOR:

pythonCopy Code

import injector

class B:
    pass

class A:
    def __init__(self, b: B):
        self.b = b

class MyModule(injector.Module):
    def configure(self, binder):
        binder.bind(B)

injector_instance = injector.Injector(MyModule)
a_instance = injector_instance.get(A)

4. DEPENDENCY INJECTION PATTERNS:

You can also follow dependency injection patterns like constructor injection,
property injection, or method injection to achieve loose coupling between
objects.

While Python doesn’t have traditional DI frameworks, the language’s flexibility
and support for different programming paradigms make it easy to implement
dependency injection using patterns, libraries, or custom solutions to manage
object dependencies effectively.

Dependency Management and Packaging

Managing the myriad of third party libraries is essential to productivity and stability of applications. The Java ecosystem has Maven, while the .NET world has NuGet. Python has pip. However, after speaking with some folks at Keyhole who are working with Python, they said pip is not quite up to the task for supporting individual project dependency versions. Python pip manages dependencies, but at a global level to the Python environment. Therefore, developers having multiple projects on a workstation might run into version issues.

For more on dependency injection check out our video, What is Dependency Injection & Why Is It Important In the Spring Framework.

Python and AI

Arguably the most successful use case of Python is that it was used to implement the GPT algorithm to train the large language models we used today for ChatGPT. The pytorch library was instrumental in allowing OpenAI to implement GPT as we know and use today. When ChatGPT was asked if it used pytorch, here is what it said.

Keyhole Question:

“Did OpenAI use pytorch to implement the gpt algorithm?”

EnterpriseGPT Response:

Yes, OpenAI used PyTorch to implement the GPT (Generative Pre-trained
Transformer) algorithms, including GPT-1, GPT-2, and GPT-3. These models are
based on transformer architecture and have been instrumental in advancing
natural language processing and generative AI research.

PyTorch’s flexibility, dynamic computation graph, and strong support for deep
learning applications made it a suitable choice for implementing the GPT models.
PyTorch’s automatic differentiation capabilities, ease of use for building
complex neural network architectures, and GPU acceleration support have
contributed to the successful implementation and training of large-scale
transformer models like GPT.

GPT models rely on self-attention mechanisms and transformer architecture, which
are well-supported in PyTorch. OpenAI has pushed the boundaries of language
modeling and AI research with the GPT models, demonstrating the power and
scalability of PyTorch for cutting-edge research and development in the field of
natural language processing and artificial intelligence.

Conclusion

For enterprise developers familiar with languages like Java or .NET, Python is a great, easy-to-pick-up alternative. Its simple syntax, rapid development capabilities, and strong ecosystem of frameworks make it a valuable asset for everything from scripting tasks to enterprise applications. Python is constantly evolving, positioning it as an essential language for the future of software development. Whether you’re building AI models, APIs, or enterprise web applications, Python is definitely worth checking out.

For more on Python, Dependency Injection, AI, and more, check out the Keyhole Software blog.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments