Bosan dengan hack sys.path?
Ada banyak sys.path.append
-hack yang tersedia, tetapi saya menemukan cara alternatif untuk memecahkan masalah di tangan.
Ringkasan
- Bungkus kode ke dalam satu folder (mis.
packaged_stuff
)
- Gunakan buat
setup.py
skrip tempat Anda menggunakan setuptools.setup () .
- Pip instal paket dengan status yang dapat diedit
pip install -e <myproject_folder>
- Impor menggunakan
from packaged_stuff.modulename import function_name
Mempersiapkan
Titik awal adalah struktur file yang Anda berikan, dibungkus dengan folder yang disebut 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
Saya akan memanggil .
folder root, dan dalam contoh saya ini terletak di C:\tmp\test_imports\
.
api.py
Sebagai uji coba, mari gunakan yang berikut ini ./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()
Coba jalankan 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'
Juga mencoba impor relatif tidak akan berfungsi:
Menggunakan from ..api.api import function_from_api
akan menghasilkan
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
Langkah
- Buat file setup.py ke direktori level root
Isi untuk setup.py
akan *
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
- Gunakan lingkungan virtual
Jika Anda terbiasa dengan lingkungan virtual, aktifkan satu, dan lewati ke langkah berikutnya. Penggunaan lingkungan virtual tidak mutlak diperlukan, tetapi mereka benar - benar akan membantu Anda dalam jangka panjang (ketika Anda memiliki lebih dari 1 proyek yang sedang berlangsung ..). Langkah paling dasar adalah (dijalankan di folder root)
- Buat virtual env
- Aktifkan virtual env
source ./venv/bin/activate
(Linux, macOS) atau ./venv/Scripts/activate
(Win)
Untuk mempelajari lebih lanjut tentang ini, cukup Google keluar "python virtual env tutorial" atau serupa. Anda mungkin tidak pernah membutuhkan perintah selain membuat, mengaktifkan, dan menonaktifkan.
Setelah Anda membuat dan mengaktifkan lingkungan virtual, konsol Anda harus memberi nama lingkungan virtual dalam tanda kurung
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
dan pohon folder Anda akan terlihat seperti ini **
.
├── 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 instal proyek Anda dalam keadaan dapat diedit
Instal paket tingkat atas Anda myproject
menggunakan pip
. Caranya adalah dengan menggunakan -e
bendera saat melakukan instalasi. Dengan cara ini diinstal dalam keadaan yang dapat diedit, dan semua pengeditan yang dilakukan pada file .py akan secara otomatis disertakan dalam paket yang diinstal.
Di direktori root, jalankan
pip install -e .
(perhatikan titik, singkatan dari "direktori saat ini")
Anda juga dapat melihat bahwa itu diinstal dengan menggunakan 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
- Tambahkan
myproject.
ke impor Anda
Perhatikan bahwa Anda harus menambahkan myproject.
hanya ke impor yang tidak akan berfungsi sebaliknya. Impor yang berfungsi tanpa setup.py
& pip install
akan berfungsi dengan baik. Lihat contoh di bawah ini.
Uji solusinya
Sekarang, mari kita coba solusinya menggunakan yang api.py
didefinisikan di atas, dan yang test_one.py
didefinisikan di bawah ini.
test_one.py
from myproject.api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
menjalankan tes
(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!
* Lihat dokumen setuptools untuk lebih banyak contoh setup.py verbose.
** Pada kenyataannya, Anda dapat menempatkan lingkungan virtual Anda di mana saja di hard disk Anda.
sys.path
peretasan dan membaca satu-satunya solusi aktual yang telah diposting sejauh ini (setelah 7 tahun!).