Python vs. Java: Comparing Two Popular Programming Languages

In this article, we'll be comparing the features of two server-side programming languages; Python and Java. Let's begin with some design differences in both the languages.

Fundamental differences in the design and implementation of Python and Java

History

Having an idea of the past can provide us the context to understand why things were built the way they are now. Python was created to bridge the gap between C and the shell. It was intended to be a higher-level interpreted language that enables clean, concise, and readable code.

Java was created to be a compiled, platform-independent Object-Oriented programming language. The intention was to achieve code portability (write once run everywhere) with little or no programmer effort. One of the early applications of Java was incorporation into browsers like Netscape, and it soon became popular.

You'll find most of the legacy systems and enterprise-level web applications programmed in Java than in any other language. And you'd often find Python being used a "glue" to combine different components in these systems.

Design

There are a lot of great resources on the internet that explains the design differences in-depth, so we won't dive into those, but instead, I'll mention a few "simplified" takeaways,

Consequences of the design and history

On semantics

On performance

Many luxuries in the CPython implementation of Python (the most widely used Python implementation) come at the cost of,

Concurrency in Python

CPython implements a Global Interpreter Lock to ensure thread-safety, which means,

Python provides some abstraction for performing multiprocessing through the built-in multiprocessing module. For parallelization of I/O related tasks, Python included asyncio module which received significant usability and performance improvements in the recent Python 3.7.x version.

Concurrency in Java

Java Virtual Machine (JVM) is capable of executing multiple threads in parallel on multiple CPU cores. The programmers have to deal with the complexities of dividing their tasks into threads and synchronization between them. Java provides Thread class and Java .util.concurrent package containing some abstractions for multi-threading. The fact that most of the popular distributed computation frameworks (like Spark and Hadoop) are primarily written in Java is evidence of its suitability for concurrent execution.

Note: We discussed the most popular implementation of Python (CPython) in this section. There are other implementations as well, which make some other trade-offs for the sake of performance and to support parallel execution (take a look at the pypy project and Stackless Python, which supports JIT compilation and concurrency).

Comparing simple iterative and recursive programs in Python and Java

We'll take two well known mathematical problem statements,

  1. Compute n'th value in the Fibonacci sequence.
  2. Compute factorial of n.

Following are the simple implementations for the same, you can observe some of the differences that we discussed in above section in the code and the results.

# Python version 3.8.0 (CPython implementation)
def fib(n):
    # Iterative fibonacci
    a, b = 0, 1
    for i in range(0, n):
        a, b = b, a + b
    return a
  
def fib_r(n): 
  # Recursive fibonacci
  if n < 2: return n 
  return fib_r(n-1) + fib_r(n-2) 

def fac(n):
  # Iterative factorial
  x = 1
  for i in range(2, n + 1):
    x = x * i

def fac_r(n):
  # Recursive factorial
  if  n >= 1:
    return n * fac_r(n - 1)
  return 1

# Printing out the run times, the value of n is decided based on execution times and maximum stack depth
print(timeit.timeit(lambda: fib(60), number=1) * 1000)
print(timeit.timeit(lambda: fib_r(40), number=1))
print(timeit.timeit(lambda: fac_r(25), number=1) * 1000)
print(timeit.timeit(lambda: fac(25), number=1) * 1000)
/*
Java version 11.0.3
Please excuse me for using `snake_case` in the program.
 */
public class SimpleMethodsPrimitive {

    public static void main(String args[]) {
        long start_time = System.nanoTime();
        fib(60);
        // fib_r(40);
        // fac_r(25);
        // fac(25);
        long stop_time = System.nanoTime();
          // Printing out run time in nanoseconds
        System.out.println(stop_time - start_time);
    }

    private static long fib(int n) {
        // Iterative fibonacci
        long a = 0, b = 1;
        for (int i = 0; i < n; i++) {
            a = b;
            b = a + b;
        }
        return a;
    }

    private static int fib_r(int n) {
        // Recursive fibonacci
        return n < 2 ? n: fib_r(n-1) + fib_r(n-2);
    }

    private static long fac(int n) {
        // Iterative factorial
        long x = 1;
        for (int i = 2; i < n + 1; i++) {
            x = x * i;
        }
        return x;
    }

