Python:尝试从另一个编码的.py文件导入模块时出现“ ModuleNotFoundError”

时间:2020-03-17 17:51:38

标签: python python-3.x

我在MacBook Pro(13英寸,2016年,两个Thunderbolt 3端口)上使用Python 3.8.3

我目前正在建立在线聊天,这是我的person.py代码:

class Person:

    """
    Represents a person, hold name, socket client and client addr
    """
    def __init__(self, addr, client):
        self.addr = addr
        self.client = client
        self.name = None

    def set_name(self, name):
        self.name = name

    def __repr__(self):
        return f"Person({self.addr}, {self.name})"

这是我的server.py编码:

from threading import Thread
import time
from person import Person

# GLOBAL CONSTANTS
HOST = 'localhost'
PORT = 5500
ADDR = (HOST, PORT)
MAX_CONNECTIONS = 10
BUFSIZ = 512

# GLOBAL VARIABLES
persons = []
SERVER = socket(AF_INET, SOCK_STREAM)
SERVER.bind(ADDR)  # set up server

def broadcast(msg, name):
    """
    send new messages to all clients
    :param msg: bytes["utf8"]
    :param name: str
    :return:
    """
    for person in persons:
        client = person.client
        client.send(bytes(name, "utf8") + msg)


def client_communication(person):
    """
    Thread to handle all messages from client
    :param person: Person
    :return: None
    """
    client = person.client

    # get persons name
    name = client.recv(BUFSIZ).decode("utf8")
    person.set_name(name)
    msg = bytes(f"{name} has joined the chat!", "utf8")
    broadcast(msg, "")  # broadcast welcome message


    while True:
        try:
            msg = client.recv(BUFSIZ)

            if msg == bytes("{quit}", "utf8"):
                client.close()
                persons.remove(person)
                broadcast(f"{name} has left the chat...", "")
                print(f"[DISCONNECTED] {name} disconnected")
                break
            else:
                broadcast(msg, name+": ")
                print(f"{name}: ", msg.decode("utf8"))

        except Exception as e:
            print("[EXCEPTION]", e)
            break


def wait_for_connection():
    """
    Wait for connetion from new clients, start new thread once connected
    :param SERVER: SOCKET
    :return: None
    """
    run = True
    while run:
        try:
            client, addr = SERVER.accept()
            person = Person(addr, client)
            persons.append(person)
            print(f"[CONNECTION] {addr} connected to the server at {time.time()}")
            Thread(target=client_communication, args=(person,)).start()
        except Exception as e:
            print("[EXCEPTION]", e)
            run = False

    print("SERVER CRASHED")


if __name__ == "__main__":
    SERVER.listen(MAX_CONNECTIONS)  # listen for connections
    print("[STARTED] Waiting for connections...")
    ACCEPT_THREAD = Thread(target=wait_for_connection)
    ACCEPT_THREAD.start()
    ACCEPT_THREAD.join()
    SERVER.close()

问题是,每次我尝试运行该程序时,都会出现此错误:

    from person import Person
ModuleNotFoundError: No module named 'person'

有人知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

问题

这很可能是寻路错误。 Python路径将在安装的libsite-packages文件夹中查找。它还将查看当前的工作目录。因此,如果您正在从另一个文件夹中运行一个文件,但是尝试导入某些文件,它将在您的运行目录中查找,而不是您正在运行的文件的位置。这是解决此问题的两种方法。

第一个解决方案

您可以使工作目录与正在运行的文件相同。给出以下文件结构:

workingdir
+-- thecode
    |-- server.py
    +-- person.py

您具有当前的工作目录,也可以在workingdir中运行命令,因此终端可能看起来像这样:

workingdir % python thecode/server.py

因此,您需要将工作目录更改为thecode。做cd thecode到达那里。

第二个解决方案

您可以改为将文件目录添加到python路径。这保存在sys.path中,并在每次python运行结束时获取。因此,最好在您的server.py文件的开头添加路径,以使person.py在导入之前就在您的路径中。使用类似以下代码的代码来做到这一点。

import sys
import os.path
sys.path.append(os.path.split(os.path.abspath(__file__))[0])

# now you may import Person.
from person import Person

前两个模块sysos非常标准,将为您提供附加到Python路径的工具。 os.path.abspath获取当前文件的绝对路径,在本例中为server.py。然后os.path.split将获得绝对路径的结尾(所有目录)和标题(文件名)。最后,附加到sys.path后,Python可以在文件目录中找到person.py

其他解决方案(在这种情况下可能不会使用)

您还可以创建自定义Python软件包并使用pip安装它。在这种情况下,这不是很有用,因为导入问题只是一个文件,但是,如果您要创建一个其他人可能使用this Python docs article will help的自定义Python项目。

最终的解决方案(我曾经做过,但这并不是最佳解决方法)是将文件放在Python路径中已经存在的文件夹中。在这种情况下,它可能是lib文件夹。对我而言,运行Python 3.8的路径为/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8,对于任何Python 3.x版本,该路径都相同,但已替换该版本。有时Python 2.x的位置不同。