Saya menjalankan Python 2.5.
Ini pohon folder saya:
ptdraft/
nib.py
simulations/
life/
life.py
(Saya juga punya __init__.py
di setiap folder, dihilangkan di sini agar mudah dibaca)
Bagaimana cara mengimpor nib
modul dari dalam life
modul? Saya berharap ini bisa dilakukan tanpa bermain-main dengan sys.path.
Catatan: Modul utama yang dijalankan ada di ptdraft
folder.
__init__.py
. S.Lott: Saya tidak tahu cara memeriksa ...sys.path
atauPYTHONPATH
jawaban dan memeriksa jawaban np8 yang sangat baik . Ya, sudah lama dibaca. Ya, sepertinya banyak pekerjaan. Tapi itu satu-satunya jawaban yang benar-benar menyelesaikan masalah dengan benar dan bersih.Jawaban:
Tampaknya masalahnya tidak terkait dengan modul yang berada di direktori induk atau semacamnya.
Anda perlu menambahkan direktori yang berisi
ptdraft
ke PYTHONPATHAnda mengatakan bahwa
import nib
bekerja dengan Anda, itu mungkin berarti Anda menambahkanptdraft
dirinya sendiri (bukan orang tuanya) ke PYTHONPATH.sumber
import sys
dan kemudiansys.path.append("..\<parent_folder>")
Anda dapat menggunakan impor relatif (python> = 2.5):
(Apa yang Baru di Python 2.5) PEP 328: Impor Mutlak dan Relatif
EDIT : menambahkan titik lain '.' untuk naik dua paket
sumber
ValueError: Attempted relative import in non-package
__init__.py
file.__init__.py
bukan satu-satunya hal yang harus Anda lakukan: stackoverflow.com/questions/11536764/…Impor relatif (seperti dalam
from .. import mymodule
) hanya bekerja dalam satu paket. Untuk mengimpor 'mymodule' yang ada di direktori induk modul Anda saat ini:sunting :
__file__
atribut tidak selalu diberikan. Alih-alih menggunakanos.path.abspath(__file__)
saya sekarang menyarankan menggunakan modul memeriksa untuk mengambil nama file (dan path) dari file saat inisumber
sys.path.insert(1, os.path.join(sys.path[0], '..'))
parentdir
, tetapi di salah satu jalur yang sudah ditentukansys.path
, ada modul lain dengan nama 'mymodule'. Menyisipkanparentdir
sebagai elemen pertama darisys.path
daftar memastikan bahwa modul dariparentdir
akan diimpor sebagai gantinya.sys.path.insert(1, os.path.realpath(os.path.pardir))
bekerja juga.Saya memposting jawaban yang sama juga untuk pertanyaan tentang impor dari paket saudara. Anda bisa melihatnya di sini .
Solusi tanpa
sys.path
peretasanRingkasan
packaged_stuff
)setup.py
skrip tempat Anda menggunakan setuptools.setup () .pip install -e <myproject_folder>
from packaged_stuff.modulename import function_name
Mendirikan
Saya menganggap struktur folder yang sama seperti pada pertanyaan
Saya memanggil
.
folder root, dan dalam kasus saya ini terletak diC:\tmp\test_imports
.Langkah
1) Tambahkan
setup.py
ke folder rootIsi dari
setup.py
bisa sederhanaPada dasarnya "apapun"
setup.py
akan berhasil. Ini hanya contoh kerja minimal.2) 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)
python -m venv venv
. /venv/bin/activate
(Linux) atau./venv/Scripts/activate
(Menang)Untuk mempelajari lebih lanjut tentang ini, cukup Google "tutorial python virtualenv" 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
3) pip instal proyek Anda dalam keadaan dapat diedit
Instal paket tingkat atas Anda
myproject
menggunakanpip
. Caranya adalah dengan menggunakan-e
bendera saat melakukan instalasi. Dengan cara ini diinstal dalam keadaan 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
4) Impor dengan menambahkan
mainfolder
ke setiap imporDalam contoh ini,
mainfolder
akan menjadiptdraft
. Ini memiliki keuntungan bahwa Anda tidak akan mengalami tabrakan nama dengan nama modul lain (dari pustaka standar python atau modul pihak ke-3).Contoh Penggunaan
nib.py
life.py
Menjalankan life.py
sumber
sys.path
dan di mana kode biasanya akan diinstal oleh pengguna akhir. Itu lebih baik daripadasys.path
peretasan (dan Anda dapat menyertakan menggunakan PYTHONPATH dalam kategori peretasan jalur itu) karena itu berarti kode dalam pengembangan harus berperilaku dengan cara yang sama bagi Anda seperti halnya bagi pengguna lain. Sebaliknya, ketika menggunakan modifikasi jalur, pernyataan impor akan diselesaikan dengan cara yang berbeda.Anda dapat menggunakan jalur tergantung OS di "jalur pencarian modul" yang tercantum di sys.path . Jadi Anda dapat dengan mudah menambahkan direktori induk seperti berikut
Jika Anda ingin menambahkan direktori parent-parent,
Ini berfungsi baik di python 2 dan 3.
sumber
Jika menambahkan folder modul Anda ke PYTHONPATH tidak berfungsi, Anda dapat memodifikasi daftar sys.path di program Anda di mana penerjemah Python mencari modul untuk diimpor, dokumentasi python mengatakan:
Mengetahui hal ini, Anda dapat melakukan hal berikut dalam program Anda:
sumber
/path/to/ptdraft
harus diedit. Ada solusi yang bekerja di luar direktori file saat ini dan mengimpornya dari folder induk juga.Tidak tahu banyak tentang python 2.
Dalam python 3, folder induk dapat ditambahkan sebagai berikut:
... dan kemudian seseorang dapat mengimpor modul dari itu
sumber
'..'
mengarah ke direktori dengan modul yang dimaksud.Berikut adalah jawaban yang sederhana sehingga Anda dapat melihat cara kerjanya, kecil dan lintas platform.
Ini hanya menggunakan modul built-in (
os
,sys
daninspect
) jadi harus bekerjapada sistem operasi (OS) apa pun karena Python dirancang untuk itu.
Kode pendek untuk jawaban - lebih sedikit baris dan variabel
Untuk baris yang lebih sedikit dari ini, ganti baris kedua dengan
import os.path as path, sys, inspect
,tambahkan
inspect.
di awalgetsourcefile
(baris 3) dan hapus baris pertama.- namun ini mengimpor semua modul sehingga dapat membutuhkan lebih banyak waktu, memori, dan sumber daya.
Kode untuk jawaban saya ( versi lebih panjang )
Ini menggunakan contoh dari jawaban Stack Overflow Bagaimana cara mendapatkan path dari
file yang dieksekusi saat ini di Python? untuk menemukan sumber (nama file) kode yang sedang berjalan dengan alat bawaan.
Kode saya menambahkan path file ke
sys.path
, daftar path pythonkarena ini memungkinkan Python untuk mengimpor modul dari folder itu.
Setelah mengimpor modul dalam kode, sebaiknya jalankan
sys.path.pop(0)
di baris baruketika folder yang ditambahkan memiliki modul dengan nama yang sama dengan modul lain yang diimpor
kemudian di program. Anda perlu menghapus item daftar yang ditambahkan sebelum impor, bukan jalur lain.
Jika program Anda tidak mengimpor modul lain, aman untuk tidak menghapus path file karena
setelah program berakhir (atau me-restart shell Python), setiap pengeditan dibuat
sys.path
menghilang.Catatan tentang variabel nama file
Jawaban saya tidak menggunakan
__file__
variabel untuk mendapatkan path file / nama file darikode yang sedang berjalan karena pengguna di sini sering menggambarkannya sebagai tidak dapat diandalkan . Anda tidak boleh menggunakannya
untuk mengimpor modul dari folder induk dalam program yang digunakan oleh orang lain.
Beberapa contoh di mana tidak bekerja (kutipan dari ini pertanyaan Stack Overflow):
• tidak dapat ditemukan pada beberapa platform • kadang-kadang bukan path file lengkap
sumber
sys.path.pop(0)
segera setelah mengimpor modul yang diinginkan. Namun, impor berikutnya masih pergi ke lokasi itu. Sebagai contoh, saya punyaapp/config
,app/tools
danapp/submodule/config
. Darisubmodule
, saya menyisipkanapp/
untuk importools
, kemudian menghapusapp/
dan mencoba untuk imporconfig
, tapi aku mendapatkanapp/config
bukannyaapp/submodule/config
.tools
impor juga mengimporconfig
dari direktori induk. Jadi ketika saya kemudian mencoba melakukannyasys.path.pop(0); import config
di dalamsubmodule
, berharap untuk mendapatkanapp/submodule/config
, saya benar-benar mendapatkanapp/config
. Jelas Python mengembalikan versi cache modul dengan nama yang sama dan bukan benar-benar memeriksasys.path
modul yang cocok dengan nama itu.sys.path
dalam hal ini sedang diubah dengan benar, Python tidak mengeceknya karena modul dengan nama yang sama telah dimuat.sys.modules
... sys.modules dapat ditulis. Menghapus kunci akan membatalkan entri cache untuk modul bernama, menyebabkan Python mencari lagi setelah impor berikutnya. ... Berhati-hatilah, seolah-olah Anda menyimpan referensi ke objek modul, membatalkan cache-nya lalu mengimpor kembali, kedua objek akan berbeda. Sebaliknya,importlib.reload()
akan menggunakan kembali dan menginisialisasi ulang isi modul ...os.path.realpath(getsourcefile(lambda:0) + "/../..")
. Akan mendapatkan file sumber saat ini ditambahkan dengan dua simbol direktori induk. Saya tidak menggunakanos.path.sep
sepertigetsourcefile
mengembalikan string menggunakan/
bahkan pada Windows.realpath
akan menangani pemunculan dua entri direktori dari path lengkap (dalam hal ini, nama file, dan kemudian direktori saat ini) yang memberikan direktori induk.Berikut ini adalah solusi yang lebih umum yang menyertakan direktori induk ke sys.path (berfungsi untuk saya):
sumber
import os, sys\n sys.path.insert(0,os.path.pardir)
hal yang sama, tetapi penyortir :) (tidak ada baris feed dalam komentar)os.path.pardir
Anda tidak akan mendapatkan jalur utama dari induknya, cukup jalur relatif dari tempat Anda memanggilsys.path.insert()
__file__
variabel yang bisa tidak dapat diandalkan (tidak selalu path file lengkap, tidak bekerja pada setiap sistem operasi, dll.) Seperti yang sering disebutkan pengguna StackOverflow. Mengubah jawaban untuk tidak memasukkannya akan menyebabkan lebih sedikit masalah dan lebih kompatibel lintas. Untuk informasi lebih lanjut, lihat stackoverflow.com/a/33532002/3787376 .Saya menemukan cara berikut berfungsi untuk mengimpor paket dari direktori induk skrip. Dalam contoh ini, saya ingin mengimpor fungsi
env.py
dariapp.db
paket.sumber
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path
sama sekali biasanya merupakan ide yang buruk. Anda memerlukan beberapa cara ( mis. ,PYTHONPATH
) Agar perpustakaan Anda dapat diakses oleh kode lain (atau kalau bukan itu sebenarnya perpustakaan); gunakan saja sepanjang waktu!Solusi yang disebutkan di atas juga baik-baik saja. Solusi lain untuk masalah ini adalah
Jika Anda ingin mengimpor sesuatu dari direktori tingkat atas. Kemudian,
Juga, jika Anda ingin mengimpor modul apa pun dari direktori induk. Kemudian,
Juga, jika Anda ingin mengimpor modul apa pun dari direktori induk. Kemudian,
Dengan cara ini Anda dapat mengimpor metode tertentu jika Anda mau.
sumber
sys.path.append
peretasan di atas dan saya tidak dapat mengimpor lib saya seperti ini. Inilah yang pertama kali saya coba lakukan sebelum mulai ke google :) Ok, beginiValueError: attempted relative import beyond top-level package
Bagi saya oneliner terpendek dan favorit saya untuk mengakses ke direktori induk adalah:
atau:
os.getcwd () mengembalikan nama direktori kerja saat ini, os.path.dirname (direktori_name) mengembalikan nama direktori untuk yang dilewati.
Sebenarnya, menurut saya arsitektur proyek Python harus dilakukan dengan cara di mana tidak ada modul dari direktori anak akan menggunakan modul apa pun dari direktori induk. Jika sesuatu seperti ini terjadi, perlu memikirkan kembali tentang pohon proyek.
Cara lain adalah menambahkan direktori induk ke variabel lingkungan sistem PYTHONPATH.
sumber
Dalam Notebook Jupyter
Selama Anda bekerja di Notebook Jupyter, solusi singkat ini mungkin berguna:
Ia bekerja bahkan tanpa
__init__.py
file.Saya mengujinya dengan Anaconda3 di Linux dan Windows 7.
sumber
%cd -
setelah impor, sehingga direktori notebook saat ini tetap tidak berubah.import sys sys.path.append('../')
sumber
Ketika tidak berada dalam lingkungan paket dengan
__init__.py
file pustaka pathlib (termasuk dengan> = Python 3.4) membuatnya sangat ringkas dan intuitif untuk menambahkan path direktori induk ke PYTHONPATH:sumber
jenis gaya yang sama dengan jawaban masa lalu - tetapi dalam beberapa baris: P
file mengembalikan lokasi tempat Anda bekerja
sumber
Bekerja dengan perpustakaan. Buat pustaka yang disebut nib, instal menggunakan setup.py, biarkan berada di paket-situs dan masalah Anda terpecahkan. Anda tidak harus memasukkan semua yang Anda buat dalam satu paket. Pecah-pecah.
sumber
site-packages
setiap kali mereka menjalankannya di komputer yang berbeda.Dalam sistem Linux, Anda dapat membuat tautan lunak dari folder "life" ke file nib.py. Kemudian, Anda dapat mengimpornya seperti:
sumber