我在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'
有人知道如何解决这个问题吗?
答案 0 :(得分:0)
这很可能是寻路错误。 Python路径将在安装的lib
和site-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
前两个模块sys
和os
非常标准,将为您提供附加到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的位置不同。