from - python3 relative import




Importa un modulo da un percorso relativo (16)

Come posso importare un modulo Python dato il suo percorso relativo?

Ad esempio, se dirFoo contiene Foo.py e dirBar e dirBar contiene Bar.py , come posso importare Bar.py in Foo.py ?

Ecco una rappresentazione visiva:

dirFoo\
    Foo.py
    dirBar\
        Bar.py

Foo desidera includere la Bar , ma la ristrutturazione della gerarchia delle cartelle non è un'opzione.


Il modo rapido e sporco per gli utenti Linux

Se stai solo cercando di risolvere i problemi di distribuzione, puoi utilizzare un link simbolico (supponendo che il tuo filesystem lo supporti) per rendere il modulo o il pacchetto direttamente visibile nella cartella del modulo richiedente.

ln -s (path)/module_name.py

o

ln -s (path)/package_name

Nota: un "modulo" è qualsiasi file con estensione .py e un "pacchetto" è una qualsiasi cartella che contiene il file __init__.py (che può essere un file vuoto). Dal punto di vista dell'utilizzo, moduli e pacchetti sono identici - entrambi espongono le loro "definizioni e dichiarazioni" contenute come richiesto tramite il comando di import .

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


È anche possibile aggiungere la sottodirectory al percorso Python in modo che importi come uno script normale.

import sys
sys.path.insert(0, <path to dirFoo>)
import Bar

Assicurati che dirBar abbia il file __init__.py - questo rende una directory in un pacchetto Python.


Basta fare cose semplici per importare il file .py da una cartella diversa.

Diciamo che hai una directory come:

lib/abc.py

Quindi tieni solo un file vuoto nella cartella lib come indicato

__init__.py

E poi usa

from lib.abc import <Your Module name>

Conserva il file __init__.py in ogni cartella della gerarchia del modulo di importazione.


Chiamami eccessivamente cauto, ma mi piace renderlo più portatile perché è pericoloso presumere che i file siano sempre nello stesso posto su tutti i computer. Personalmente ho il codice per cercare prima il percorso del file. Io uso Linux così il mio sarebbe simile a questo:

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!")

Ovviamente, a meno che non abbiate intenzione di impacchettarli insieme. Ma se questo è il caso non hai davvero bisogno di due file separati comunque.


Ecco un modo per importare un file da un livello superiore, usando il percorso relativo.

Fondamentalmente, basta spostare la directory di lavoro su un livello (o qualsiasi posizione relativa), aggiungerla al percorso, quindi spostare la directory di lavoro dove è stata avviata.

#to import from one level above:
cwd = os.getcwd()
os.chdir("..")
below_path =  os.getcwd()
sys.path.append(below_path)
os.chdir(cwd)

Funziona anche, ed è molto più semplice di qualsiasi altra cosa con il modulo sys :

with open("C:/yourpath/foobar.py") as f:
    eval(f.read())

Guarda il modulo pkgutil dalla libreria standard. Potrebbe aiutarti a fare quello che vuoi.


Il modo più semplice senza alcuna modifica al tuo script è impostare la variabile di ambiente PYTHONPATH. Perché sys.path è inizializzato da queste posizioni:

  1. La directory che contiene lo script di input (o la directory corrente).
  2. PYTHONPATH (un elenco di nomi di directory, con la stessa sintassi della variabile di shell PATH).
  3. Il default dipendente dall'installazione.

Corri:

export PYTHONPATH=/absolute/path/to/your/module

Sys.path conterrà il percorso sopra, come mostrato di seguito:

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']

In questo caso, per importare Bar.py in Foo.py, prima trasformo queste cartelle in pacchetti Python in questo modo:

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

Allora lo farei così in Foo.py:

from .dirBar import Bar

Se volessi che il namespace assomigliasse a Bar. qualunque cosa , o

from . import dirBar

Se volessi lo spazio dei nomi dirBar.Bar. qualunque cosa . Questo secondo caso è utile se si hanno più moduli sotto il pacchetto dirBar.



Se strutturi il tuo progetto in questo modo:

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

Quindi da Foo.py dovresti essere in grado di fare:

import dirFoo.Foo

O:

from dirFoo.Foo import FooObject

Per il commento di Tom, questo richiede che la cartella src sia accessibile tramite site_packages o il percorso di ricerca. Inoltre, come dice, __init__.py viene importato implicitamente quando si importa per la prima volta un modulo in quel pacchetto / directory. In genere __init__.py è semplicemente un file vuoto.


Semplicemente puoi usare: from Desktop.filename import something

Esempio:

dato che il file è name test.py nella directory Users/user/Desktop , e importa tutto.

il codice:

from Desktop.test import *

Ma assicurati di creare un file vuoto chiamato " __init__.py " in quella directory


Supponendo che entrambe le directory siano veri pacchetti Python (avere il file __init__.py al loro interno), ecco una soluzione sicura per l'inclusione di moduli relativamente alla posizione dello script.

Presumo che tu voglia fare questo, perché devi includere un set di moduli con il tuo script. Uso questo in produzione in diversi prodotti e funziona in molti scenari speciali come: script chiamati da un'altra directory o eseguiti con python execute invece di aprire un nuovo interprete.

 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.

Come bonus, questo approccio ti permette di forzare Python a usare il tuo modulo invece di quelli installati sul sistema.

Avvertimento! Non so davvero cosa stia succedendo quando il modulo corrente si trova all'interno di un file egg . Probabilmente fallisce anche tu.


from .dirBar import Bar

invece di:

from dirBar import Bar

nel caso ci possa essere un altro dirBar installato e confondere un lettore foo.py.


import os
import sys
lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))
sys.path.append(lib_path)

import mymodule






python-import