    private static long fac_r(int n) {
        // Recursive factorial
        return n < 1 ? 1: n * fac_r(n -1 );
    }
}

Beyond design - The Development Ecosystem, Libraries and Frameworks

Developer productivity is an essential factor in deciding which language to choose from. Let's take a look at the ecosystem and libraries that support developer productivity.

Dependency management and Code distribution

Java code is packaged and distributed in the form of .jar files, whereas in Python, it is distributed in the form of .whl files. Package management in Java is relatively stable but more complex to learn.

In Python, pip is pretty much what you'll need to know about in most of the use-cases to manage dependencies. PyPI (Python's package index) is the place where the packages are hosted so that anyone can use them.

PyPI's equivalent in Java is MVNRepository, and the dependencies are specified in the configuration files of build-automation tools like Apache Maven and Gradle. Python now has built-in support from virtual environments (isolated dependency environment specific to projects); a similar thing can be achieved in Java using classpaths.

Libraries and Frameworks supporting typical web development

Java has a strong JDBC (Java DataBase Connectivity) API for and connecting to databases, which is also the reason why Java language has been the popular choice among the enterprise systems. Python's database access layers are slightly more challenging to deal with, as compared to Java. Both languages have ORM capabilities.

It is tough to write the entire backend from scratch, so both the languages have frameworks that provide an abstraction to set-up a reliable and secure backend without reinventing the wheel. Spring is by far the most popular web frameworks in Java, whereas Django and Flask are the two popular web frameworks in Python.

In terms of performance, Java web frameworks are faster, but the Python frameworks are also not far behind (see the benchmarks here). Spring has a LOT of production-friendly dependencies to deal with caching, authentication, databases, messaging, and whatnot, which means the developers can focus just on business logic. The downside of Spring is the big learning curve it has (because of things like dependency injection, verbose configurations, and more), with some developers even describing their early learning experiences as "black magic." It is also much more resource-intensive as compared to Django or Flask. The resource overhead of Spring can sometimes seem unjustified for small-to-medium size web applications.

Debugging and Testing

Both the languages are easy to debug, but I've personally found stack-traces and exceptions in Python to be more helpful. Another thing that sticks out for me is the build-time is usually much faster in Python as compared to Java (since Python is an interpreted language), which is excellent when you are doing hit-and-trial style debugging. This might be true because Java codebases are typically more substantial and more complex.

If you use a modern IDE or static code analysis tools, these can prevent many errors beforehand in both the languages, and be able to add breakpoints to inspect the variables during runtime.

Java has various popular libraries at various levels of abstraction (like JunitTestNGPowerMock) to unit-test your code. Python has a built-in unit test library whose design was inspired by Java's JUnit framework. Other higher-level frameworks for unit-testing in Python include pytest and nose. Unit testing in Python requires slightly more effort because of its dynamically typed nature.

When it comes to Behavior Driven Development, the most popular BDD framework in Python is behave, followed by pytest plugins like pytest-bdd. In Java, popular choices are Cucumber and SpockSelenium, the most popular web-automation testing framework, is primarily written in Java. It is easier to find solutions to your issues when you're using their Java API (Selenium has a Python API, too) to do things like end-to-end automation testing.

Documentation also helps in debugging and testing well. Python has a built-in doctest module that mixes well with the interactive nature of the language, as it helps in writing interactive statements in the documentation that serve the purpose of explaining as well as testing (this way you've fewer chances of outdated documentation). Similar functionality is very complex to replicate in Java.

Community

Python's community has been proliferating due to its suitability in domains beyond web applications (like Data Analytics, Image Processing, Machine Learning, and more). According to Github's Octoverse, Python was the second most used language on Github, followed by Java. In Stackoverflow's 2019 developer survey, Python was crowned the fastest-growing programming language edging out Java this year.

Who's using Java and Python in web development?

Below is a list of well-known companies that use Java in web development:

And here is a list of companies that use Python in web development:

Conclusion

In this article, we discussed the differences between Java and Python. We can safely say that both of these languages suitable server-side web-development. If you're about to build a very "enterprisey" web application where performance and security are critical, then Java still has the upper hand despite Python's fast-growing ecosystem. On the other hand, if you have experienced Python developers and care more about developer productivity, or have to deal with things like extensive number crunching, image processing, analytics, then Python has the edge over Java.