Importowanie modułu ze ścieżki względnej

Jak zaimportować moduł Pythona ze względu na jego względną ścieżkę?

Na przykład, jeśli dirFoo zawiera Foo.py i dirBar, a dirBar zawiera Bar.py, Jak zaimportować Bar.py do Foo.py?

Oto wizualna reprezentacja:

dirFoo\
    Foo.py
    dirBar\
        Bar.py

Foo chce dołączyć Bar, ale restrukturyzacja hierarchii folderów nie wchodzi w grę.

Author: Peter Mortensen, 2008-11-11

23 answers

Zakładając, że oba katalogi są prawdziwymi pakietami Pythona (mają w sobie plik __init__.py), Oto bezpieczne rozwiązanie dla włączenia modułów w stosunku do lokalizacji skryptu.

Zakładam, że chcesz to zrobić, ponieważ musisz dołączyć zestaw modułów do swojego skryptu. Używam tego w produkcji w kilku produktach i działa w wielu specjalnych scenariuszach, takich jak: skrypty wywołane z innego katalogu lub wykonane z Pythona wykonać zamiast otwierania nowego Tłumacz.

 import os, sys, inspect
 # realpath() will make your script run, even if you symlink it :)
 cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
 if cmd_folder not in sys.path:
     sys.path.insert(0, cmd_folder)

 # Use this if you want to include modules from a subfolder
 cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
 if cmd_subfolder not in sys.path:
     sys.path.insert(0, cmd_subfolder)

 # Info:
 # cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
 # __file__ fails if the script is called in different ways on Windows.
 # __file__ fails if someone does os.chdir() before.
 # sys.argv[0] also fails, because it doesn't not always contains the path.

Jako bonus, to podejście pozwala zmusić Pythona do używania Twojego modułu zamiast tych zainstalowanych w systemie.

Uwaga! Nie wiem, co się dzieje, gdy bieżący moduł znajduje się w pliku egg. To pewnie też zawiedzie.
 314
Author: sorin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 13:55:41

Upewnij się, że dirBar ma Plik __init__.py -- to sprawia, że katalog staje się pakietem Pythona.

 317
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 21:33:33

Możesz również dodać podkatalog do ścieżki Pythona, aby zaimportował go jako zwykły skrypt.

import sys
sys.path.insert(0, <path to dirFoo>)
import Bar
 245
Author: Andrew Cox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 21:42:26
import os
import sys
lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))
sys.path.append(lib_path)

import mymodule
 110
Author: lefakir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-26 06:35:49

Po prostu zrób proste rzeczy, aby zaimportować plik. py z innego folderu.

Powiedzmy, że masz katalog w stylu:

lib/abc.py

Następnie zachowaj pusty plik w folderze lib o nazwie

__init__.py

A następnie użyj

from lib.abc import <Your Module name>

Przechowuj plik __init__.py w każdym folderze hierarchii modułu importu.

 94
Author: Deepak 'Kaseriya',
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 14:17:21

Jeśli tak skonstruujesz swój projekt:

src\
  __init__.py
  main.py
  dirFoo\
    __init__.py
    Foo.py
  dirBar\
    __init__.py
    Bar.py

Następnie od Foo.py powinieneś umieć:

import dirFoo.Foo

Lub:

from dirFoo.Foo import FooObject

Zgodnie z komentarzem Toma wymaga to, aby folder src był dostępny przez site_packages lub ścieżkę wyszukiwania. Ponadto, jak wspomina, {[5] } jest domyślnie importowane, gdy po raz pierwszy importujesz moduł z tego katalogu / pakietu. Zazwyczaj __init__.py jest po prostu pustym plikiem.

 77
Author: bouvard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 13:57:24

Najprostszą metodą jest użycie sys./ align = "left" / append ().

Jednak może cię również zainteresować moduł imp . Zapewnia dostęp do wewnętrznych funkcji importu.

