commit a7ec700c1b366b5cd96ba894916ad0a6e6fa0b4c Author: Damian Johnson atagar@torproject.org Date: Thu Aug 29 10:13:48 2013 -0700
Explaining python's 'with' keyword
We've had a couple stem newcomers that saw the 'with' keyword in our examples then misused it in their scripts. Adding a little tutorial on the keyword and the common mistake they've been making. --- docs/faq.rst | 62 ++++++++++++++++++++++++ docs/tutorials/the_little_relay_that_could.rst | 4 +- 2 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/docs/faq.rst b/docs/faq.rst index f1edeee..76e7c91 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -14,6 +14,7 @@ Frequently Asked Questions * :ref:`how_do_i_request_a_new_identity_from_tor` * :ref:`how_do_i_get_information_about_my_exits` * :ref:`how_do_i_reload_my_torrc` + * :ref:`what_is_that_with_keyword_i_keep_seeing_in_the_tutorials`
* **Development**
@@ -180,6 +181,67 @@ Tor is configured through its `torrc <https://www.torproject.org/docs/faq.html.e controller.authenticate() controller.signal(Signal.SIGHUP)
+.. _what_is_that_with_keyword_i_keep_seeing_in_the_tutorials: + +What is that 'with' keyword I keep seeing in the tutorials? +----------------------------------------------------------- + +Python's '**with**' keyword is shorthand for a try/finally block. With a :class:`~stem.control.Controller` the following... + +:: + + with Controller.from_port(port = 9051) as controller: + # do my stuff + +... is equivialnt to... + +:: + + controller = Controller.from_port(port = 9051) + + try: + # do my stuff + finally: + controller.close() + +This helps to make sure that regardless of if your code raises an exception or not the control connection will be cleaned up afterward. Note that this means that if you leave the 'with' scope your :class:`~stem.control.Controller` will be closed. For instance... + +:: + + class BandwidthReporter(object): + def __init__(self, controller): + self.controller = controller + + def print_bandwidth(self): + bytes_read = self.controller.get_info("traffic/read") + bytes_written = self.controller.get_info("traffic/written") + + print "My Tor relay has read %s bytes and written %s." % (bytes_read, bytes_written) + + if __name__ == '__main__': + with Controller.from_port(port = 9051) as controller: + reporter = BandwidthReporter(controller) + + # The following line is broken because the 'controller' we initialised + # above was disconnected once we left the 'with' scope. + + reporter.print_bandwidth() + +To fix this we could either move the print_bandwidth() call into the 'with' scope, or simply avoid using 'with' all together... + +:: + + if __name__ == '__main__': + controller = Controller.from_port(port = 9051) + + try: + reporter = BandwidthReporter(controller) + reporter.print_bandwidth() + finally: + controller.close() + +For more information about the 'with' keyword see `here http://effbot.org/zone/python-with-statement.htm`_. + Development ===========
diff --git a/docs/tutorials/the_little_relay_that_could.rst b/docs/tutorials/the_little_relay_that_could.rst index 74fbe46..c30ae55 100644 --- a/docs/tutorials/the_little_relay_that_could.rst +++ b/docs/tutorials/the_little_relay_that_could.rst @@ -42,7 +42,9 @@ the following configuration options...
When you change your torrc you'll need to either restart Tor is issue a SIGHUP for the new settings to take effect. Now let's write a script that tells us how -many bytes Tor has sent and received since it started... +many bytes Tor has sent and received since it started. If you're unfamiliar +with the '**with**' keyword then see `here +<../faq.html#what-is-that-with-keyword-i-keep-seeing-in-the-tutorials>`_...
::