web-dev-qa-db-fra.com

amélioration de la vitesse d'importation du module Python

La question de savoir comment accélérer l’importation de modules Python a déjà été posée ( Accélérer le chargeur "import" de python et Python - Accélérer les importations? ) mais sans exemple spécifique et n’a pas été acceptée solutions. Je vais donc reprendre la question ici, mais cette fois avec un exemple spécifique. 

J'ai un script Python qui charge une pile d'images 3D à partir du disque, le lisse et l'affiche sous forme de film. J'appelle ce script à partir de la commande système Invite lorsque je souhaite visualiser rapidement mes données. Je suis d'accord avec les 700 ms nécessaires pour lisser les données, ce qui est comparable à MATLAB. Cependant, il faut 650 ms supplémentaires pour importer les modules. Ainsi, du point de vue de l'utilisateur, le code Python s'exécute à la moitié de la vitesse.

Voici la série de modules que j'importe:

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

Bien entendu, tous les modules ne sont pas tous aussi lents à importer. Les principaux coupables sont:

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

J'ai essayé d'utiliser from, mais ce n'est pas plus rapide. Puisque Matplotlib est le principal coupable et qu'il est réputé pour ses mises à jour d'écran lentes, j'ai cherché des alternatives. On est PyQtGraph, mais cela prend 550 ms pour importer. 

Je connais une solution évidente, qui consiste à appeler ma fonction depuis une session Python interactive plutôt que la commande système Invite. C'est bien, mais c'est trop MATLAB, je préférerais l'élégance de pouvoir utiliser ma fonction depuis le système Prompt. 

Je suis nouveau sur Python et je ne sais pas comment procéder à ce stade. Depuis que je suis nouvelle, j'apprécierais des liens sur la façon de mettre en œuvre les solutions proposées. Idéalement, je recherche une solution simple (ne le sommes-nous pas tous!), Car le code doit être portable entre plusieurs ordinateurs Mac et Linux. 

23
RAAC

vous pouvez créer un serveur/client simple, le serveur en fonctionnement continu créant et mettant à jour le tracé, et le client communiquant simplement le fichier suivant à traiter.

J'ai écrit un exemple simple de serveur/client basé sur l'exemple de base tiré de la documentation du module socket: http://docs.python.org/2/library/socket.html#example

voici 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()

et 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)

vous venez de lancer le serveur:

python server.py

qui fait les importations, le client envoie simplement via le socket le nom du nouveau fichier à tracer:

python client.py mytextfile.txt

alors le serveur met à jour l'intrigue.

Sur ma machine, les importations prennent 0,6 seconde, alors que client.py 0,03 seconde est exécuté.

11
Andrea Zonca

Pas une réponse réelle à la question, mais un conseil sur la manière de déterminer la vitesse d’importation avec Python 3.7 et thon (un petit projet minier):

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

 enter image description here

3
Nico Schlömer

Vous pouvez importer vos modules manuellement à la place, en utilisant imp. Voir documentation ici .

Par exemple, import numpy as np pourrait probablement être écrit comme

import imp
np = imp.load_module("numpy",None,"/usr/lib/python2.7/dist-packages/numpy",('','',5))

Cela évitera à python de parcourir l'intégralité de votre sys.path afin de trouver les packages souhaités.

Voir également:

Echec de l'importation manuelle de gtk: module introuvable

2
Blauhirn

1,35 seconde n'est pas long, mais je suppose que si vous avez l'habitude de réduire de moitié ce temps pour un "contrôle rapide", cela semble peut-être le cas.

Andrea suggère une configuration client/serveur simple, mais il me semble que vous pouvez tout aussi facilement appeler une très légère modification de votre script et garder sa fenêtre de console ouverte pendant que vous travaillez:

  • Appelez le script, qui fait les importations puis attend l'entrée
  • Réduisez la fenêtre de la console, passez à votre travail, peu importe: * Faites le travail *
  • Sélectionnez à nouveau la console
  • Fournir au script une sorte de saisie
  • Recevez les résultats sans surcoût d'importation
  • Quittez le script à nouveau pendant qu'il attend les entrées avec joie

Je suppose que votre script est identique à chaque fois, c’est-à-dire qu’il n’est pas nécessaire de lui donner à chaque fois l’emplacement de la pile d’images ou des commandes particulières (mais elles sont aussi faciles à faire!). 

Exemple RAAC's_Script.py:

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

print('********* RAAC\'s Script Now Running *********')

while True: # Loops forever
    # Display a message and wait for user to enter text followed by enter key.
    # In this case, we're not expecting any text at all and if there is any it's ignored
    input('Press Enter to test image stack...')

    '''
    *
    *
    **RAAC's Code Goes Here** (Make sure it's indented/inside the while loop!)
    *
    *
    '''

Pour terminer le script, fermez la fenêtre de la console ou appuyez sur ctrl + c.

C’est aussi simple que possible, mais il faudrait très peu d’argent pour gérer des choses comme cesser de fumer gentiment, faire des choses légèrement différentes en fonction des suggestions, etc.

0
ElectricWarr