Importowanie modułów z katalogu nadrzędnego

Używam Pythona 2.5.

To jest moje drzewo katalogów:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(mam również __init__.py w każdym folderze, pominięte tutaj dla czytelności)

Jak zaimportować moduł nib z wnętrza modułu life? Mam nadzieję, że można to zrobić bez majsterkowania z sys./ align = "left" /

Uwaga: uruchamiany główny moduł znajduje się w folderze ptdraft.

Author: Edward, 2009-04-03

22 answers

Wydaje się, że problem nie jest związany z tym, że moduł znajduje się w katalogu nadrzędnym lub czymś w tym rodzaju.

Musisz dodać katalog zawierający ptdraft do PYTHONPATH

Powiedziałeś, że import nib współpracuje z tobą, to prawdopodobnie oznacza, że dodałeś ptdraft siebie (nie jego rodzica) do PYTHONPATH.

 135
Author: hasen,
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-01-12 18:30:07

Możesz użyć importu względnego (python >= 2.5):

from ... import nib

(Co nowego w Pythonie 2.5) PEP 328: Import bezwzględny i względny

EDIT : dodano kolejną kropkę '."do góry dwa pakiety

 644
Author: f3lix,
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
2013-02-17 21:43:03

Import względny (jak w from .. import mymodule) działa tylko w pakiecie. Aby zaimportować 'mymodule', który znajduje się w katalogu nadrzędnym bieżącego modułu:

import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir) 

import mymodule

Edit : atrybut __file__ nie zawsze jest podany. Zamiast używać os.path.abspath(__file__) zasugerowałem teraz użycie modułu inspect do pobrania nazwy pliku (i ścieżki) bieżącego pliku

 329
Author: Remi,
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-12-27 10:00:44

podobną odpowiedź zamieściłem również na pytanie dotyczące importu z paczek rodzeństwa. Możesz go zobaczyć tutaj .

Rozwiązanie bez sys.path hacków

Podsumowanie

  • zawiń kod w jeden folder (np. packaged_stuff)
  • Użyj skryptu create setup.py gdzie używasz setuptools.setup () .
  • Pip instaluje pakiet w stanie edytowalnym za pomocą pip install -e <myproject_folder>
  • Importuj za pomocą from packaged_stuff.modulename import function_name

Setup

Zakładam taka sama struktura folderów jak w pytaniu

.
└── ptdraft
    ├── __init__.py
    ├── nib.py
    └── simulations
        ├── __init__.py
        └── life
            ├── __init__.py
            └── life.py

Nazywam . katalogiem głównym i w moim przypadku znajduje się on w C:\tmp\test_imports.

Kroki

1) Dodaj setup.py do folderu głównego

Zawartość setup.py może być po prostu

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())

W zasadzie " każdy "setup.py zadziała. To tylko minimalny przykład pracy.

2) Użyj środowiska wirtualnego

jeśli znasz środowiska wirtualne, aktywuj je i przejdź do następnego krok. korzystanie ze środowisk wirtualnych nie jest bezwzględnie wymagane, ale one naprawdę pomogą Ci w dłuższej perspektywie (gdy masz więcej niż 1 projekt w toku..). Najbardziej podstawowe kroki to (Uruchom w folderze głównym)

  • Create virtual env
    • python -m venv venv
  • Aktywuj wirtualny env
    • . /venv/bin/activate (Linux) lub ./venv/Scripts/activate (Win)

Aby dowiedzieć się więcej na ten temat, po prostu wygoogluj " Python virtualenv tutorial" lub podobne. Prawdopodobnie nigdy nie potrzebujesz innych poleceń niż tworzenie, aktywowanie i dezaktywowanie.

Po utworzeniu i aktywacji środowiska wirtualnego konsola powinna podać nazwę środowiska wirtualnego w nawiasie.]}
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) pip zainstaluj swój projekt w edytowalnym stanie

