Impor modul dari subfolder

104

Saya ingin mengimpor subfolder sebagai modul. Oleh karena itu, setiap subfolder berisi file __init__.py. Struktur folder saya seperti ini:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

Di skrip utama saya, saya mengimpor

from dirFoo.foofactory import FooFactory

Dalam file pabrik ini saya menyertakan sub modul:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

Jika saya memanggil foofactory saya, saya mendapatkan kesalahan, python itu tidak dapat mengimpor submodul foo1 dan foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1
Razer
sumber

Jawaban:

136

Tidak perlu repot dengan Anda PYTHONPATHatau di sys.pathsini.

Untuk menggunakan impor absolut dengan benar dalam sebuah paket, Anda juga harus menyertakan nama paket "root", misalnya:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

Atau Anda dapat menggunakan impor relatif :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2
Rob Wouters
sumber
47
Satu hal yang perlu diingat! tambahkan __init__.pyke setiap subfolder tempat Anda mengimpor.
Aziz Alto
6
Kosong __init__.pydapat melakukan pekerjaan itu.
cerebrou
1
Seperti apa sintaksnya jika sebelumnya Foo1ada di direktori induk dan ada kode seperti itu from Foo1 import *. Adakah cara untuk mencapai efek yang sama sehingga Anda tidak perlu mengawali semuanya dengan Foo1?
jxramos
1
@ AzizAlto: tanpa komentar Anda solusi ini tidak terlalu berguna
Alex
21

Hanya untuk memberi tahu di sini. (dari newbee, keviv22)

Tidak pernah dan selamanya demi kebaikan Anda sendiri, beri nama folder atau file dengan simbol seperti "-" atau "_". Jika Anda melakukannya, Anda mungkin menghadapi beberapa masalah. seperti milik saya, katakanlah, meskipun perintah Anda untuk mengimpor benar, Anda tidak akan berhasil mengimpor file yang diinginkan yang tersedia di dalam folder bernama tersebut.

Nama folder tidak valid sebagai berikut:

  • Generik-Kelas-Folder
  • Generic_Classes_Folder

penamaan Folder yang valid untuk di atas:

  • GenericClassesFolder atau Genericclassesfolder atau genericClassesFolder (atau seperti ini tanpa spasi atau simbol khusus di antara kata-kata)

Kesalahan apa yang saya lakukan:

pertimbangkan struktur file.

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

Apa yang ingin saya lakukan?

  • dari testFile.py, saya ingin mengimpor file 'targetClass.py' di dalam file Generic-Class-Folder untuk menggunakan fungsi bernama "functionExecute" di file 'targetClass.py'

Perintah apa yang saya lakukan?

  • dari 'testFile.py', menulis perintah, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Mendapat kesalahan seperti SyntaxError: invalid syntax

Mencoba banyak pencarian dan melihat banyak pertanyaan stackoverflow dan tidak dapat memutuskan apa yang salah. Saya memeriksa ulang file saya beberapa kali, saya menggunakan __init__.pyfile, memasukkan jalur lingkungan dan sangat khawatir apa yang salah ......

Dan setelah sekian lama, saya mengetahuinya saat berbicara dengan teman saya. Saya agak bodoh menggunakan konvensi penamaan seperti itu. Saya tidak boleh menggunakan spasi atau simbol khusus untuk menentukan nama folder atau file apa pun. Jadi, ini yang ingin saya sampaikan. Semoga harimu menyenangkan!

(maaf untuk kiriman besar ini ... biarkan saja rasa frustasiku pergi .... :) Terima kasih!)

Vivek 22
sumber
22
Spasi dan tanda hubung ("-") akan menyebabkan hal ini, tetapi garis bawah ("_") seharusnya masih berfungsi dengan baik.
Cowlinator
6

Setel variabel lingkungan PYTHONPATH Anda. Misalnya seperti ini PYTHONPATH =.: .. (untuk * nix family).

Anda juga dapat secara manual menambahkan direktori Anda saat ini (src dalam kasus Anda) ke pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())
Max Kamenkov
sumber
2

Katakanlah proyek Anda terstruktur seperti ini:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

Di dalamnya run.py, Anda dapat mengimpor skrip satu dan dua dengan:

from subscripts import script_one as One
from subscripts import script_two as Two

Sekarang, masih di dalam run.py, Anda akan dapat memanggil metode mereka dengan:

One.method_from_one(param)
Two.method_from_two(other_param)
Flavio Wuensche
sumber
1

Cukup buat file ___init____.py kosong dan tambahkan di root serta semua sub direktori / folder aplikasi python Anda di mana Anda memiliki modul python lainnya.

Abhijit Pritam Dutta
sumber
-2

Mengalami masalah bahkan saat init .py ada di subfolder dan semua yang hilang adalah menambahkan 'sebagai' setelah impor

from folder.file import Class as Class
import folder.file as functions
Tomas Trdla
sumber