Pertanyaan Impor modul dari direktori (paket) satu tingkat ke atas


Apa cara yang benar dalam Python untuk mengimpor modul dari direktori satu tingkat ke atas? Direktori adalah paket Python dengan semua modul ini dan saya memiliki sub direktori dengan kode yang membutuhkan modul-modul ini.

Berikut ini berfungsi dengan baik, tetapi itu hanya sebuah retasan. Saya ingin cara yang disarankan / pythonic.

import sys
sys.path.append("../")
from fruit import Fruit
print("OK")

Struktur direktori:

pkg1
   __init__.py  
   fruit.py  
   +sub_pkg
      __init__.py
      recipe.py

isi buah.py

class Fruit:
   def get_name(self):
       print("Fruit name")

Isi dari sub_pkg/recipe.py .. hanya satu baris impor:

from fruit import Fruit

Ketika saya menjalankan:

python recipe.py

ini memberikan kesalahan berikut.

Traceback (most recent call last):
  File "recipe.py", line 2, in <module>
    from fruit import Fruit
ImportError: No module named fruit

Saya juga mencoba: from pkg1.fruit import Fruit , tidak bekerja. Juga melihat pertanyaan serupa lainnya .. python -m recipe.py  atau python -m sub_pkg/recipe.py tidak bekerja.


7
2017-09-24 17:21


asal


Jawaban:


Di file utama Anda recipe.py menambahkan pkg1 jalan menuju PYTHONPATH

sys.path.append('/path/to/pkg1')

Atau gunakan jalur relatif

sys.path.append('../..')

Ini harus memungkinkan impor pkg1 dari mana saja di program Anda.

Selalu ada pilihan untuk menggunakan impor relatif seperti yang disarankan di sini, saya menemukan penggunaan impor mutlak lebih mudah dibaca dan cenderung mengarah ke bug. Juga, dalam proyek-proyek besar yang menggunakan impor relatif akan membuat Anda terus-menerus menghitung hierarki jalur ketika menggunakan impor absolut, sangat mudah untuk mengetahui bahwa Anda selalu mengacu pada satu direktori root.

Tentang impor relatif dari PEP328 dengan Python 2.5:

Membaca kode yang bergantung pada impor relatif juga kurang jelas, karena pembaca mungkin bingung tentang modul mana yang dimaksudkan untuk digunakan. Pengguna Python segera belajar untuk tidak menggandakan nama modul pustaka standar dalam nama submodul paket mereka, tetapi Anda tidak dapat melindungi agar nama submodul Anda digunakan untuk modul baru yang ditambahkan dalam versi Python di masa mendatang.


Guido menyarankan menggunakan titik-titik utama dalam impor relatif untuk menghindari impor rancu seperti yang dijelaskan di atas, dari PEP328 lagi:

Guido telah menyatakan bahwa impor relatif akan menggunakan titik-titik utama. Titik tunggal tunggal menunjukkan impor relatif, dimulai dengan paket saat ini. Dua atau lebih titik-titik utama memberikan impor relatif ke induk (s) dari paket saat ini, satu tingkat per titik setelah yang pertama.


2
2017-09-24 19:18



Jika Anda mengalami masalah, Anda dapat menggunakan yang berikut juga.

Ini impor dari direktori saat ini

from . import something

impor ini dari satu direktori di atas

from .. import fruit

Dok untuk jalur relatif: https://docs.python.org/2/tutorial/modules.html#intra-package-references

PAKET RELATIF MASALAH ValueError: Mencoba mengimpor relatif dalam bukan paket

Untuk orang yang memiliki masalah dengan paket relatif. Inilah solusi Anda.

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name"

Juga penjelasannya, disalin dari yang lain dokumen python

Ketika modul utama ditentukan oleh namafile, maka paket atribut akan disetel ke Tidak ada. Untuk memungkinkan impor relatif ketika modul dijalankan secara langsung, boilerplate mirip dengan yang berikut ini akan diperlukan sebelum pernyataan impor relatif pertama:

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name

Perhatikan bahwa boiler ini cukup hanya jika paket tingkat atas sudah dapat diakses melalui sys.path. Kode tambahan yang memanipulasi sys.path akan diperlukan agar eksekusi langsung dapat berfungsi tanpa paket tingkat atas yang sudah dapat diimpor.

Dok untuk membuat paket Saya tidak akan menempel konten karena agak panjang, tapi inilah bagian pada python docs untuk membuat paket. https://docs.python.org/2/tutorial/modules.html#packages

Satu lagi dokumen di PYTHONPATH https://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH


2
2017-09-24 17:48



Kamu dapat memakai impor relatif:

from ..fruit import Fruit

0
2017-09-24 17:48



Alih-alih menggunakan impor atas, memiliki titik masuk yang dapat Anda hubungi dari tingkat paling atas dan impor Anda relatif terhadap titik masuk tersebut di recipe.py mengajukan.

Ex:

pkg1/
   __init__.py  
   main.py
   fruit.py  
   +sub_pkg
      __init__.py
      recipe.py

Dimana main.py mengandung:

#!/usr/bin/env python3

import subpkg.recipe as recipe
import fruit

if __package__ is None and __name__ == "__main__":
    __package__ = "main"
    print()
    # Call recipe.py or fruit.py methods from here

Dan masuk recipe.py:

import fruit
# do stuff with fruit module, which is properly imported now

Untuk menjalankan, panggil python3 main.py


-1
2017-09-24 18:01