2013-05-04 20 views
21

Pytanie o to, jak przyspieszyć importowanie modułów Pythona zostało zadane wcześniej (Speeding up the python "import" loader i Python -- Speed Up Imports?), ale bez konkretnych przykładów i nie przyniosło akceptowalnych rozwiązań. W związku z tym przejdę do tej kwestii ponownie, ale tym razem z konkretnym przykładem.poprawa szybkości importu modułu Python

Mam skrypt w języku Python, który ładuje stos obrazów 3D z dysku, wygładza go i wyświetla jako film. Wywołuję ten skrypt z wiersza poleceń systemu, gdy chcę szybko wyświetlić moje dane. Jestem w porządku z 700 ms, które zajmuje wygładzenie danych, ponieważ jest to porównywalne z MATLAB. Jednak importowanie modułów zajmuje dodatkowe 650 ms. Z perspektywy użytkownika kod Pythona działa z połową prędkości.

Jest to seria modułów jestem importowania:

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

Oczywiście, nie wszystkie moduły są równie wolno importować. Główni winowajcy są:

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

I eksperymentowali z użyciem from, ale nie jest to szybciej. Ponieważ Matplotlib jest głównym winowajcą i ma reputację powolnych aktualizacji ekranu, szukałem alternatyw. Jednym z nich jest PyQtGraph, ale importowanie trwa 550 ms.

Jestem świadomy jednego oczywistego rozwiązania, które polega na wywoływaniu mojej funkcji z interaktywnej sesji w Pythonie, a nie w wierszu poleceń systemu. To jest w porządku, ale jest zbyt podobna do MATLAB-u, wolałabym elegancję polegającą na tym, aby moja funkcja była dostępna z systemu.

Jestem nowy w Pythonie i nie jestem pewien, jak postępować w tym momencie. Ponieważ jestem nowy, chciałbym docenić linki na temat wdrażania proponowanych rozwiązań. Idealnie, szukam prostego rozwiązania (nie wszyscy jesteśmy!), Ponieważ kod musi być przenośny pomiędzy wieloma komputerami Mac i Linux.

+0

Sprawdź, czy to produkcji .pyc wersje modułów Pythona - Loading tych jest nieco szybciej. Ale te liczby są całkiem prawdopodobne, nawet jeśli istnieją pliki Pyc. –

+0

Ponadto, jeśli masz dużo katalogów .egg na 'sys.path', szuka modułów wewnątrz każdego, co spowalnia działanie. Użyj menedżera pakietów dystrybucyjnych lub pip, aby zainstalować je w lepszym układzie. Jednak mało prawdopodobne jest, że przyspieszysz. –

+0

Zauważyłem sugestię pyc we wcześniejszym pytaniu, ale nie wiem, gdzie szukać wersji modułów pyc. Teraz jestem na Macu. – RAAC

Odpowiedz

9

można zbudować prosty serwer/klient, serwer działający na bieżąco i aktualizujący wykres, a klient po prostu komunikuje następny plik do przetworzenia.

Napisałem prosty przykład serwer/klient oparty na prostym przykładzie z docs modułu socket: http://docs.python.org/2/library/socket.html#example

tutaj jest 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() 

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

wystarczy uruchomić serwer:

python server.py 

która robi importu, klient po prostu wysyła za pośrednictwem gniazda nazwa pliku nowego pliku do działki:

python client.py mytextfile.txt 

następnie serwer aktualizuje wykres.

Na komputerze, na którym trwa import, trwa to 0,6 sekundy, a uruchomienie client.py 0,03 sekundy.

+1

btw, do kreślenia, możesz rzucić okiem na 'chaco': https://pypi.python.org/pypi/chaco –

+0

Dzięki, myślę, że twoje rozwiązanie jest prawdopodobnie drogą do zrobienia. Od tego czasu zmieniłem mój kod na PyQtGraph, ponieważ jest on szybszy niż Matplotlib przy generowaniu dynamicznych wykresów, które produkuję. Chaco z pewnością też jest warte odwiedzenia. – RAAC

0

1.35 sekund nie jest długa, ale przypuszczam, że jeśli przyzwyczaisz się do tego o połowę za "szybką kontrolę", być może wydaje się, że tak.

Andrea sugeruje prostą konfigurację klient/serwer, ale wydaje mi się, że można tak łatwo wywołać bardzo nieznaczną modyfikację skryptu i zachować to okno konsoli otwarte podczas pracy:

  • Wywołać skrypt, który robi importu następnie czeka na wejście
  • zminimalizować okno konsoli, przełącz się do swojej pracy, bez względu na: * Czy praca *
  • Wybierz konsolę ponownie
  • Zapewnić scenariusz z jakiegoś wejścia
  • Otrzymuj wyniki z importu bez narzutu
  • Przełącznik dala od skryptu ponownie podczas gdy szczęśliwie czeka moc wejściowa

I zakładamy, że skrypt jest identyczny w każdym czasie, to znaczy nie trzeba nadać mu położenie obrazu stosu lub za każdym razem jakieś specjalne polecenia (ale te są łatwe do wykonania!).

Przykład 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!) 
    * 
    * 
    ''' 

Aby zakończyć scenariusz zamknąć konsolę lub nacisnąć klawisze Ctrl + C.

Zrobiłem to tak proste, jak to możliwe, ale wymagałoby to bardzo niewiele dodatkowy obsłużyć rzeczy jak rzucenie ładnie, lekko robi różne rzeczy na podstawie danych wejściowych, itp

2

Można importować moduły zamiast ręcznie, przy użyciu imp. Zobacz documentation here.

Na przykład import numpy as np prawdopodobnie mógłby być zapisany jako

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

To oszczędzi pytona od przeglądania całego sys.path aby znaleźć żądane pakiety.

Zobacz także:

Manually importing gtk fails: module not found