Python(3.3)Web服务器脚本,有一个有趣的错误
我有一个小的pythonwebserver脚本来托管我自己的网站,包括请求处理和错误返回。这个脚本在我的电脑上运行得很好,但当我在我的raspberry Pi上尝试它时,它不会每3分钟重启一次(服务器会在15分钟后崩溃,所以每3分钟重启一次似乎很好) 所以我重写了我的服务器脚本,它会检查一些东西,比如它是第一次启动还是重新启动。我给你看看代码Python(3.3)Web服务器脚本,有一个有趣的错误,python,multithreading,http,raspberry-pi,Python,Multithreading,Http,Raspberry Pi,我有一个小的pythonwebserver脚本来托管我自己的网站,包括请求处理和错误返回。这个脚本在我的电脑上运行得很好,但当我在我的raspberry Pi上尝试它时,它不会每3分钟重启一次(服务器会在15分钟后崩溃,所以每3分钟重启一次似乎很好) 所以我重写了我的服务器脚本,它会检查一些东西,比如它是第一次启动还是重新启动。我给你看看代码 #Handler class above here ... ... class Server: global server_class, ser
#Handler class above here
...
...
class Server:
global server_class, server_adress, httpd
server_class = HTTPServer
server_adress = ('localhost', 8080)
httpd = server_class(server_adress, Handler)
def __init__(self):
self.status = False
self.process()
def process(self):
print(self.status)
process = threading.Timer(10, self.process)
process.start()
if self.status == True:
httpd.socket.close()
self.main()
if self.status == False:
self.main()
def main(self):
try:
if self.status == False:
print("Server online!")
self.status = True
httpd.serve_forever()
if self.status == True:
print("Server restarted!")
httpd.serve_forever()
except KeyboardInterrupt:
print("Server shutting down...")
httpd.socket.close()
if __name__ == "__main__":
instance = Server()
在运行10秒钟后(运行正常后,我可以在http://localhost:8080/index.html
),它将继续每隔10秒出现以下错误:
File "C:\Users\myname\Dropbox\Python\Webserver\html\server.py", line 187, in main httpd.serve_forever()
File "C:\Python33\lib\socketserver.py", line 237, in serve_forever poll_interval)
File "C:\Python33\lib\socketserver.py", line 155, in _eintr_retry return func(*args)
ValueError: file descriptor cannot be a negative integer (-1)
基本上,我该如何解决这个问题?我可以使用一个带线程计时器的简单函数来重新启动运行服务器的函数,但在我的Raspberry Pi上不起作用,但在我的windows上起作用
编辑:
我还应该注意,第一次启动脚本时,我可以访问网站,而且速度很快。10秒后(服务器重新启动后),我可以访问它,但速度非常慢。再过10秒钟,我就无法访问我的网站了。您遇到的问题是因为您直接访问了服务器的底层套接字。关闭插座就像拔掉网络连接一样有效。位于套接字顶部的实际服务器仍然不知道套接字已关闭,并尝试继续提供服务。由于套接字已关闭,因此不再有可用的文件描述符(这是您得到的错误) 因此,与其切断服务器的连接,不如告诉服务器实际正常关闭。这允许它完成任何正在进行的连接,并安全地释放它在后台可能做的一切。您可以使用该方法来实现这一点。执行该命令将在内部告诉服务器记住在下次循环发生时关闭 如果我没记错的话,
永远服务
是一种阻塞方法,这意味着它在执行时不会继续。因此,让服务器自行重启的最简单方法是使用单个主线程执行以下操作:
while True:
httpd.serve_forever()
因此,无论何时服务器出于何种原因停止,它都会立即重新启动。当然,现在您可以添加一些状态变量(而不是
True
),它允许您实际关闭服务器。例如,在KeyboardInterrupt
catch的主体中,首先将该变量设置为False
,然后使用httpd.shutdown()
关闭服务器,这些全局变量的原因是什么?您应该改为将它们作为服务器
类型的实例变量。@poke这是我尝试过的。此外,我发现self.status
和httpd
变量都存在巨大的并发问题。两者都不是线程安全的,但您一直从不同的线程(在main
和process
中)访问它们。@poke它们怎么不是线程安全的?我应该使用线程以外的其他东西来重新启动吗?