2010-02-18 15 views
15

Io uso questo pezzo di codice nel mio script per individuare, in modo cross-platform, esattamente dove è in fase di esecuzione da:come posso ottenere la directory corrente dell'eseguibile in py2exe?

SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__)) 

Abbastanza semplice. Successivamente, utilizzerò lo SCRIPT_ROOT in altre aree del mio script per assicurarmi che tutto sia correttamente relativo. Il mio problema si verifica quando lo eseguo tramite py2exe, perché l'eseguibile generato non imposta __file__, quindi il mio script si interrompe. Qualcuno sa come risolvere o aggirare questo?

+0

C'è una domanda duplicata precedente ma con meno risposte: [Determinazione del percorso dell'applicazione in un EXE Python generato da pyInstaller] (http://stackoverflow.com/questions/404744) – olibre

risposta

2

Prova questa:

import os 
import sys 
os.path.realpath(os.path.dirname(sys.argv[0])) 
+1

Nella mia esperienza, utilizzando 'sys.argv [ 0] 'non ha un percorso quando il programma viene trovato tramite la variabile PATH. – Ber

+0

@Ber, ... tuttavia, 'py2exe' è un caso speciale e lo imposta su un valore completo in tutti i casi. –

20

Ecco l'py2exe documentation reference e qui ci sono le voci pertinenti:

  • sys.executable è impostato per il percorso completo del file exe.
  • Il primo elemento in sys.argv è il percorso completo dell'eseguibile, il resto sono gli argomenti della riga di comando.
  • sys.frozen esiste solo nell'eseguibile. È impostato su "console_exe" per un eseguibile della console, su "windows_exe" per un eseguibile di gui senza console e su "dll" per un server di dll in elaborazione.
  • __file__ non è definito (si potrebbe desiderare di usare sys.argv [0] invece)

Non è Da tali documenti se "il file exe" e "l'eseguibile" sono la stessa cosa e quindi se sys.executable e sys.argv[0] sono la stessa cosa. Guardando il codice che ha lavorato sia per script.py e py2exe_executable.exe ultima volta che ho dovuto fare questo, trovo qualcosa di simile:

if hasattr(sys, 'frozen'): 
    basis = sys.executable 
else: 
    basis = sys.argv[0] 
required_folder = os.path.split(basis)[0] 

Come dico che ha funzionato, ma non mi ricordo perché ho pensato che era necessario invece di usare solo sys.argv[0].

Utilizzare solo basis era adeguato per il lavoro in corso (leggere i file in tale directory). Per una registrazione più permanente, dividi qualcosa come os.path.realpath(basis).

Aggiornamento Effettuato effettivamente un test; beat supposizione e pontificazione poltrona :-)

Riepilogo: Ignora sys.frozen, ignora sys.executable, vai con sys.argv [0] incondizionatamente.

Evidence:

=== === foo.py

# coding: ascii 
import sys, os.path 
print 'sys has frozen:', hasattr(sys, 'frozen') 
print 'using sys.executable:', repr(os.path.dirname(os.path.realpath(sys.executable))) 
print 'using sys.argv[0]:', repr(os.path.dirname(os.path.realpath(sys.argv[0] ))) 

=== setup.py ===

from distutils.core import setup 
import py2exe 
setup(console=['foo.py']) 

risultati === ===

C:\junk\so\py2exe>\python26\python foo.py 
sys has frozen: False 
using sys.executable: 'C:\\python26' 
using sys.argv[0]: 'C:\\junk\\so\\py2exe' # where foo.py lives 

C:\junk\so\py2exe>dist\foo 
sys has frozen: True 
using sys.executable: 'C:\\junk\\so\\py2exe\\dist' 
using sys.argv[0]: 'C:\\junk\\so\\py2exe\\dist' # where foo.exe lives 
+0

Credo che sys.executable di solito punta all'interprete python stesso, che è ciò che si vuole sotto py2exe, ma non altrimenti. – prestomation

+0

@prestomation: cosa significa "l'interprete Python stesso" nel caso py2exe? Cosa intendi con "ma non altrimenti"? –

+0

"altrimenti" è quando si esegue un file interpretato, che è la maggior parte degli ambienti. Nel caso py2exe, immagino che l'interprete sia il tuo py2exe, perché è incluso. Sembra che la tua modifica più recente lo confermi. – prestomation

8

py2exe non definisce __file__: http://www.py2exe.org/index.cgi/Py2exeEnvironment

Il PO ha richiesto una versione py2exe amichevole:

SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__)) 

La risposta migliore è determinare se python è congelato in un exe, py2exe ha docum entazione su questo: http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe

import imp, os, sys 

def main_is_frozen(): 
    return (hasattr(sys, "frozen") or # new py2exe 
      hasattr(sys, "importers") # old py2exe 
      or imp.is_frozen("__main__")) # tools/freeze 

def get_main_dir(): 
    if main_is_frozen(): 
     return os.path.dirname(sys.executable) 
    return os.path.dirname(os.path.realpath(__file__)) 

SCRIPT_ROOT = get_main_dir() 

Dal momento che, il pitone è EAFP, ecco una versione EAFP ...

try: 
    if sys.frozen or sys.importers: 
     SCRIPT_ROOT = os.path.dirname(sys.executable) 
except AttributeError: 
    SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__)) 

Cheers!

+0

@Ber hai ragione ... Avrei dovuto leggere più attentamente. Meglio? – VertigoRay

+1

Questo è ESATTAMENTE quello che la domanda ha chiesto. Grazie per la grande soluzione. –

Problemi correlati