Tidak bisa mendapatkan Python untuk diimpor dari folder lain

90

Saya tidak bisa mendapatkan Python untuk mengimpor modul dalam subfolder. Saya mendapatkan kesalahan saat mencoba membuat instance kelas dari modul yang diimpor, tetapi impor itu sendiri berhasil. Berikut adalah struktur direktori saya:

Server
    -server.py
    -Models
        --user.py

Berikut isi dari server.py:

from sys import path
from os import getcwd
path.append(getcwd() + "\\models") #Yes, i'm on windows
print path
import user

u=user.User() #error on this line

Dan user.py:

class User(Entity):
    using_options(tablename='users')

    username = Field(String(15))
    password = Field(String(64))
    email    = Field(String(50))
    status   = Field(Integer)
    created  = Field(DateTime)

Kesalahannya adalah: AttributeError: objek 'module' tidak memiliki atribut 'User'

ryeguy
sumber
1
Bisakah Anda menempelkan pesan kesalahan?
Harley Holcombe
Jika dari user.py, saya ingin mengimpor server.py. Apa yang saya lakukan?
Chandra Kanth

Jawaban:

142

Saya yakin Anda perlu membuat file yang disebut __init__.pydalam direktori Model sehingga python memperlakukannya sebagai modul.

Kemudian Anda dapat melakukan:

from Models.user import User

Anda dapat menyertakan kode dalam __init__.py(misalnya kode inisialisasi yang dibutuhkan beberapa kelas berbeda) atau biarkan kosong. Tapi itu pasti ada.

Dana
sumber
2
Terima kasih, saya belum pernah mendengar tentang paket sebelumnya.
ryeguy
1
Sebenarnya, saat mengimpor Python, memperlakukan blah.py dan dan blah / __ init__.py sama persis.
pi.
2
Itu tidak jelas ... Dan saya berkata pada diri saya sendiri: RTFM FMF
Alexander.Iljushkin
1
Perhatikan bahwa ini tidak akan berfungsi jika Anda menjalankan server.py dari direktori lain.
kchoi
1
bagaimana jika server.py ada di folder lain?
Mandroid
24

Anda harus membuat __init__.py di Modelssubfolder. File mungkin kosong. Ini mendefinisikan sebuah paket.

Kemudian Anda dapat melakukan:

from Models.user import User

Baca semua tentang itu di tutorial python, sini .

Ada juga artikel bagus tentang organisasi file proyek python di sini .

nosklo.dll
sumber
Bagaimana jika file TIDAK kosong?
darkgaze
12

impor pengguna

u = user.User () #error di baris ini

Karena kurangnya __init__ yang disebutkan di atas, Anda akan mengharapkan ImportError yang akan membuat masalah menjadi lebih jelas.

Anda tidak mendapatkannya karena 'pengguna' juga merupakan modul yang ada di pustaka standar. Pernyataan import Anda mengambil yang satu itu dan mencoba menemukan kelas User di dalamnya; yang tidak ada dan hanya setelah itu Anda mendapatkan kesalahan.

Biasanya merupakan ide yang baik untuk menjadikan impor Anda absolut:

import Server.Models.user

untuk menghindari ambiguitas semacam ini. Memang dari Python 2.7 'import user' tidak akan terlihat relatif terhadap modul saat ini sama sekali.

Jika Anda benar-benar menginginkan impor relatif, Anda dapat memilikinya secara eksplisit dengan Python 2.5 dan lebih tinggi menggunakan sintaks yang agak jelek:

from .user import User
bobince
sumber
9

Cara yang benar untuk mengimpor modul yang terletak di folder induk, jika Anda tidak memiliki struktur paket standar, adalah:

import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))

(Anda dapat menggabungkan dua baris terakhir tetapi cara ini lebih mudah dipahami).

Solusi ini bersifat lintas platform dan cukup umum sehingga tidak perlu dimodifikasi dalam keadaan lain.

glarrain
sumber
7

Anda kehilangan __init__.py. Dari tutorial Python:

File __init__.py diperlukan untuk membuat Python memperlakukan direktori sebagai paket yang berisi; ini dilakukan untuk mencegah direktori dengan nama umum, seperti string, menyembunyikan modul valid yang terjadi kemudian di jalur pencarian modul secara tidak sengaja. Dalam kasus yang paling sederhana, __init__.py hanya bisa menjadi file kosong, tetapi juga dapat mengeksekusi kode inisialisasi untuk paket atau menyetel variabel __all__, dijelaskan nanti.

Letakkan file kosong bernama __init__.py di direktori Model Anda, dan semuanya harus berwarna emas.

Harper Shelby
sumber
1

bagaimana Anda menuliskan parameter os.path.dirname.... perintah?

import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))
pengguna3440815
sumber
0

Cara yang saya sukai adalah memiliki __init__.py di setiap direktori yang berisi modul yang digunakan oleh modul lain, dan di titik masuk, timpa sys.path seperti di bawah ini:

def get_path(ss):
  return os.path.join(os.path.dirname(__file__), ss)
sys.path += [
  get_path('Server'), 
  get_path('Models')
]

Ini membuat file dalam direktori tertentu terlihat untuk diimpor, dan saya dapat mengimpor pengguna dari Server.py.

kchoi
sumber
0

Setelah melalui jawaban yang diberikan oleh para kontributor di atas - Zorglub29, Tom, Mark, Aaron McMillin, lucasamaral, JoeyZhao, Kjeld Flarup, Procyclinsur, martin.zaenker, tooty44 dan debugging masalah yang saya hadapi, saya menemukan kasus penggunaan yang berbeda karena yang saya hadapi masalah ini. Karenanya menambahkan pengamatan saya di bawah ini untuk referensi siapa pun.

Dalam kode saya, saya memiliki impor siklik kelas. Sebagai contoh:

src
 |-- utilities.py (has Utilities class that uses Event class)  
 |-- consume_utilities.py (has Event class that uses Utilities class)
 |-- tests
      |-- test_consume_utilities.py (executes test cases that involves Event class)

Saya mendapat kesalahan berikut ketika saya mencoba menjalankan python -m pytest tests / test_utilities.py untuk menjalankan UT yang ditulis dalam test_utilities.py.

ImportError while importing test module '/Users/.../src/tests/test_utilities.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_utilities.py:1: in <module>
    from utilities import Utilities
...
...
E   ImportError: cannot import name 'Utilities'

Cara saya menyelesaikan kesalahan adalah dengan memfaktorkan ulang kode saya untuk memindahkan fungsionalitas dalam kelas impor siklik sehingga saya dapat menghapus impor siklik kelas.

Catatan, saya memiliki __init__.pyfile di folder ' src ' saya serta folder ' tes ' dan masih bisa menyingkirkan ' ImportError ' hanya dengan memfaktorkan ulang kodenya.

Tautan stackoverflow berikut memberikan lebih banyak detail tentang ketergantungan Circular di Python .

shekharlondhe
sumber