2013-05-04 12 views
21

La domanda su come accelerare l'importazione dei moduli Python è stata precedentemente richiesta (Speeding up the python "import" loader e Python -- Speed Up Imports?) ma senza esempi specifici e non ha prodotto soluzioni accettate. Pertanto riprenderò il problema qui, ma questa volta con un esempio specifico.miglioramento della velocità dell'importazione del modulo Python

Ho uno script Python che carica uno stack di immagini 3D dal disco, lo ammorbidisce e lo visualizza come film. Io chiamo questo script dal prompt dei comandi di sistema quando voglio visualizzare rapidamente i miei dati. Sto bene con i 700 ms necessari per appianare i dati in quanto è paragonabile a MATLAB. Tuttavia, occorrono altri 650 ms per importare i moduli. Quindi dal punto di vista dell'utente il codice Python funziona a metà della velocità.

Questa è la serie di moduli che sto importando:

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

Naturalmente, non tutti i moduli sono ugualmente lento da importare. I colpevoli principali sono:

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

ho sperimentato con l'utilizzo di from, ma questo non è più veloce. Dal momento che Matplotlib è il principale colpevole e ha una reputazione per gli aggiornamenti a schermo lento, ho cercato delle alternative. Uno è PyQtGraph, ma per l'importazione occorrono 550 ms.

Sono a conoscenza di una soluzione ovvia, ovvero chiamare la mia funzione da una sessione Python interattiva anziché dal prompt dei comandi di sistema. Questo va bene, ma è troppo MATLAB-like, preferirei l'eleganza di avere la mia funzione disponibile dal prompt di sistema.

Sono nuovo di Python e non sono sicuro di come procedere a questo punto. Dato che sono nuovo, gradirei link su come implementare le soluzioni proposte. Idealmente, sto cercando una soluzione semplice (non lo siamo tutti!) Perché il codice deve essere portatile tra più macchine Mac e Linux.

+0

Controllare che sta producendo versioni .pyc dei moduli Python - loading questi è un po 'più veloce. Ma quei numeri sono abbastanza plausibili anche se i file pyc ci sono. –

+0

Inoltre, se hai molte directory .egg su 'sys.path', cerca i moduli all'interno di ognuno, il che rallenta le cose. Utilizzare un gestore di pacchetti di distribuzione o un pip per installarli in un layout migliore. È improbabile che tu abbia una maggiore accelerazione, comunque. –

+0

Avevo notato il suggerimento del pyc in una domanda precedente, ma non so dove cercare le versioni pyc dei moduli. In questo momento sono su un Mac. – RAAC

risposta

9

è possibile creare un semplice server/client, il server che esegue continuamente la creazione e l'aggiornamento della trama e il client che comunica semplicemente il file successivo da elaborare.

Ho scritto un esempio server/client semplice sull'esempio base dalla documentazione dei moduli socket: http://docs.python.org/2/library/socket.html#example

qui è 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() 

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

è sufficiente eseguire il server:

python server.py 

che fa le importazioni, il client invia solo attraverso la presa il nome del nuovo file per tracciare:

python client.py mytextfile.txt 

allora il server aggiorna la trama.

Sulla mia macchina in esecuzione le importazioni richiedono 0,6 secondi, mentre in esecuzione client.py 0,03 secondi.

+1

btw, per la stampa, puoi dare un'occhiata a 'chaco': https://pypi.python.org/pypi/chaco –

+0

Grazie, penso che la tua soluzione sia probabilmente la strada da percorrere. Da allora ho cambiato il mio codice in PyQtGraph, perché è più veloce di Matplotlib nel generare i grafici dinamici che sto producendo. Anche Chaco vale la pena dare un'occhiata. – RAAC

0

1.35 secondi non è lungo, ma suppongo che se sei abituato a metà per un "controllo rapido" allora forse sembra così.

Andrea suggerisce una semplice configurazione client/server, ma mi sembra che si potrebbe chiamare la stessa facilità con una leggera modifica del vostro script e mantenere la sua finestra di console aperta mentre si lavora:

  • chiamata la script, che fa le importazioni quindi attende ingresso
  • Minimizzare la finestra della console, passare al lavoro, qualunque: * fare lavoro *
  • Selezionare la console di nuovo
  • Fornire lo script con una sorta di ingresso
  • ricevere i risultati senza spese generali di importazione
  • Passare dalla sceneggiatura di nuovo mentre attende felicemente ingresso

presumo lo script è identico ogni volta, vale a dire che non è necessario dare luogo serie di immagini o ogni particolare comando ogni volta (ma anche questi sono facili da fare!).

Esempio 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!) 
    * 
    * 
    ''' 

Per terminare lo script, chiudere la finestra della console o premere CTRL + C.

Ho fatto questo più semplice possibile, ma richiederebbe molto poco in più per gestire le cose come smettere bene, fare le cose leggermente diverse in base all'input, ecc

2

È possibile importare i moduli manualmente, invece, utilizzando imp. Vedi documentation here.

Per esempio, import numpy as np potrebbe probabilmente essere scritto come

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

Questo risparmierà pitone da navigare l'intera sys.path per trovare i pacchetti desiderati.

Consulta anche:

Manually importing gtk fails: module not found

Problemi correlati