Saya memiliki struktur direktori yang mirip dengan berikut ini
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
Ketika bekerja di notebook.jpynb
jika saya mencoba untuk menggunakan impor relatif untuk mengakses fungsi function()
di module.py
dengan:
from ..project1.lib.module import function
Saya mendapatkan kesalahan berikut:
SystemError Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function
SystemError: Parent module '' not loaded, cannot perform relative import
Apakah ada cara untuk membuatnya bekerja menggunakan impor relatif?
Catatan, server buku catatan dibuat pada tingkat meta_project
direktori, jadi harus memiliki akses ke informasi di file tersebut.
Perhatikan, juga, bahwa setidaknya seperti yang dimaksudkan semula project1
tidak dianggap sebagai modul dan oleh karena itu tidak memiliki __init__.py
file, itu hanya dimaksudkan sebagai direktori sistem file. Jika solusi untuk masalah memerlukan memperlakukannya sebagai modul dan menyertakan __init__.py
file (bahkan yang kosong) itu baik-baik saja, tetapi melakukannya tidak cukup untuk menyelesaikan masalah.
Saya membagikan direktori ini antara mesin dan impor relatif memungkinkan saya menggunakan kode yang sama di mana-mana, & saya sering menggunakan notebook untuk pembuatan prototipe cepat, jadi saran yang melibatkan meretas jalur absolut tidak mungkin membantu.
Sunting: Ini tidak seperti impor Relatif di Python 3 , yang berbicara tentang impor relatif di Python 3 secara umum dan - khususnya - menjalankan skrip dari dalam direktori paket. Ini ada hubungannya dengan bekerja dalam notebook jupyter yang mencoba memanggil fungsi dalam modul lokal di direktori lain yang memiliki aspek umum dan khusus yang berbeda.
__init__
file di direktori paket Anda?lib
direktori.Jawaban:
Saya memiliki contoh yang hampir sama seperti Anda di notebook ini di mana saya ingin mengilustrasikan penggunaan fungsi modul yang berdekatan dengan cara KERING.
Solusi saya adalah memberi tahu Python tentang jalur impor modul tambahan itu dengan menambahkan cuplikan seperti ini ke notebook:
Ini memungkinkan Anda untuk mengimpor fungsi yang diinginkan dari hierarki modul:
Perhatikan bahwa Anda perlu menambahkan
__init__.py
file kosong ke folder project1 / dan lib / jika Anda belum memilikinya.sumber
Datang ke sini mencari praktik terbaik dalam mengabstraksi kode ke submodul saat bekerja di Notebook. Saya tidak yakin ada praktik terbaik. Saya telah mengusulkan ini.
Hierarki proyek seperti:
Dan dari
20170609-Initial_Database_Connection.ipynb
:Ini berfungsi karena secara default Notebook Jupyter dapat mengurai
cd
perintah. Perhatikan bahwa ini tidak menggunakan sihir Notebook Python. Ini hanya berfungsi tanpa persiapan%bash
.Mengingat 99 kali dari 100 saya bekerja di Docker menggunakan salah satu image Project Jupyter Docker , modifikasi berikut adalah idempotent
sumber
chdir
daripada menambahkan ke path, karena saya tertarik untuk mengimpor dari repo utama serta berinteraksi dengan beberapa file di sana.if os.path.isdir('../lib/'): os.chdir('../lib')
:; atau, lebih baik, gunakan../lib/db/
dengan Andapostgres.py
agar tidak secara tidak sengaja berpindah ke direktori yang lebih tinggi yang juga berisi direktori lainlib
.cd ..
dua kali.Sejauh ini, jawaban yang diterima paling berhasil untuk saya. Namun, kekhawatiran saya selalu adalah bahwa ada kemungkinan skenario di mana saya mungkin merefaktor
notebooks
direktori menjadi subdirektori, memerlukan untuk mengubahmodule_path
di setiap notebook. Saya memutuskan untuk menambahkan file python dalam setiap direktori notebook untuk mengimpor modul yang diperlukan.Dengan demikian, memiliki struktur proyek berikut:
Saya menambahkan file
project_path.py
di setiap subdirektori notebook (notebooks/explore
dannotebooks/explain
). File ini berisi kode untuk impor relatif (dari @metakermit):Dengan cara ini, saya hanya perlu melakukan impor relatif di dalam
project_path.py
file, dan bukan di buku catatan. File buku catatan kemudian hanya perlu diimporproject_path
sebelum diimporlib
. Misalnya di0.0-notebook.ipynb
:Peringatan di sini adalah bahwa pembalikan impor tidak akan berhasil. INI TIDAK BEKERJA:
Jadi kehati-hatian harus dilakukan selama impor.
sumber
Saya baru saja menemukan solusi cantik ini:
Anda hanya menginginkan beberapa fungsi dari file itu
Jika python version> = 3.3 Anda tidak membutuhkan file init.py di folder
sumber
if ".." not in sys.path: ... sys.path.insert(0,"..")
Meneliti topik ini sendiri dan setelah membaca jawabannya saya sarankan menggunakan pustaka path.py karena ini menyediakan pengelola konteks untuk mengubah direktori kerja saat ini.
Anda kemudian memiliki sesuatu seperti
Meskipun, Anda mungkin mengabaikan
isdir
pernyataan itu.Di sini saya akan menambahkan pernyataan cetak agar mudah mengikuti apa yang terjadi
yang mana keluaran dalam contoh ini (di mana lib berada di
/home/jovyan/shared/notebooks/by-team/data-vis/demos/lib
):Karena solusinya menggunakan manajer konteks, Anda dijamin untuk kembali ke direktori kerja Anda sebelumnya, tidak peduli apa status kernel Anda sebelum sel dan tidak peduli pengecualian apa yang dilemparkan dengan mengimpor kode perpustakaan Anda.
sumber
Ini 2 sen saya:
impor sys
memetakan jalur tempat file modul berada. Dalam kasus saya itu adalah desktop
sys.path.append ('/ Users / John / Desktop')
Impor seluruh modul pemetaan TETAPI Anda harus menggunakan .notation untuk memetakan kelas seperti pemetaan.Shipping ()
import mapping # mapping.py adalah nama file modul saya
shipit = mapping.Shipment () #Shipment adalah nama kelas yang perlu saya gunakan dalam modul pemetaan
Atau impor kelas tertentu dari modul pemetaan
dari pemetaan impor Mapping
shipit = Shipment () # Sekarang Anda tidak perlu menggunakan .notation
sumber
Saya telah menemukan bahwa python-dotenv membantu menyelesaikan masalah ini dengan cukup efektif. Struktur proyek Anda akhirnya sedikit berubah, tetapi kode di buku catatan Anda sedikit lebih sederhana dan konsisten di seluruh buku catatan.
Untuk proyek Anda, lakukan sedikit penginstalan.
Kemudian, proyek berubah menjadi:
Dan terakhir, impor Anda berubah menjadi:
Sebuah +1 untuk paket ini adalah bahwa buku catatan Anda dapat memiliki beberapa direktori. python-dotenv akan menemukan yang terdekat di direktori induk dan menggunakannya. A +2 untuk pendekatan ini adalah bahwa jupyter akan memuat variabel lingkungan dari file .env saat startup. Whammy ganda.
sumber