Stanco degli hack di sys.path?
Ce ne sono molti sys.path.append
-hack disponibili, ma ho trovato un modo alternativo per risolvere il problema in mano.
Sommario
- Avvolgere il codice in una cartella (ad es.
packaged_stuff
)
- Usa lo
setup.py
script di creazione in cui usi setuptools.setup () .
- Pip installa il pacchetto in stato modificabile con
pip install -e <myproject_folder>
- Importa utilizzando
from packaged_stuff.modulename import function_name
Impostare
Il punto di partenza è la struttura del file che hai fornito, racchiusa in una cartella chiamata myproject
.
.
└── myproject
├── api
│ ├── api_key.py
│ ├── api.py
│ └── __init__.py
├── examples
│ ├── example_one.py
│ ├── example_two.py
│ └── __init__.py
├── LICENCE.md
├── README.md
└── tests
├── __init__.py
└── test_one.py
Chiamerò la .
cartella principale e nel mio caso di esempio si trova in C:\tmp\test_imports\
.
api.py
Come test case, usiamo il seguente ./api/api.py
def function_from_api():
return 'I am the return value from api.api!'
test_one.py
from api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
Prova a eseguire test_one:
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\myproject\tests\test_one.py", line 1, in <module>
from api.api import function_from_api
ModuleNotFoundError: No module named 'api'
Anche provare le importazioni relative non funzionerà:
L'uso from ..api.api import function_from_api
sarebbe risultato in
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\tests\test_one.py", line 1, in <module>
from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package
passi
- Crea un file setup.py nella directory di livello principale
I contenuti per il setup.py
sarebbero *
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
- Usa un ambiente virtuale
Se hai familiarità con gli ambienti virtuali, attivane uno e vai al passaggio successivo. L'uso di ambienti virtuali non è assolutamente necessario, ma ti aiuteranno davvero a lungo termine (quando hai in corso più di 1 progetto ...). I passaggi più basilari sono (esegui nella cartella principale)
- Crea un ambiente virtuale
- Attiva env virtuale
source ./venv/bin/activate
(Linux, macOS) o ./venv/Scripts/activate
(Win)
Per saperne di più su questo, basta uscire da Google "tutorial virtuale su Python" o simili. Probabilmente non avrai mai bisogno di altri comandi oltre a creare, attivare e disattivare.
Dopo aver creato e attivato un ambiente virtuale, la console dovrebbe fornire il nome dell'ambiente virtuale tra parentesi
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
e l'albero delle cartelle dovrebbe apparire così **
.
├── myproject
│ ├── api
│ │ ├── api_key.py
│ │ ├── api.py
│ │ └── __init__.py
│ ├── examples
│ │ ├── example_one.py
│ │ ├── example_two.py
│ │ └── __init__.py
│ ├── LICENCE.md
│ ├── README.md
│ └── tests
│ ├── __init__.py
│ └── test_one.py
├── setup.py
└── venv
├── Include
├── Lib
├── pyvenv.cfg
└── Scripts [87 entries exceeds filelimit, not opening dir]
- pip installa il tuo progetto in stato modificabile
Installa il tuo pacchetto di livello superiore myproject
utilizzando pip
. Il trucco è usare la -e
bandiera durante l'installazione. In questo modo viene installato in uno stato modificabile e tutte le modifiche apportate ai file .py verranno automaticamente incluse nel pacchetto installato.
Nella directory principale, eseguire
pip install -e .
(notare il punto, sta per "directory corrente")
Puoi anche vedere che è installato usando 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
- Aggiungi
myproject.
alle tue importazioni
Tieni presente che dovrai aggiungere myproject.
solo le importazioni che altrimenti non funzionerebbero. Le importazioni che hanno funzionato senza setup.py
e pip install
funzioneranno ancora bene. Vedi un esempio di seguito.
Prova la soluzione
Ora, testiamo la soluzione usando api.py
definito sopra e test_one.py
definito di seguito.
test_one.py
from myproject.api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
eseguendo il test
(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!
* Vedi i documenti setuptools per esempi più dettagliati di setup.py.
** In realtà, potresti mettere il tuo ambiente virtuale ovunque sul tuo disco rigido.
sys.path
hack e di leggere l'unica vera soluzione che è stata pubblicata finora (dopo 7 anni!).