python - Python:尝试从另一个编码 .py 文件导入模块时出现“ModuleNotFoundError”
问题描述
我在 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'
有人知道如何解决这个问题吗?
解决方案
问题
这很可能是寻路错误。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
允许 Pythonperson.py
在您的文件目录中查找。
其他解决方案(在这种情况下可能不会使用)
您还可以创建自定义 Python 包并使用pip
. 这在这种情况下不是很有用,因为导入问题只是一个文件,但是,如果您想创建一个其他人可能使用的自定义 Python 项目,这篇 Python 文档文章会有所帮助。
最终的解决方案(诚然,我曾经这样做并且不是最好的解决方法)是将您的文件放在 Python 路径中已经存在的文件夹中。在这种情况下,它可能是lib
文件夹。对我来说,运行 Python 3.8 的路径是/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8
,对于任何 Python 3.x 版本,这将是相同的,但版本被替换了。Python 2.x 有时有不同的位置。
推荐阅读
- c# - 如何制作一个与加速和减速统一的自由飞行相机脚本?
- amazon-s3 - AWS Kinesis Firehose 到 Lambda,Lambda 到 S3 使用 java
- javascript - 哈希锚链接无法找到/定位 ID DOM 元素目标(在某些情况下)
- regex - 如何使用 RewriteCond 匹配特定 URL
- javascript - 如何防止出现蓝色突出显示
- c - 如何搜索 for 循环 C 中的每个元素
- java - 获取复合键的 generatedkey()
- cocos2d-x - 为 windows 64 位编译 cocos2dx 游戏
- ios - 我在 Testflight 中看不到我在 x-code 测试中构建的分支
- makefile - 删除 Makefile 中的重复:目标文件在 Phony 变量 `all` 下写入一次,然后再次作为配方目标