# mod_name is the filename without the .py/.pyc extention
py_mod = imp.load_source(mod_name,filename_path) # Loads .py file
py_mod = imp.load_compiled(mod_name,filename_path) # Loads .pyc file 

Może być używany do dynamicznego ładowania modułów, gdy nie znasz nazwy modułu.

Używałem tego w przeszłości do tworzenia interfejsu typu wtyczki do aplikacji, gdzie użytkownik napisałby skrypt z konkretnymi funkcjami aplikacji i po prostu upuścił skrypt w określonym katalog.

Również te funkcje mogą być przydatne:

imp.find_module(name[, path])
imp.load_module(name, file, pathname, description)
 44
Author: monkut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-12 01:56:51

To jest odpowiedni PEP:

Http://www.python.org/dev/peps/pep-0328/

W szczególności, zakładając, że dirFoo jest katalogiem w górę od dirbara...

W dirFoo\Foo.py:

from ..dirBar import Bar
 41
Author: Peter Crabtree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 22:22:47

Najprostszym sposobem Bez Modyfikacji skryptu jest ustawienie zmiennej środowiskowej PYTHONPATH. Ponieważ sys.ścieżka jest inicjalizowana z tych lokalizacji:

  1. katalog zawierający skrypt wejściowy (lub bieżący katalog).
  2. PYTHONPATH (lista nazw katalogów, z tym samym składni jako ścieżka zmiennej powłoki).
  3. domyślna zależna od instalacji.

Just run:

export PYTHONPATH=/absolute/path/to/your/module
Ty sys.ścieżka będzie zawierać powyższą ścieżkę, jak pokazano poniżej:
print sys.path

