简体   繁体   中英

Integrating HTML+JS for host system display into Python script running in Docker container (linux subsystem)

I have a basic HTML page with some javascript that I want to use to display the results of a python script at repeated steps during its execution, as well as waiting for some user trigger to continue. The webpage consists of an HTML file, a main javascript file, a secondary javascript file generated by the script containing the custom data, and references to external javascript dependencies (eg "https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js".

To complicate things, the python script is running in a Docker container (Linux subsystem) via Visual Studio Code, so some operations like automatically opening an HTML file on the host system are difficult to accomplish (and there also seems to be a problem, with firefox at least, preventing opening local HTML files that reference other local files - see ).

My initial plan was to, at each display step in the script, start a simple python http server, serve the page on localhost by piping it through a forwarded port see , wait for the user to open the localhost in their host browser, then once the page has been loaded close the server and continue with the script. I'm sure there is some fancier way of keeping the server up the entire time using threading and passing the updated data but web dev isn't really my field and this isn't exactly production code either so I felt this approach made more sense.

So assuming that this is a valid approach (and if there is a better one, I am more than happy to hear it), here's my best attempt at it (following this guide):

import http.server # Our http server handler for http requests
import socketserver # Establish the TCP Socket connections
from time import sleep  # To sleep before shutting down server

PORT = 8000
count = 0

class requestHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        global count
        if self.path == "/":
            self.path == ".server/"
        count += 1
        return http.server.SimpleHTTPRequestHandler.do_GET(self)

# Prevent errors when restarting server and address (port) is still in use
socketserver.TCPServer.allow_reuse_address = True

handler = requestHandler

# Start server
with socketserver.TCPServer(("", PORT), handler) as httpd:
    # Checking for request count, 3 expected:
    #   "GET /.server/ HTTP/1.1"
    #   "GET /.server/dots.js HTTP/1.1"
    #   "GET /.server/script.js HTTP/1.1"
    #  so accept 3 requests and end

    while count < 3:
        httpd.handle_request()

This is called from the main script with exec(open().read()).

Currently I get the error "NameError: name 'http' is not defined" in line 23. Weirdly, I'm sure a couple of days ago this was working fine, and I've just come back to it so I wouldn't have thought anything had changed. I've also tried a bunch of simple http.server examples with and without custom handlers, with and without the with...as block, with various errors from "Loading failed for the with source "http://localhost:8000/.server/dots.js" (in the browser F12 console) to failures to load the entire./server directory and others. So I'm pretty much out of ideas at this point and am hoping one of you nice people can help me out.

PS Sorry for the long post, had to get it all out.

can you try to change:

with socketserver.TCPServer(("", PORT), handler) as httpd:

to:

with socketserver.TCPServer(("0.0.0.0", PORT), handler) as httpd:

so your application may need to listen on all interfaces?

EDIT :

as I wrote in the comments, using simple webserver such as flask might be easier for you, only to serve static files. Here is the first post I found: https://code-maven.com/flask-serve-static-files

Okay so I seem to have found a rather inelegant but at least functional solution for the time being. For anyone reading in the future here is the server.py file:

import http.server
import socketserver

PORT = 8000

socketserver.TCPServer.allow_reuse_address = True

httpd = socketserver.TCPServer(("", PORT), http.server.SimpleHTTPRequestHandler)
for i in range(3):
    httpd.handle_request()

I'll leave the question up for a little longer in case something better comes along, otherwise I'll mark this as a solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM