Đối tượng TypeError: 'module' không thể gọi được


543
File "C:\Users\Administrator\Documents\Mibot\oops\blinkserv.py", line 82, in __init__
    self.serv = socket(AF_INET,SOCK_STREAM)
TypeError: 'module' object is not callable

Tại sao tôi nhận được lỗi này? Tôi bối rối.

Bạn cần biết gì để trả lời câu hỏi của tôi?


8
Tôi đã từng gặp lỗi này vì tôi có cả biến (toàn cầu) và hàm có cùng tên.
remustata

Câu trả lời:


563

socketlà một mô-đun, chứa các lớp socket.

Bạn cần phải làm socket.socket(...)hoặc from socket import socket:

>>> import socket
>>> socket
<module 'socket' from 'C:\Python27\lib\socket.pyc'>
>>> socket.socket
<class 'socket._socketobject'>
>>>
>>> from socket import socket
>>> socket
<class 'socket._socketobject'>

Đây là ý nghĩa của thông báo lỗi:
Nó nói module object is not callable, bởi vì mã của bạn đang gọi một đối tượng mô-đun . Đối tượng mô-đun là loại điều bạn nhận được khi nhập mô-đun. Những gì bạn đã cố gắng làm là gọi một đối tượng lớp trong đối tượng mô-đun xảy ra có cùng tên với mô-đun chứa nó.

Đây là một cách để phá vỡ logic loại lỗi này:

  • " module object is not callable. Python đang nói với tôi mã của tôi đang cố gọi thứ gì đó không thể gọi được. Mã của tôi đang cố gọi là gì?"
  • "Mã đang cố gắng gọi socket. Điều đó có thể gọi được! Biến socketcó phải là cái tôi nghĩ không? '
  • Tôi nên in ra ổ cắm là gì và kiểm tra print socket

Tôi hiện đang sử dụng ổ cắm như thế này: từ nhập ổ cắm *
user551717

Tôi cũng đã thay đổi nó từ ổ cắm nhập ổ cắm và tôi vẫn gặp lỗi tương tự.
dùng551717

@user: nếu bạn print socketsẽ thấy tên đó socketlà một mô-đun. Nó đã được ràng buộc với mô-đun đó ở đâu đó ! Đọc kỹ mã của bạn và tôi chắc chắn bạn sẽ thấy một import sockethoặc một số nơi mà bạn không mong đợi nó.
Katriel

2
Ồ tôi hiểu rồi Có socket.socketmột chút bối rối. Tôi chỉ đơn giản là làm import write_to_filevà sau đó, vì phương pháp tôi đang sử dụng bên trong write_to_file.pyđược đặt tên là writeToTextFiletôi chỉ đơn giản là randwrite_to_file.writeToTextFile
maudulus

9
Điều đáng chú ý là điều này không rõ ràng với ít nhất 133 người đã dành thời gian để bỏ phiếu (bao gồm cả bản thân tôi), những người không hiểu điều này. Bây giờ, điều đó là hiển nhiên và khi tôi tiếp cận trong hộp công cụ của mình, tôi sẽ tìm thấy công cụ này khi một mô-đun được báo cáo là "không thể gọi được". Bắt đầu với một ngôn ngữ mới là phần khó nhất.
jmort253

168

Giả sử rằng nội dung của YourClass.py là:

class YourClass:
    # ......

Nếu bạn dùng:

from YourClassParentDir import YourClass  # means YourClass.py

Theo cách này, tôi đã nhận được đối tượng TypeError: 'module' không thể gọi được nếu sau đó bạn đã cố gắng sử dụng YourClass().

Nhưng, nếu bạn sử dụng:

from YourClassParentDir.YourClass import YourClass   # means Class YourClass

hoặc sử dụng YourClass.YourClass(), nó làm việc cho tôi.


2
class = YourClass.YourClass ()
Xie

2
Tôi đã giải quyết vấn đề này bằng cách sử dụng từ nhập khẩu YourClass *
Keith

104

Thêm vào chính __init__.pytrong YourClassParentDir, ví dụ:

from .YourClass import YourClass

Sau đó, bạn sẽ có một thể hiện của lớp của bạn sẵn sàng khi bạn nhập nó vào một tập lệnh khác:

from YourClassParentDir import YourClass

5
Không nên có from .YourClass import YourClass trong __init__.pytập tin?
Nicolas Seiller

28

Đây là một gotcha khác, tôi đã mất một lúc để xem ngay cả sau khi đọc những bài viết này. Tôi đã thiết lập một kịch bản để gọi các kịch bản bin python của tôi. Tôi đã nhận được các mô-đun không thể gọi quá.

Zig của tôi là tôi đã làm như sau:

from mypackage.bin import myscript
...
myscript(...)

khi zag của tôi cần phải làm như sau:

from mypackage.bin.myscript import myscript
...
myscript(...)

Tóm lại, kiểm tra lại gói và mô-đun lồng của bạn.

Những gì tôi đang cố gắng làm là có một thư mục script không có phần mở rộng * .py và vẫn có các mô-đun 'bin' nằm trong mypackage / bin và chúng có phần mở rộng * .py của tôi. Tôi chưa quen với việc đóng gói và cố gắng tuân theo các tiêu chuẩn khi tôi diễn giải chúng. Vì vậy, tôi có tại root thiết lập:

