Không thể lấy Python để nhập từ một thư mục khác


90

Tôi dường như không thể lấy Python để nhập một mô-đun trong một thư mục con. Tôi gặp lỗi khi cố gắng tạo một phiên bản của lớp từ mô-đun đã nhập, nhưng quá trình nhập thành công. Đây là cấu trúc thư mục của tôi:

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

Đây là nội dung của 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

Và 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)

Lỗi là: AttributeError: đối tượng 'mô-đun' không có thuộc tính 'Người dùng'


1
Bạn có thể dán thông báo lỗi?
Harley Holcombe

Nếu từ user.py, tôi muốn nhập server.py. Tôi làm gì?
Chandra Kanth,

Câu trả lời:


139

Tôi tin rằng bạn cần tạo một tệp có tên __init__.pytrong thư mục Mô hình để python xử lý nó như một mô-đun.

Sau đó, bạn có thể làm:

from Models.user import User

Bạn có thể đưa mã vào __init__.py(ví dụ: mã khởi tạo mà một số lớp khác nhau cần) hoặc để trống. Nhưng nó phải ở đó.


2
Cảm ơn, tôi chưa bao giờ nghe nói về gói này trước đây.
ryeguy

1
Trên thực tế, khi nhập Python xử lý blah.py và và blah / __ init__.py hoàn toàn giống nhau.
pi.

2
Đó là unobvious ... Và tôi nói với bản thân mình: RTFM FMF
Alexander.Iljushkin

1
Lưu ý rằng điều này sẽ không hoạt động nếu bạn đang chạy server.py từ một thư mục khác.
kchoi

1
điều gì xảy ra nếu server.py nằm trong một thư mục khác?
Mandroid

24

Bạn phải tạo __init__.pytrên Modelsthư mục con. Tệp có thể trống. Nó định nghĩa một gói.

Sau đó, bạn có thể làm:

from Models.user import User

Đọc tất cả về nó trong hướng dẫn python, tại đây .

Ngoài ra còn có một bài viết tốt về tổ chức tập tin của dự án python đây .


Điều gì xảy ra nếu tệp KHÔNG trống?
darkgaze

12

nhập người dùng

u = user.User () #error trên dòng này

Do thiếu __init__ được đề cập ở trên, bạn sẽ mong đợi một ImportError sẽ làm cho vấn đề trở nên rõ ràng hơn.

Bạn không nhận được vì 'người dùng' cũng là một mô-đun hiện có trong thư viện chuẩn. Câu lệnh nhập của bạn lấy câu lệnh đó và cố gắng tìm lớp Người dùng bên trong nó; điều đó không tồn tại và chỉ khi đó bạn mới gặp lỗi.

Nói chung, bạn nên làm cho việc nhập của bạn là tuyệt đối:

import Server.Models.user

để tránh loại mơ hồ này. Thật vậy, từ 'nhập người dùng' Python 2.7 sẽ không giống với mô-đun hiện tại chút nào.

Nếu bạn thực sự muốn nhập tương đối, bạn có thể có chúng một cách rõ ràng trong Python 2.5 trở lên bằng cách sử dụng cú pháp hơi xấu xí:

from .user import User

9

Cách phù hợp để nhập mô-đun nằm trên thư mục mẹ, khi bạn không có cấu trúc gói tiêu chuẩn, là:

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

(bạn có thể gộp 2 dòng cuối nhưng cách này dễ hiểu hơn).

Giải pháp này là đa nền tảng và đủ chung để không cần sửa đổi trong các trường hợp khác.


7

Bạn đang thiếu __init__.py. Từ hướng dẫn Python:

Các tệp __init__.py được yêu cầu để Python coi các thư mục là chứa các gói; điều này được thực hiện để ngăn các thư mục có tên chung, chẳng hạn như chuỗi, vô tình ẩn các mô-đun hợp lệ xảy ra sau này trên đường dẫn tìm kiếm mô-đun. Trong trường hợp đơn giản nhất, __init__.py có thể chỉ là một tệp trống, nhưng nó cũng có thể thực thi mã khởi tạo cho gói hoặc đặt biến __all__, được mô tả sau.

Đặt một tệp trống có tên __init__.py trong thư mục Mô hình của bạn và tất cả đều phải có màu vàng.


1

làm thế nào để bạn viết ra các tham số os.path.dirname.... lệnh?

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

0

Cách ưa thích của tôi là có __init__.py trên mọi thư mục có chứa các mô-đun được các mô-đun khác sử dụng và trong điểm nhập, ghi đè sys.path như bên dưới:

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

Điều này làm cho các tệp trong thư mục được chỉ định hiển thị để nhập và tôi có thể nhập người dùng từ Server.py.


0

Sau khi xem qua các câu trả lời được đưa ra bởi những người đóng góp ở trên - Zorglub29, Tom, Mark, Aaron McMillin, lucasamaral, JoeyZhao, Kjeld Flarup, Procyclinsur, martin.zaenker, tooty44 và gỡ lỗi vấn đề mà tôi đang gặp phải, tôi đã phát hiện ra một trường hợp sử dụng khác do mà tôi đã phải đối mặt với vấn đề này. Do đó thêm các quan sát của tôi bên dưới để mọi người tham khảo.

Trong mã của tôi, tôi đã nhập tuần hoàn các lớp. Ví dụ:

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)

Tôi gặp lỗi sau khi cố gắng thực thi python -m pytest tests / test_utilities.py để thực thi UT được viết trong 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'

Cách tôi giải quyết lỗi là bằng cách tính lại mã của mình để di chuyển chức năng trong lớp nhập tuần hoàn để tôi có thể loại bỏ lớp nhập theo chu kỳ.

Lưu ý, tôi có __init__.pytệp trong thư mục ' src ' cũng như thư mục ' tests ' và vẫn có thể loại bỏ ' ImportError ' chỉ bằng cách tính lại mã.

Liên kết stackoverflow sau cung cấp nhiều chi tiết hơn về sự phụ thuộc của Tròn trong Python .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.