Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

improving speed of Python module import

The question of how to speed up importing of Python modules has been asked previously (Speeding up the python "import" loader and Python -- Speed Up Imports?) but without specific examples and has not yielded accepted solutions. I will therefore take up the issue again here, but this time with a specific example.

I have a Python script that loads a 3-D image stack from disk, smooths it, and displays it as a movie. I call this script from the system command prompt when I want to quickly view my data. I'm OK with the 700 ms it takes to smooth the data as this is comparable to MATLAB. However, it takes an additional 650 ms to import the modules. So from the user's perspective the Python code runs at half the speed.

This is the series of modules I'm importing:

import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation import scipy.ndimage import scipy.signal import sys import os 

Of course, not all modules are equally slow to import. The chief culprits are:

matplotlib.pyplot   [300ms] numpy               [110ms] scipy.signal        [200ms] 

I have experimented with using from, but this isn't any faster. Since Matplotlib is the main culprit and it's got a reputation for slow screen updates, I looked for alternatives. One is PyQtGraph, but that takes 550 ms to import.

I am aware of one obvious solution, which is to call my function from an interactive Python session rather than the system command prompt. This is fine but it's too MATLAB-like, I'd prefer the elegance of having my function available from the system prompt.

I'm new to Python and I'm not sure how to proceed at this point. Since I'm new, I'd appreciate links on how to implement proposed solutions. Ideally, I'm looking for a simple solution (aren't we all!) because the code needs to be portable between multiple Mac and Linux machines.

like image 392
RAAC Avatar asked May 04 '13 10:05

RAAC


People also ask

Is there a way to speed up Python?

Use the Built-In Functions Many of Python's built-in functions are written in C, which makes them much faster than a pure python solution. Take a very simple task of summing a lot of numbers. We could loop through each number, summing as we go.

Do imports slow down Python?

Startup and Module Importing Overhead. Starting a Python interpreter and importing Python modules is relatively slow if you care about milliseconds. If you need to start hundreds or thousands of Python processes as part of a workload, this overhead will amount to several seconds of overhead.


2 Answers

Not an actual answer to the question, but a hint on how to profile the import speed with Python 3.7 and tuna (a small project of mine):

python3 -X importtime -c "import scipy" 2> scipy.log tuna scipy.log 

enter image description here

like image 65
Nico Schlömer Avatar answered Sep 21 '22 09:09

Nico Schlömer


you could build a simple server/client, the server running continuously making and updating the plot, and the client just communicating the next file to process.

I wrote a simple server/client example based on the basic example from the socket module docs: http://docs.python.org/2/library/socket.html#example

here is server.py:

# expensive imports import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation import scipy.ndimage import scipy.signal import sys import os  # Echo server program import socket  HOST = ''                 # Symbolic name meaning all available interfaces PORT = 50007              # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) while 1:     conn, addr = s.accept()     print 'Connected by', addr     data = conn.recv(1024)     if not data: break     conn.sendall("PLOTTING:" + data)     # update plot     conn.close() 

and client.py:

# Echo client program import socket import sys  HOST = ''    # The remote host PORT = 50007              # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall(sys.argv[1]) data = s.recv(1024) s.close() print 'Received', repr(data) 

you just run the server:

python server.py 

which does the imports, then the client just sends via the socket the filename of the new file to plot:

python client.py mytextfile.txt 

then the server updates the plot.

On my machine running your imports take 0.6 seconds, while running client.py 0.03 seconds.

like image 38
Andrea Zonca Avatar answered Sep 20 '22 09:09

Andrea Zonca