setup.py
scripts/
      script1
mypackage/
   bin/
      script1.py
   subpackage1/
   subpackage_etc/

Nếu điều này không tuân thủ tiêu chuẩn, xin vui lòng cho tôi biết.


22

Có vẻ như những gì bạn đã làm được nhập socketmô-đun như import socket. Do đó socketlà mô-đun. Bạn cần phải thay đổi dòng đó thành self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM), cũng như mọi cách sử dụng khác của socketmô-đun, hoặc thay đổi câu lệnh nhập thành from socket import socket.

Hoặc bạn đã có import socketsau from socket import *:

>>> from socket import *
>>> serv = socket(AF_INET,SOCK_STREAM)
>>> import socket
>>> serv = socket(AF_INET,SOCK_STREAM)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'module' object is not callable

Tôi đã nhập ổ cắm dưới dạng: từ nhập ổ cắm * Tôi có thể thay đổi ổ cắm, nhưng sẽ mất một lúc, vì vậy tôi miễn cưỡng.
dùng551717

@user Có lẽ sau này bạn đã có một nơi import socket, sẽ nhập mô-đun ghi socketđè lên lớp socket. Xem đoạn mã trong chỉnh sửa.
moinudin

3
@user: bạn nên thay đổi nó Lý do from <...> import *nhập khẩu là xấu, xấu, xấu ít nhiều là thế này: thông thường bạn biết chính xác những gì trong không gian tên toàn cầu, bởi vì đó chính xác là những gì bạn đã đặt ở đó. Nhưng khi bạn import *, bạn lấp đầy không gian tên đó với tất cả các loại nội dung mà các mô-đun khác xác định. Trong trường hợp này, không rõ tên socketđến từ đâu - đó là mô-đun hoặc một cái gì đó được xác định trong mô-đun đó? Nếu bạn luôn sử dụng import sockethoặc from socket import socket, bạn sẽ không bao giờ gặp phải vấn đề này, vì bạn có thể thấy chính xác tên nào đang được sử dụng.
Katriel

Được chứ. Cảm ơn vì tiền hỗ trợ. Tôi đã có thói quen từ rất nhiều hướng dẫn.
dùng551717

7

Tôi biết chủ đề này là một năm tuổi, nhưng vấn đề thực sự là trong thư mục làm việc của bạn.

Tôi tin rằng các thư mục làm việc là C:\Users\Administrator\Documents\Mibot\oops\. Vui lòng kiểm tra các tập tin có tên socket.pytrong thư mục này. Một khi bạn tìm thấy nó, đổi tên hoặc di chuyển nó. Khi bạn nhập ổ cắm, socket.pytừ thư mục hiện tại được sử dụng thay vì socket.pytừ thư mục của Python. Hy vọng điều này sẽ giúp. :)

Lưu ý: Không bao giờ sử dụng tên tệp từ thư mục của Python để lưu tên tệp chương trình của bạn; nó sẽ xung đột với (các) chương trình của bạn.


1
Điều này chắc chắn đáng chú ý. Tôi chỉ đang thử kiểm tra nhanh với các ổ cắm nên tôi chỉ cần đặt tên cho tệp socket.py. Vâng, đó là nguyên nhân chính xác thông báo lỗi này. Trang này đưa tôi đi đúng hướng: python-notes.curiouseffic.org/en/latest/python_con accept / ám
Công nghệ

0

Khi định cấu hình điểm truy cập console_scripts trong setup.py tôi thấy vấn đề này tồn tại khi điểm cuối là mô-đun hoặc gói chứ không phải là một chức năng trong mô-đun.

Traceback (most recent call last):
   File "/Users/ubuntu/.virtualenvs/virtualenv/bin/mycli", line 11, in <module>
load_entry_point('my-package', 'console_scripts', 'mycli')()
TypeError: 'module' object is not callable

Ví dụ

from setuptools import setup
setup (
# ...
    entry_points = {
        'console_scripts': [mycli=package.module.submodule]
    },
# ...
)

Đáng lẽ phải

from setuptools import setup
setup (
# ...
    entry_points = {
        'console_scripts': [mycli=package.module.submodule:main]
    },
# ...
)

Vì vậy, nó sẽ đề cập đến một chức năng có thể gọi được chứ không phải là chính mô-đun. Nó dường như không có sự khác biệt nếu mô-đun có một if __name__ == '__main__':khối. Điều này sẽ không làm cho mô-đun có thể gọi được.


0

Tôi đoán bạn đã ghi đè hàm / biến dựng sẵn hoặc "mô-đun" nào khác bằng cách đặt "mô-đun" biến toàn cục. Chỉ cần in các mô-đun xem những gì trong đó.


0

kiểm tra các báo cáo nhập khẩu vì một mô-đun không thể gọi được. Trong Python, mọi thứ (bao gồm các hàm, phương thức, mô-đun, lớp, v.v.) là một đối tượng.


-1

Một cách đơn giản để giải quyết vấn đề này là xuất PYTHONPATHmôi trường biến. Ví dụ: đối với Python 2.6 trong Debian / GNU Linux:

export PYTHONPATH=/usr/lib/python2.6`

Trong các hệ điều hành khác, trước tiên bạn sẽ tìm thấy vị trí của mô-đun này hoặc socket.pytệp.

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.