Zainstaluj pakiet najwyższego poziomu myproject używając pip. Sztuczka polega na użyciu znacznika -e podczas instalacji. W ten sposób jest zainstalowany w stanie edytowalnym, a wszystkie zmiany dokonane w plikach. py zostaną automatycznie uwzględnione w zainstalowanym pakiecie.

W katalogu głównym uruchom

pip install -e . (Uwaga kropka, oznacza "bieżący katalog")

Możesz również zobaczyć, że jest on zainstalowany za pomocą pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0

4) Import przez prepending mainfolder do każdego importu

W tym przykładzie, {[25] } będzie ptdraft. Ma to tę zaletę, że nie napotkasz kolizji nazw z innymi nazwami modułów (z Pythona biblioteka standardowa lub Moduły innych firm).


Przykładowe Użycie

Nib.py

def function_from_nib():
    print('I am the return value from function_from_nib!')

Life.py

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
    function_from_nib()

Bieganie life.py

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
 281
Author: np8,
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
2020-06-03 21:09:01

Możesz użyć ścieżki zależnej od systemu operacyjnego w "ścieżce wyszukiwania modułów", która jest wymieniona w sys.ścieżka . Możesz więc łatwo dodać Katalog nadrzędny, taki jak następujący

import sys
sys.path.insert(0,'..')

Jeśli chcesz dodać katalog parent-parent,

sys.path.insert(0,'../..')

To działa zarówno w Pythonie 2 jak i 3.

 79
Author: Shinbero,
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
2020-01-29 04:06:15

Jeśli dodanie folderu modułu do ścieżki PYTHONPATH nie zadziałało, możesz zmodyfikować sys .path lista w programie, w którym interpreter Pythona wyszukuje moduły do zaimportowania, Dokumentacja Pythona mówi:

Gdy importowany jest moduł o nazwie spam, interpreter najpierw wyszukuje wbudowany Moduł o tej nazwie. Jeśli nie znaleziono, wyszukuje plik o nazwie spam.py w liście katalogów podanych przez zmienną sys./ align = "left" / sys.ścieżka jest inicjalizowana z tych lokalizacji:

  • katalog zawierający skrypt wejściowy (lub bieżący katalog).
  • PYTHONPATH (lista nazw katalogów, o tej samej składni co ścieżka zmiennej powłoki).
  • domyślna zależna od instalacji.

Po inicjalizacji, programy Pythona mogą modyfikować sys.ścieżka . Katalog zawierający uruchamiany skrypt umieszczony jest na początku ścieżki wyszukiwania, przed Standardowa ścieżka biblioteczna. Oznacza to, że skrypty w tym katalogu będą ładowane zamiast modułów o tej samej nazwie w katalogu biblioteki. Jest to błąd, chyba że wymiana jest przeznaczona.

Wiedząc o tym, możesz wykonać następujące czynności w swoim programie:

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft
 59
Author: Ricardo Murillo,
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-09-19 18:14:46

Nie wiem zbyt wiele o Pythonie 2.
W Pythonie 3, folder nadrzędny można dodać w następujący sposób:

import sys 
sys.path.append('..')

...a następnie można z niego importować Moduły

 57
Author: Rob Ellenbroek,
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-02-14 20:07:45

Oto odpowiedź, która jest prosta, więc możesz zobaczyć, jak to działa, małe i wieloplatformowe.
Wykorzystuje tylko wbudowane moduły (os, sys i inspect) tak powinno działać
na każdym systemie operacyjnym (OS), ponieważ Python jest do tego przeznaczony.

Krótszy kod odpowiedzi-mniej linii i zmiennych

from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module  # Replace "my_module" here with the module name.
sys.path.pop(0)

Dla mniejszej liczby wierszy niż ta, zamień drugi wiersz na import os.path as path, sys, inspect,
dodaj inspect. na początku getsourcefile (linia 3) i usuń pierwszy wiersz.
- jednak ten import cały moduł może więc potrzebować więcej czasu, pamięci i zasobów.

Kod mojej odpowiedzi (dłuższa wersja )

from inspect import getsourcefile
import os.path
import sys

current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]

sys.path.insert(0, parent_dir)

import my_module  # Replace "my_module" here with the module name.

