Bayangkan struktur direktori ini:
app/
__init__.py
sub1/
__init__.py
mod1.py
sub2/
__init__.py
mod2.py
Saya sedang coding mod1
, dan saya perlu mengimpor sesuatu mod2
. Bagaimana saya harus melakukannya?
Saya mencoba from ..sub2 import mod2
tetapi saya mendapatkan "Impor relatif non-paket".
Saya mencari-cari di sekitar tetapi hanya menemukan sys.path
hacks "manipulasi". Apakah tidak ada cara yang bersih?
Sunting: semua milik saya __init__.py
saat ini kosong
Edit2: Saya mencoba untuk melakukan hal ini karena Sub2 berisi kelas yang dibagi di sub paket ( sub1
, subX
, dll).
Sunting3: Perilaku yang saya cari adalah sama seperti yang dijelaskan dalam PEP 366 (terima kasih John B)
Jawaban:
Semua orang tampaknya ingin memberi tahu Anda apa yang harus Anda lakukan daripada hanya menjawab pertanyaan.
Masalahnya adalah Anda menjalankan modul sebagai '__main__' dengan melewatkan mod1.py sebagai argumen ke penerjemah.
Dari PEP 328 :
Dalam Python 2.6, mereka menambahkan kemampuan untuk referensi modul relatif ke modul utama. PEP 366 menjelaskan perubahan tersebut.
Pembaruan : Menurut Nick Coghlan, alternatif yang disarankan adalah menjalankan modul di dalam paket menggunakan saklar -m.
sumber
-m
sakelar, alih-alih dengan menentukan nama file secara langsung.from sub2 import mod2
. Kemudian, untuk menjalankan mod1, dari dalam aplikasi, lakukanpython -m sub1.mod1
.Inilah solusi yang berfungsi untuk saya:
Saya melakukan impor relatif sebagai
from ..sub2 import mod2
dan kemudian, jika saya ingin menjalankanmod1.py
maka saya pergi ke direktori indukapp
dan menjalankan modul menggunakan saklar python -m sebagaipython -m app.sub1.mod1
.Alasan sebenarnya mengapa masalah ini terjadi pada impor relatif, adalah impor relatif bekerja dengan mengambil
__name__
properti modul. Jika modul sedang dijalankan secara langsung, maka__name__
diatur ke__main__
dan tidak mengandung informasi tentang struktur paket. Dan, itu sebabnya python mengeluh tentangrelative import in non-package
kesalahan tersebut.Jadi, dengan menggunakan sakelar -m Anda memberikan informasi struktur paket ke python, yang dengannya ia dapat menyelesaikan impor relatif dengan sukses.
Saya telah mengalami masalah ini berkali-kali saat melakukan impor relatif. Dan, setelah membaca semua jawaban sebelumnya, saya masih tidak dapat menemukan cara untuk menyelesaikannya, dengan cara yang bersih, tanpa perlu memasukkan kode boilerplate di semua file. (Meskipun beberapa komentar sangat membantu, terima kasih kepada @ncoghlan dan @XiongChiamiov)
Semoga ini membantu seseorang yang berjuang dengan masalah impor relatif, karena melalui PEP benar-benar tidak menyenangkan.
sumber
-m
dirancang untuk dipecahkan.from . import some_module
.python main.py
.main.py
tidak:import app.package_a.module_a
module_a.py
tidakimport app.package_b.module_b
Atau 2 atau 3 dapat menggunakan:
from app.package_a import module_a
Itu akan bekerja selama Anda miliki
app
di PYTHONPATH Anda.main.py
bisa di mana saja kalau begitu.Jadi, Anda menulis
setup.py
untuk menyalin (menginstal) seluruh paket aplikasi dan subpackages ke folder python sistem target, danmain.py
untuk menargetkan folder skrip sistem.sumber
"Guido memandang menjalankan skrip dalam sebuah paket sebagai anti-pola" (ditolak PEP-3122 )
Saya telah menghabiskan banyak waktu untuk mencari solusi, membaca posting terkait di sini di Stack Overflow dan berkata pada diri sendiri "pasti ada cara yang lebih baik!". Sepertinya tidak ada.
sumber
-m
sakelar:python -m app.sub1.mod1
atau memanggilapp.sub1.mod1.main()
dari skrip tingkat atas (mis., dihasilkan dari entry_points setuptools yang ditentukan dalam setup.py).Ini diselesaikan 100%:
Impor pengaturan / local_setting.py di app / main.py:
main.py:
sumber
sys.path.insert(0, "../settings")
dan kemudianfrom local_settings import *
Saya menggunakan cuplikan ini untuk mengimpor modul dari jalur, semoga bisa membantu
sumber
penjelasan
nosklo's
jawaban dengan contohcatatan: semua
__init__.py
file kosong.app / package_a / fun_a.py
app / package_b / fun_b.py
main.py
jika Anda menjalankannya
$ python main.py
kembali:from app.package_b import fun_b
from app.package_a.fun_a import print_a
jadi file dalam folder
package_b
menggunakan file dalam folderpackage_a
, yang adalah apa yang Anda inginkan. Baik??sumber
Sayangnya ini adalah hack sys.path, tetapi ia bekerja dengan cukup baik.
Saya mengalami masalah ini dengan lapisan lain: Saya sudah memiliki modul dengan nama yang ditentukan, tetapi itu adalah modul yang salah.
apa yang ingin saya lakukan adalah sebagai berikut (modul tempat saya bekerja adalah module3):
Perhatikan bahwa saya telah menginstal mymodule, tetapi dalam instalasi saya, saya tidak memiliki "mymodule1"
dan saya akan mendapatkan ImportError karena mencoba mengimpor dari modul yang diinstal.
Saya mencoba melakukan sys.path.append, dan itu tidak berhasil. Apa yang berhasil adalah sys.path.insert
Semacam hack, tapi semuanya berhasil! Jadi perlu diingat, jika Anda ingin keputusan Anda untuk menimpa jalur lain maka Anda perlu menggunakan sys.path.insert (0, pathname) untuk membuatnya berfungsi! Ini adalah titik yang sangat menyebalkan bagi saya, banyak orang mengatakan untuk menggunakan fungsi "append" untuk sys.path, tetapi itu tidak berfungsi jika Anda sudah memiliki modul yang ditentukan (saya menemukan perilaku yang sangat aneh)
sumber
sys.path.append('../')
berfungsi dengan baik untuk saya (Python 3.5.2)Biarkan saya letakkan ini di sini untuk referensi saya sendiri. Saya tahu bahwa itu bukan kode Python yang baik, tetapi saya membutuhkan skrip untuk proyek yang sedang saya kerjakan dan saya ingin meletakkan skrip dalam
scripts
direktori.sumber
Seperti yang dikatakan @EvgeniSergeev dalam komentar di OP, Anda dapat mengimpor kode dari
.py
file di lokasi acak dengan:Ini diambil dari jawaban SO ini .
sumber
Lihatlah http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-import . Anda bisa melakukannya
sumber
Dari Python doc ,
sumber
Saya menemukan lebih mudah untuk mengatur variabel lingkungan "PYTHONPATH" ke folder teratas:
kemudian:
tentu saja, PYTHONPATH adalah "global", tetapi itu belum menimbulkan masalah bagi saya.
sumber
virtualenv
Anda mengelola laporan impor Anda.Di atas apa yang dikatakan John B, sepertinya mengatur
__package__
variabel harus membantu, alih-alih mengubah__main__
yang dapat mengacaukan hal-hal lain. Tetapi sejauh yang saya bisa uji, itu tidak sepenuhnya berfungsi sebagaimana mestinya.Saya memiliki masalah yang sama dan PEP 328 atau 366 tidak menyelesaikan masalah sepenuhnya, karena keduanya, pada akhir hari, membutuhkan kepala paket untuk dimasukkan
sys.path
, sejauh yang saya bisa mengerti.Saya juga harus menyebutkan bahwa saya tidak menemukan cara memformat string yang harus dimasukkan ke dalam variabel tersebut. Apakah itu
"package_head.subfolder.module_name"
atau apa?sumber
Anda harus menambahkan jalur modul ke
PYTHONPATH
:sumber
sys.path
, karenasys.path
akan diinisialisasi dariPYTHONPATH
sys.path
perlu di-hardcode dalam kode sumber berbeda denganPYTHONPATH
yang merupakan variabel lingkungan dan dapat diekspor.