2009-10-04 11 views
26

Questa è una domanda molto semplice - ma non sono stato in grado di trovare una risposta cercando online.python refresh/reload

Sto usando python per controllare ArcGIS e ho un semplice script python che chiama un codice pre-scritto.

Tuttavia, quando apporto una modifica al codice pre-scritto, non sembra che comporti alcuna modifica. Importo questo modulo e ho provato ad aggiornarlo, ma non succede nulla.

Ho persino spostato il file che chiama in un'altra posizione e lo script funziona ancora correttamente. Una cosa che ho fatto ieri è stata l'aggiunta della cartella in cui tutti i miei file python si trovano sul percorso sys (usando sys.append ('path')), e mi chiedo se questo abbia fatto la differenza.

Grazie in anticipo, e mi dispiace per la terminologia sciatta.

risposta

31

Non è chiaro che cosa si intende con "refresh", ma il comportamento normale di Python è che è necessario riavviare il software per esso per dare una nuova occhiata a un modulo Python e rileggerlo.

Se le modifiche non è curato, anche dopo il riavvio, allora questo è dovuto a uno dei due errori:

  1. Il timestamp sul PYC file non è corretto e un po 'di tempo in futuro.
  2. In realtà stai modificando il file sbagliato.

È possibile ricaricare con rilettura un file anche senza riavviare il software con il comando reload(). Nota che qualsiasi variabile che punta a qualcosa nel modulo dovrà essere reimportata dopo il ricaricamento. Qualcosa di simile a questo:

import themodule 
from themodule import AClass 

reload(themodule) 
from themodule import AClass 
+0

Ho avuto un problema simile e questo ha fatto il trucco. Ho notato che rimuovere il primo 'da themodule import AClass' continua a fare il trucco. Qualche ragione per avere entrambi? – pentandrous

+0

Non è davvero "un trucco" per risolvere un problema, e il tuo problema reale viene da qualche altra parte. Dovresti provare a risolvere quello invece. –

19

Un modo per fare ciò è chiamare reload.

Esempio: Ecco il contenuto della foo.py:

def bar(): 
    return 1 

In una sessione interattiva, posso fare:

>>> import foo 
>>> foo.bar() 
1 

Poi in un'altra finestra, posso cambiare foo.py a:

def bar(): 
    return "Hello" 

Indietro nella sessione interattiva, chiamando foo.bar() ancora gira 1, fino a quando lo faccio:

>>> reload(foo) 
<module 'foo' from 'foo.py'> 
>>> foo.bar() 
'Hello' 

Calling reload è un modo per garantire che il modulo è up-to-date, anche se il file sul disco è cambiato. Non è necessariamente il più efficiente (potrebbe essere meglio controllare l'ultima modifica sul file o utilizzare qualcosa come pyinotify prima di reload), ma è certamente veloce da implementare.

Uno dei motivi per cui Python non legge il modulo sorgente ogni volta è che il caricamento di un modulo è (relativamente) costoso: cosa succede se si dispone di un modulo da 300 kb e si stesse utilizzando una singola costante dal file? Python carica un modulo una volta e lo conserva in memoria, fino a quando non lo fai reload.

1

Non sono proprio sicuro che sia ciò che intendi, quindi non esitare a correggermi. Stai importando un modulo - chiamiamolo mymodule.py - nel tuo programma, ma quando cambi il suo contenuto, non vedi la differenza?

Python non cercherà le modifiche in mymodule.py ogni volta che verrà utilizzato, lo caricherà per la prima volta, lo compilerà in bytecode e lo manterrà internamente. Normalmente salverà anche il bytecode compilato (mymodule.pyc). La prossima volta che avvierai il tuo programma, controllerà se mymodule.py è più recente di mymodule.pyc e ricompilalo se necessario.

Se è necessario, è possibile ricaricare il modulo in modo esplicito:

import mymodule 

[... some code ...] 

if userAskedForRefresh: 
    reload(mymodule) 

Naturalmente, è più complicato di così e si può avere effetti collaterali a seconda di quello che fate con il vostro programma per quanto riguarda l'altra modulo, ad esempio se le variabili dipendono dalle classi definite in mymodule.

In alternativa, è possibile utilizzare la funzione execfile (o exec(), eval(), compile())

+0

Grazie a tutti per le vostre risposte. Ho provato a usare ricaricare e chiudere/riaprire il programma. Il problema è stato causato da un file con lo stesso nome, nel codice originale. Anche se pensavo di importarlo da una nuova posizione, utilizzava ancora il vecchio file. – womble

3

ho usato il seguente quando si importano tutti gli oggetti all'interno di un modulo per garantire web2py stava usando il mio codice corrente:

import buttons 
import table 
reload(buttons) 
reload(table) 
from buttons import * 
from table import * 
0

Ho avuto lo stesso problema esatto creazione di uno script di geoprocessing per ArcGIS 10.2. Ho avuto uno script di Python Toolbox, uno script di strumenti e uno script comune. Ho un parametro per Dev/Test/Prod nello strumento che controllerebbe quale versione del codice è stata eseguita. Dev eseguirà il codice nella cartella dev, test dalla cartella test e prod dalla cartella prod. Le modifiche allo script di sviluppo comune non venivano eseguite quando lo strumento veniva eseguito da ArcCatalog. La chiusura di ArcCatalog non ha fatto alcuna differenza. Anche se ho selezionato Dev o Test, è sempre stato eseguito dalla cartella prod.

L'aggiunta del ricaricamento (myCommonModule) allo script dello strumento ha risolto questo problema.

3

Se si utilizza una shell IPython, esistono alcuni comandi magici.

I documenti IPython coprono questa funzione denominata autoreload extension.

Originariamente, ho trovato questa soluzione da Jonathan March's blog posting on this very subject (vedere il punto 3 da quel collegamento).

In pratica tutto quello che dovete fare è il seguente, e le modifiche apportate si riflettono automaticamente dopo aver salvato:

In [1]: %load_ext autoreload 

In [2]: %autoreload 2 

In [3]: Import MODULE 

In [4]: my_class = Module.class() 
     my_class.printham() 
Out[4]: ham 

In [5]: #make changes to printham and save 
In [6]: my_class.printham() 
Out[6]: hamlet