Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 928213
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T19:58:29+00:00 2026-05-15T19:58:29+00:00

This is an annoying problem I am having with Twisted.web. Basically, I have a

  • 0

This is an annoying problem I am having with Twisted.web. Basically, I have a class that inherits from twisted.web.resource.Resource and adds some default stuff to Mako templates:

from twisted.web.resource import Resource
from mako.lookup import TemplateLookup
from project.session import SessionData
from project.security import make_nonce


class Page(Resource):

    template = ""

    def display(self, request, **kwargs):
        session = SessionData(request.getSession())

        if self.template:
            templates = TemplateLookup(directories=['templates'])
            template = templates.get_template(self.template)
            return template.render(user=session.user,
                                   info=session.info,
                                   current_path=request.path,
                                   nonce=make_nonce(session),
                                   **kwargs)
        else:
            return ""

Then, and I have narrowed the problem down to this small class (which I tested), I write a resource which inherits from Page:

class Test(pages.Page):
    def render_GET(self, request):
        return "<form method='post'><input type='submit'></form>"
    def render_POST(self, request):
        request.redirect("/test")
        request.finish()

I’d like to note that, in every other case, if request.finish() isn’t the last line in a function, then I return immediately after it.

Anyways, I add this class to the site at /test and when I navigate there, I get a submit button. I click the submit button, and in the console I get:

C:\Python26\lib\site-packages\twisted\web\server.py:200: UserWarning: Warning! request.finish called twice.
  self.finish()

But, I get this ONLY the first time I submit the page. Every other time, it’s fine. I would just ignore this, but it’s been nagging at me, and I can’t for the life of me figure out why it’s doing this at all, and why only the first time the page is submitted. I can’t seem to find anything online, and even dropping print statements and tracebacks in the request.finish() code didn’t reveal anything.

edit

This morning I tried adding a second request.finish() line to the resource, and it still only gave me the error one time. I suppose it will only warn about it in a resource once — maybe per run of the program, or per session, I’m not sure. In any case, I changed it to:

class Test(pages.Page):
    def render_GET(self, request):
        return "<form method='post'><input type='submit'></form>"
    def render_POST(self, request):
        request.redirect("/test")
        request.finish()
        request.finish()

and just got two messages, one time. I still have no idea why I can’t redirect the request without it saying I finished it twice (because I can’t redirect without request.finish()).

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T19:58:29+00:00Added an answer on May 15, 2026 at 7:58 pm

    Short Answer


    It has to be:

    request.redirect("/test")
    request.finish()
    return twisted.web.server.NOT_DONE_YET
    

    Long Answer


    I decided to go sifting through some Twisted source code. I first added a traceback to the area that prints the error if request.finish() is called twice:

    def finish(self):
        import traceback #here
        """
        Indicate that all response data has been written to this L{Request}.
        """
        if self._disconnected:
            raise RuntimeError(
                "Request.finish called on a request after its connection was lost; "
                "use Request.notifyFinish to keep track of this.")
        if self.finished:
            warnings.warn("Warning! request.finish called twice.", stacklevel=2)
            traceback.print_stack() #here
            return
        #....
    
    ...
      File "C:\Python26\lib\site-packages\twisted\web\server.py", line 200, in render
        self.finish()
      File "C:\Python26\lib\site-packages\twisted\web\http.py", line 904, in finish
        traceback.print_stack()
    

    I went in and checked out render in twisted.web.server and found this:

        if body == NOT_DONE_YET:
            return
        if type(body) is not types.StringType:
            body = resource.ErrorPage(
                http.INTERNAL_SERVER_ERROR,
                "Request did not return a string",
                "Request: " + html.PRE(reflect.safe_repr(self)) + "<br />" +
                "Resource: " + html.PRE(reflect.safe_repr(resrc)) + "<br />" +
                "Value: " + html.PRE(reflect.safe_repr(body))).render(self)
    
        if self.method == "HEAD":
            if len(body) > 0:
                # This is a Bad Thing (RFC 2616, 9.4)
                log.msg("Warning: HEAD request %s for resource %s is"
                        " returning a message body."
                        "  I think I'll eat it."
                        % (self, resrc))
                self.setHeader('content-length', str(len(body)))
            self.write('')
        else:
            self.setHeader('content-length', str(len(body)))
            self.write(body)
        self.finish()
    

    body is the result of rendering a resource, so once body is populated, in the example case given in my question, finish has already been called on this request object (since self is passed from this method to the resource’s render method).

    From looking at this code it becomes apparent that by returning NOT_DONE_YET I would avoid the warning.

    I could have also changed the last line of that method to:

    if not self.finished:
        self.finish()
    

    but, in the interest of not modifying the library, the short answer is:

    after calling request.redirect() you must call request.finish() and then return twisted.web.server.NOT_DONE_YET

    More


    I found some documentation about this. It isn’t related to redirecting a request, but instead rendering a resource, using request.write(). It says to call request.finish() and then return NOT_DONE_YET. From looking at the code in render() I can see why that is the case.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.