['', '/absolute/path/to/your/module', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
 21
Author: James Gan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 14:06:14

Moim zdaniem najlepszym wyborem jest umieszczenie _ _ init__. py w folderze i wywołanie pliku za pomocą

from dirBar.Bar import *

Nie zaleca się używania sys./ align = "left" / append (), ponieważ coś może pójść nie tak, jeśli użyjesz tej samej nazwy pliku, co istniejący pakiet Pythona. Nie testowałem tego, ale to będzie dwuznaczne.

 11
Author: jhana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-15 05:02:52

Szybki i brudny sposób dla użytkowników Linuksa

Jeśli tylko majstrujesz i nie przejmujesz się problemami z wdrożeniem, możesz użyć dowiązania symbolicznego (zakładając, że Twój system plików go obsługuje), aby moduł lub pakiet był widoczny bezpośrednio w folderze modułu żądającego.

ln -s (path)/module_name.py

Lub

ln -s (path)/package_name

Uwaga: "moduł" to każdy plik z rozszerzeniem. py, a "pakiet" to każdy folder zawierający plik __init__.py (który może być pustym plikiem). Z użytkowania z punktu widzenia, moduły i pakiety są identyczne - oba ujawniają zawarte w nich" definicje i instrukcje " zgodnie z żądaniem polecenia import.

Zobacz: http://docs.python.org/2/tutorial/modules.html

 10
Author: nobar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-20 01:07:43
from .dirBar import Bar

Zamiast:

from dirBar import Bar

Na wszelki wypadek mógłby być zainstalowany inny dirBar i mylić foo.py czytelniku.

 9
Author: jgomo3,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-07 14:48:30

W tym przypadku do importu Bar.py do Foo.py, najpierw zamieniłbym te foldery na pakiety Pythona tak:

dirFoo\
    __init__.py
    Foo.py
    dirBar\
        __init__.py
        Bar.py

Wtedy zrobiłbym to tak w Foo.py:

from .dirBar import Bar

Gdybym chciał, żeby przestrzeń nazw wyglądała jak Bar.cokolwiek , lub

from . import dirBar

Gdybym chciał dirBar przestrzeni nazw.Bar.cokolwiek . Ten drugi przypadek jest przydatny, jeśli masz więcej modułów pod pakietem dirBar.

 7
Author: Al Conrad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 14:07:09

Dodaj __init__.py Plik:

dirFoo\
    Foo.py
    dirBar\
        __init__.py
        Bar.py

Następnie dodaj ten kod na początek Foo.py:

import sys
sys.path.append('dirBar')
import Bar
 6
Author: Josh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-05 07:45:00

Relative sys.przykład ścieżki:

# /lib/my_module.py
# /src/test.py


if __name__ == '__main__' and __package__ is None:
    sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib')))
import my_module

Na podstawie tej odpowiedzi.

 5
Author: Der_Meister,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Cóż, jak już wspomniałeś, zazwyczaj chcesz mieć dostęp do folderu z Twoimi modułami w stosunku do tego, gdzie jest uruchomiony Twój skrypt główny, więc po prostu je importujesz.

Rozwiązanie:

Mam skrypt w D:/Books/MyBooks.py i kilka modułów (jak oldies.py). muszę zaimportować z podkatalogu D:/Books/includes:

import sys,site
site.addsitedir(sys.path[0] + '\\includes')
print (sys.path)  # Just verify it is there
import oldies

Umieść print('done') w oldies.py, aby sprawdzić, czy wszystko idzie dobrze. Ten sposób zawsze działa, ponieważ przez definicję Pythona sys.path jako zainicjowaną podczas uruchamiania programu, pierwszy element ta lista, path[0], jest katalogiem zawierającym skrypt, który został użyty do wywołania interpretera Pythona.

Jeśli katalog skryptu nie jest dostępny (np. jeśli interpreter jest wywoływany interaktywnie lub jeśli skrypt jest odczytywany ze standardowego wejścia), path[0] jest pustym łańcuchem znaków, który kieruje Pythona do przeszukiwania modułów w bieżącym katalogu. Zauważ, że katalog skryptu jest wstawiany przed wpisami wstawionymi w wyniku PYTHONPATH.

 4
Author: Avenida Gez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 14:09:19

Innym rozwiązaniem byłoby zainstalowanie pakietu py-require, a następnie użycie następującego w Foo.py

import require
Bar = require('./dirBar/Bar')
 3
Author: Niklas R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-06 21:26:58

Spójrz na moduł pkgutil z biblioteki standardowej. To może pomóc ci zrobić, co chcesz.

 2
Author: Mihail Mihaylov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-09 15:19:55

Oto sposób na zaimportowanie pliku z jednego poziomu powyżej, przy użyciu ścieżki względnej.

Zasadniczo, po prostu przenieś katalog roboczy do poziomu (lub dowolnej względnej lokalizacji), dodaj go do ścieżki, a następnie przenieś katalog roboczy z powrotem tam, gdzie się rozpoczął.

#to import from one level above:
cwd = os.getcwd()
os.chdir("..")
below_path =  os.getcwd()
sys.path.append(below_path)
os.chdir(cwd)
 2
Author: Justin Muller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-27 17:43:59

Po prostu możesz użyć: from Desktop.filename import something

Przykład:

Biorąc pod uwagę, że plik ma nazwę test.py w katalogu Users/user/Desktop, i zaimportuje wszystko.

Kod:

from Desktop.test import *

Ale upewnij się, że robisz pusty plik o nazwie "__init__.py " w tym katalogu

 2
Author: 0x1996,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-27 17:13:09

Nie mam doświadczenia w Pythonie, więc jeśli jest coś złego w moich słowach, po prostu mi powiedz. Jeśli twoja hierarchia plików ułożona jest tak:

project\
    module_1.py 
    module_2.py

module_1.py definiuje funkcję o nazwie func_1(), module_2.py :

from module_1 import func_1

def func_2():
    func_1()

if __name__ == '__main__':
    func_2()

I uruchamiasz python module_2.py W cmd, to uruchomi to, co definiuje func_1(). Zazwyczaj w ten sposób importujemy te same pliki hierarchii. Ale kiedy piszesz from .module_1 import func_1 w module_2.py, interpreter Pythona powie No module named '__main__.module_1'; '__main__' is not a package. Więc aby to naprawić, zachowamy zmiany, które właśnie wprowadzimy, i przeniesiemy oba moduł do pakietu, i zrobić trzeci moduł jako wywołujący do uruchomienia module_2.py.

project\
    package_1\
        module_1.py
        module_2.py
    main.py

Main.py :

from package_1.module_2 import func_2

def func_3():
    func_2()

if __name__ == '__main__':
    func_3()

Ale powodem, dla którego dodajemy . przed module_1 w module_2.py jest to, że jeśli tego nie zrobimy i nie uruchomimy main.py, interpreter Pythona powie No module named 'module_1', to trochę skomplikowane, module_1.py jest tuż obok module_2.py. Teraz pozwalam func_1() in module_1.py zrobić coś:

def func_1():
    print(__name__)

To __name__ zapisuje wywołanie funkcji formula_1. Teraz zachowamy . przed module_1, uruchomimy main.py, wydrukuje package_1.module_1, Nie module_1. Oznacza to, że ten, kto wywołuje func_1() jest w tej samej hierarchii co main.py, . implikuje, że module_1 jest w tej samej hierarchii co module_2.py. Jeśli więc nie ma kropki, main.py rozpozna module_1 w tej samej hierarchii co ona, może rozpoznać package_1, ale nie to, co "pod" nią.

Skomplikuj to trochę. Masz config.ini i moduł definiuje funkcję do odczytu w tej samej hierarchii co 'main.py".
project\
    package_1\
        module_1.py
        module_2.py
    config.py
    config.ini
    main.py

I z jakiegoś nieuniknionego powodu, musisz wywołać go za pomocą module_2.py, więc musi importować z górnej hierarchii. module_2.py :

 import ..config
 pass

Dwie kropki oznaczają import z górnej hierarchii (trzy kropki mają dostęp do górnej niż górnej, i tak dalej). Teraz uruchamiamy main.py, interpreter powie: ValueError:attempted relative import beyond top-level package. "Pakiet najwyższego poziomu" to main.py. Tylko dlatego, że config.py jest obok main.py, są one w tej samej hierarchii, config.py nie jest "pod" main.py, lub nie jest "przewodzony" przez main.py, więc jest poza main.py. Aby to naprawić, najprostszy sposób jest:

project\
    package_1\
        module_1.py
        module_2.py
    config.py
    config.ini
main.py

Myślę, że jest to zgodne z zasadą porządkowania hierarchii plików projektu, należy rozmieścić moduły z różnymi funkcjami w różnych folderach, a po prostu zostawić top caller Na zewnątrz i można importować jak tylko chcesz.

 0
Author: OmouYue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-09 14:38:21

To również działa i jest znacznie prostsze niż cokolwiek z modułem sys:

with open("C:/yourpath/foobar.py") as f:
    eval(f.read())
 -1
Author: jgilley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-25 20:23:39

Nazwij mnie zbyt ostrożnym, ale lubię, aby mój był bardziej przenośny, ponieważ nie jest bezpieczne zakładanie, że pliki będą zawsze w tym samym miejscu na każdym komputerze. Osobiście mam kod najpierw sprawdzić ścieżkę pliku. Ja używam Linuksa więc mój wyglądałby tak:

import os, sys
from subprocess import Popen, PIPE
try:
    path = Popen("find / -name 'file' -type f", shell=True, stdout=PIPE).stdout.read().splitlines()[0]
    if not sys.path.__contains__(path):
        sys.path.append(path)
except IndexError:
    raise RuntimeError("You must have FILE to run this program!")

To jest oczywiście, chyba że planujesz spakować je razem. Ale jeśli tak, to i tak nie potrzebujesz dwóch oddzielnych plików.

 -14
Author: SuperFamousGuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 14:04:45