Używa przykładu z odpowiedzi przepełnienia stosu Jak uzyskać ścieżkę bieżącej
wykonywany plik w Pythonie?
aby znaleźć źródło (nazwę pliku) uruchomionego kodu za pomocą wbudowanego narzędzia.

from inspect import getsourcefile  
from os.path import abspath  

Następnie, gdziekolwiek chcesz znaleźć plik źródłowy, użyj:

abspath(getsourcefile(lambda:0))

Mój kod dodaje ścieżka do pliku sys.path, Lista ścieżek Pythona
ponieważ pozwala to Pythonowi importować moduły z tego folderu.

Po zaimportowaniu modułu w kodzie, dobrym pomysłem jest uruchomienie sys.path.pop(0) w nowej linii
gdy ten dodany folder ma moduł o tej samej nazwie co inny importowany moduł
później w programie. Musisz usunąć element listy dodany przed importem, a nie inne ścieżki.
Jeśli twój program nie importuje innych modułów, bezpiecznie jest nie usuwać ścieżka do pliku ponieważ
po zakończeniu programu (lub ponownym uruchomieniu powłoki Pythona) wszelkie zmiany wprowadzone do sys.path znikają.

Uwagi o zmiennej filename

Moja odpowiedź nie używa zmiennej __file__, aby uzyskać ścieżkę / nazwę pliku uruchomionego
Kod, ponieważ użytkownicy często opisywali go jako niewiarygodne . Nie powinieneś tego używać
do importowania modułów z katalogu nadrzędnego w programach używanych przez inne osoby.

Kilka przykładów, gdzie to nie działa (cytat z to pytanie o przepełnienie stosu):

• it nie może być znaleziony na niektórych platformach * it sometimes isn ' t the full file path

  • py2exe nie ma atrybutu __file__, ale istnieje obejście
  • gdy uruchamiasz z IDLE z execute() nie ma __file__ atrybutu
  • OS X 10.6 where I get NameError: global name '__file__' is not defined
 33
Author: Edward,
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-11-08 15:54:21

Tutaj jest bardziej ogólne rozwiązanie, które zawiera Katalog nadrzędny w sys.ścieżka (działa dla mnie):

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
 31
Author: Mike,
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
2014-02-14 16:09:22

Znalazłem następujący sposób importowania pakietu z katalogu nadrzędnego skryptu. W przykładzie chciałbym zaimportować funkcje w env.py z app.db pakietu.

.
└── my_application
    └── alembic
        └── env.py
    └── app
        ├── __init__.py
        └── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)
 24
Author: Yu N.,
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
2019-04-29 22:09:37

Biblioteka pathlib (dołączona do >= Python 3.4) sprawia, że dołączanie ścieżki katalogu nadrzędnego do ścieżki PYTHONPATH jest bardzo zwięzłe i intuicyjne:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))
 20
Author: itmatters,
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
2020-07-28 14:09:37

Wyżej wymienione rozwiązania są również w porządku. Innym rozwiązaniem tego problemu jest

Jeśli chcesz zaimportować cokolwiek z katalogu najwyższego poziomu. Następnie

from ...module_name import *

Również, jeśli chcesz zaimportować dowolny moduł z katalogu nadrzędnego. Następnie

from ..module_name import *

Również, jeśli chcesz zaimportować dowolny moduł z katalogu nadrzędnego. Następnie

from ...module_name.another_module import *

W ten sposób możesz zaimportować dowolną metodę, jeśli chcesz.

 15
Author: Ravin Gupta,
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-28 11:15:52

W Notatniku Jupytera

Tak długo, jak pracujesz w notebooku Jupyter, to krótkie rozwiązanie może być przydatne:]}
%cd ..
import nib

Działa nawet bez pliku __init__.py.

Przetestowałem go z Anaconda3 na Linuksie i Windows 7.

 14
Author: Thomas 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
2019-12-12 10:37:53

Dla mnie najkrótszym i moim ulubionym linkiem dostępu do katalogu nadrzędnego jest:

sys.path.append(os.path.dirname(os.getcwd()))

Lub:

sys.path.insert(1, os.path.dirname(os.getcwd()))

Os.getcwd () zwraca nazwę bieżącego katalogu roboczego, systemu operacyjnego./ align = "left" / dirname (directory_name) zwraca nazwę katalogu dla przekazanego.

Właściwie, moim zdaniem Architektura projektu Pythona powinna być wykonana tak, aby żaden moduł z katalogu podrzędnego nie używał żadnego modułu z katalogu nadrzędnego. Jeśli coś takiego się wydarzy warto Przemyśl temat drzewa projektu.

Innym sposobem jest dodanie katalogu nadrzędnego do zmiennej środowiskowej systemu PYTHONPATH.

 11
Author: zviad,
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-04-13 13:56:29

import sys sys.path.append('../')

 9
Author: Andong Zhan,
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-09-05 23:07:57

Taki sam styl jak poprzednia odpowiedź-ale w mniejszej liczbie linijek: P

import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)

Plik zwraca lokalizację, w której pracujesz

 5
Author: YFP,
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
2013-11-26 10:43:15

Praca z bibliotekami. Zrobić bibliotekę o nazwie nib, zainstalować ją za pomocą setup.py, niech się znajdzie w site-packages i twoje problemy zostaną rozwiązane. Nie musisz pakować wszystkiego, co robisz w jednym opakowaniu. Rozwal to na kawałki.

 1
Author: user3181121,
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
2015-09-24 20:56:22

W systemie Linux można utworzyć soft link z folderu "life" do nib.py plik. Następnie możesz po prostu zaimportować go w następujący sposób:

import nib
 1
Author: Erel Segal-Halevi,
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-10-25 14:16:11

Miałem problem, w którym musiałem zaimportować aplikację Flask, która miała import, który wymagał również importowania plików w oddzielnych folderach. Jest to częściowo za pomocą odpowiedzi Remiego , ale załóżmy, że mamy repozytorium, które wygląda tak:

.
└── service
    └── misc
        └── categories.csv
    └── test
        └── app_test.py
    app.py
    pipeline.py

Następnie przed zaimportowaniem obiektu app z pliku app.py, zmieniamy katalog o jeden poziom w górę, więc kiedy importujemy aplikację (która importuje pipeline.py), możemy również czytać w różnych plikach, takich jak plik csv.

import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)

os.chdir('../')
from app import app

Po zaimportowano aplikację Flask, możesz użyć os.chdir('./test'), aby twój katalog roboczy nie został zmieniony.

 1
Author: Casper Hansen,
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
2020-07-06 11:52:29

Chociaż oryginalny autor prawdopodobnie nie szuka już rozwiązania, ale dla kompletności, jest jedno proste rozwiązanie. It ' s to run life.py jako taki moduł:

cd ptdraft
python -m simulations.life.life

W ten sposób możesz zaimportować wszystko z nib.py jako katalog ptdraft znajduje się w ścieżce.

 1
Author: tjk,
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
2020-10-11 14:32:12

Po to stworzyłem tę bibliotekę.

Https://github.com/fx-kirin/add_parent_path

# Just add parent path
add_parent_path(1)

# Append to syspath and delete when the exist of with statement.
with add_parent_path(1):
   # Import modules in the parent path
   pass
 0
Author: fx-kirin,
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
2020-07-03 07:31:22

Mimo, że jest to wbrew wszystkim zasadom, nadal chcę wspomnieć o tej możliwości:

Możesz najpierw skopiować plik z katalogu nadrzędnego do katalogu podrzędnego. Następnie zaimportuj go, a następnie usuń skopiowany plik:

Na przykład w life.py:

import os
import shutil

shutil.copy('../nib.py', '.')
import nib
os.remove('nib.py')

# now you can use it just fine:
nib.foo()

Oczywiście może pojawić się kilka problemów, gdy nibs próbuje zaimportować/odczytać inne pliki z względnymi importami/ścieżkami.

 -3
Author: JLT,
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
2020-06-15 09:49:58