Ho la mia fonte Python strutturata come segue:
+-branchname/
+-dst/
+-src/
| +-library/
| | +-cleese/
| | | +-test/
| | | | +-__init__.py
| | | | +-test_cleese.py
| | | +-__init__.py
| | | +-cleese.py
| | +-palin/
| | +-test/
| | | +-__init__.py
| | | +-test_palin.py
| | +-__init__.py
| | +-palin.py
| +-productline/
| +-circus/
| | +-test/
| | | +-__init__.py
| | | +-test_circus.py
| | +-__init__.py
| | +-circus.py
| +-grail/
| +-test/
| | +-__init__.py
| | +-test_grail.py
| +-__init__.py
| +-grail.py
+-branch_root_marker
I punti di ingresso sono in circo / e grail /, così come (possibilmente) ciascuno dei test / directory, a seconda di come viene eseguito il test.
Ho più copie di questo albero di sorgenti presenti sullo storage locale in qualsiasi momento (corrispondente a vari rami di manutenzione e funzionalità), quindi non posso impostare PYTHONPATH nella mia shell senza alcun dolore. (Avrei bisogno di ricordarmi di cambiarlo ogni volta che sono passato a lavorare su un ramo diverso, e sono molto smemorato)
Invece, ho una logica che risalga la struttura dei file, iniziando dalla posizione del file "corrente", passando da una foglia all'altra, cercando branch_root_marker. Una volta trovata la directory root della copia di lavoro corrente, aggiunge la libreria / e productline / a sys.path. Io chiamo questa funzione da ogni entry-point nel sistema.
"""Add working copy (branch) to sys.path"""
import os
import sys
def _setpath():
"""Add working copy (branch) to sys.path"""
markerfile = "branch_root_marker"
path = ""
if ("__file__" in locals() or globals()) and __file__ != "__main__":
path = __file__
elif sys.argv and sys.argv[0] and not sys.argv[0] == "-c":
path = sys.argv[0]
path = os.path.realpath(os.path.expandvars(path))
while os.path.exists(path):
if os.path.exists(os.path.join(path, markerfile)):
break
else:
path = os.path.dirname(path)
errormsg = " ".join(("Could not find", markerfile))
assert os.path.exists(path) and path != os.path.dirname(path), errormsg
path = os.path.join(path, "src")
(_, subdir_list, _) = os.walk(path).next()
for subdir in subdir_list:
if subdir.startswith("."):
continue
subdir_path = os.path.join(path, subdir)
if subdir_path in sys.path:
continue
sys.path.append(subdir_path)
_setpath()
Attualmente, ho bisogno di mantenere una copia separata ma identica di questa funzione in ogni punto di ingresso. Anche se è una funzione piuttosto breve, sono piuttosto angosciato dal modo in cui fragrante il principio di ESSERE VIOLATO viene violato da questo approccio, e mi piacerebbe trovare un modo per mantenere la logica di modifica di sys.path in un unico punto. Qualche idea?
Nota: - Una cosa che viene in mente è installare la logica di modifica sys.path in una posizione comune che è sempre su PYTHONPATH. Anche se questa non è una pessima idea, significa introdurre una fase di installazione che deve essere eseguita ogni volta che mi muovo in un ambiente fresco; un'altra cosa da ricordare (o, più probabilmente, dimenticare), quindi vorrei evitare questo, se possibile.