2009-03-03 15 views
46

Załóżmy, że mam dwa moduły:Jak uzyskać nazwę pliku modułu __main__ w Pythonie?

a.py:

import b 
print __name__, __file__ 

b.py:

print __name__, __file__ 

uruchomić "a.py" plik. Drukuje:

b  C:\path\to\code\b.py 
__main__ C:\path\to\code\a.py 

pytanie: Jak mogę uzyskać ścieżkę do modułu __main__ („a.py” w tym przypadku) z poziomu „b.py” biblioteki?

Odpowiedz

58
import __main__ 
print __main__.__file__ 
+1

Schludny! Ważne, aby zdać sobie sprawę, że trzeba zaimportować __main__ - zrobiłem losowe zgadywanie i faktycznie wypróbowałem drugą linię, ale nie udało się - teraz już wiem dlaczego. –

+17

'__main__' nie zawsze ma atrybut' __file__'. – jfs

+0

Tak, byłoby miło, gdyby można było zaktualizować odpowiedź, aby o tym wspomnieć. –

27

Być może będzie to rade:

import sys 
from os import path 
print path.abspath(sys.modules['__main__'].__file__) 

pamiętać, że ze względów bezpieczeństwa należy sprawdzić, czy moduł __main__ posiada atrybut __file__. Jeśli jest tworzone dynamicznie, albo jest tylko uruchamiany na interaktywnej konsoli Pythona, to nie będzie miał __file__:

python 
>>> import sys 
>>> print sys.modules['__main__'] 
<module '__main__' (built-in)> 
>>> print sys.modules['__main__'].__file__ 
AttributeError: 'module' object has no attribute '__file__' 

Prosty hasattr() check rade aby ustrzec się przed scenariuszem 2, jeżeli taka możliwość w Twojej aplikacji.

+0

To robi - dzięki! –

+0

Wunderbar! Cieszę się że mogłem pomóc. Jeśli to odpowiada na twoje pytanie, czy mógłbybyś nacisnąć przycisk "zaakceptuj" na pytanie? :-) –

+0

Jeśli zmienisz to, aby użyć stylu "importować __main__", zmienię go z powrotem na akceptowany, ponieważ jest bardziej szczegółowy niż nowa zaakceptowana odpowiedź. –

14

Poniższy kod Pythona zapewnia dodatkową funkcjonalność, w tym, że działa bezproblemowo z plikami wykonywalnymi py2exe.

Używam podobnego kodu, aby to polubić, aby znaleźć ścieżki w odniesieniu do działającego skryptu, czyli __main__. jako dodatkowa korzyść działa na wielu platformach, w tym w systemie Windows.

import imp 
import os 
import 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(): 
     # print 'Running from path', os.path.dirname(sys.executable) 
     return os.path.dirname(sys.executable) 
    return os.path.dirname(sys.argv[0]) 

# find path to where we are running 
path_to_script=get_main_dir() 

# OPTIONAL: 
# add the sibling 'lib' dir to our module search path 
lib_path = os.path.join(get_main_dir(), os.path.pardir, 'lib') 
sys.path.insert(0, lib_path) 

# OPTIONAL: 
# use info to find relative data files in 'data' subdir 
datafile1 = os.path.join(get_main_dir(), 'data', 'file1') 

Mam nadzieję, że powyższy przykład kod może zapewnić dodatkowy wgląd w jaki sposób określić ścieżkę do skryptu uruchomiony ...

+1

Jeśli zmienisz katalog (z' os.chdir') pomiędzy uruchomieniem skrypt i wywołanie 'os.dirname (sys.argv [0])' wynik jest bez znaczenia. – RobM

+0

Używam do stworzenia modułu 'GLOBALS.py', który jest przynajmniej importowany przez główny skrypt, który wykonuje coś podobnego do powyższego kodu i przechowuje wynik w zmiennej' MAINDIR', więc mogę wtedy uzyskać dostęp do 'GLOBALS.MAINDIR' z dowolnego innego modułu, bez obawy o użycie 'os.chdir'. – Remi

+0

Jeśli chcesz poznać katalog początkowy skryptu i chcesz również użyć 'os.chdir()', będziesz chciał zapisać początkowe 'os.getcwd()'. Ponieważ użytkownik był w systemie Windows, chciałem zademonstrować coś, co nadal działałoby w kontekście py2exe i freeze. – popcnt

1
import sys, os 

def getExecPath(): 
    try: 
     sFile = os.path.abspath(sys.modules['__main__'].__file__) 
    except: 
     sFile = sys.executable 
    return os.path.dirname(sFile) 

Funkcja ta będzie działać dla Python i Cython skompilowanych programów.

6

Inną metodą byłoby użycie sys.argv[0].

import os 
import sys 

main_file = os.path.realpath(sys.argv[0]) if sys.argv[0] else None 

sys.argv[0] będzie pusty ciąg jeśli Python dostaje zacząć -c czy sprawdzane z konsoli Pythona.

Powiązane problemy