Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You can assume it will be magically patched if all of the following are true.</p> <ul> <li>You're sure of the I/O is built on top of standard Python <code>socket</code>s or other things that <code>eventlet</code>/<code>gevent</code> monkeypatches. No files, no native (C) socket objects, etc.</li> <li>You pass <code>aggressive=True</code> to <code>patch_all</code> (or <code>patch_select</code>), or you're sure the library doesn't use <code>select</code> or anything similar.</li> <li>The driver doesn't use any (implicit) internal threads. (If the driver <em>does</em> use threads internally, <code>patch_thread</code> <em>may</em> work, but it may not.)</li> </ul> <p>If you're not sure, it's pretty easy to test—probably easier than reading through the code and trying to work it out. Have one greenlet that just does something like this:</p> <pre><code>while True: print("running") gevent.sleep(0.1) </code></pre> <p>Then have another that runs a slow query against the database. If it's monkeypatched, the looping greenlet will keep printing "running" 10 times/second; if not, the looping greenlet will not get to run while the program is blocked on the query.</p> <p>So, what do you do if your driver blocks? </p> <p>The easiest solution is to use a truly concurrent threadpool for DB queries. The idea is that you fire off each query (or batch) as a threadpool job and greenlet-block your <code>gevent</code> on the completion of that job. (For really simple cases, where you don't need many concurrent queries, you can just spawn a <code>threading.Thread</code> for each one instead, but usually you can't get away with that.)</p> <p>If the driver does significant CPU work (e.g., you're using something that runs an in-process cache, or even an entire in-process DBMS like sqlite), you want this threadpool to actually be implemented on top of processes, because otherwise the GIL may prevent your <code>greenlets</code> from running. Otherwise (especially if you care about Windows), you probably want to use OS threads. (However, this means you can't <code>patch_threads()</code>; if you need to do that, use processes.)</p> <p>If you're using <code>eventlet</code>, and you want to use threads, there's a built-in simple solution called <a href="http://eventlet.net/doc/threading.html#tpool-simple-thread-pool" rel="noreferrer"><code>tpool</code></a> that may be sufficient. If you're using <code>gevent</code>, or you need to use processes, this won't work. Unfortunately, blocking a greenlet (without blocking the whole event loop) on a real threading object is a bit different between <code>eventlet</code> and <code>gevent</code>, and not documented very well, but the <code>tpool</code> source should give you the idea. Beyond that part, the rest is just using <a href="http://docs.python.org/3/library/concurrent.futures.html" rel="noreferrer"><code>concurrent.futures</code></a> (see <a href="http://pypi.python.org/pypi/futures/2.1.3" rel="noreferrer"><code>futures</code></a> on pypi if you need this in 2.x or 3.1) to execute the tasks on a <code>ThreadPoolExecutor</code> or <code>ProcessPoolExecutor</code>. (Or, if you prefer, you can go right to <code>threading</code> or <code>multiprocessing</code> instead of using <code>futures</code>.)</p> <hr> <blockquote> <p>Can you explain why I should use OS threads on Windows?</p> </blockquote> <p>The quick summary is: If you stick to threads, you can pretty much just write cross-platform code, but if you go to processes, you're effectively writing code for two different platforms.</p> <p>First, read the <a href="http://docs.python.org/3/library/multiprocessing.html#programming-guidelines" rel="noreferrer">Programming guidelines</a> for the <code>multiprocessing</code> module (both the "All platforms" section and the "Windows" section). Fortunately, a DB wrapper shouldn't run into most of this. You only need to deal with processes via the <code>ProcessPoolExecutor</code>. And, whether you wrap things up at the cursor-op level or the query level, all your arguments and return values are going to be simple types that can be pickled. Still, it's something you have to be careful about, which otherwise wouldn't be an issue.</p> <p>Meanwhile, Windows has very low overhead for its intra-process synchronization objects, but very high overhead for its inter-process ones. (It also has very fast thread creation and very slow process creation, but that's not important if you're using a pool.) So, how do you deal with that? I had a lot of fun creating OS threads to wait on the cross-process sync objects and signal the greenlets, but your definition of fun may vary.</p> <p>Finally, <code>tpool</code> can be adapted trivially to a <code>ppool</code> for Unix, but it takes more work on Windows (and you'll have to understand Windows to do that work).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload