<strong>Sage</strong> Developer’s <strong>Guide</strong>, Release 6.1.14.3.3 Attaching or Loading .spyx FilesThe easiest way to try out Cython without having to learn anything about distutils, etc., is to create a file with theextension spyx, which stands for “<strong>Sage</strong> Pyrex”:1. Create a file power2.spyx.2. Put the following in it:def is2pow(n):while n != 0 and n%2 == 0:n = n >> 1return n == 13. Start the <strong>Sage</strong> command line interpreter and load the spyx file (this will fail if you do not have a C compilerinstalled).sage: load "power2.spyx"Compiling power2.spyx...sage: is2pow(12)FalseNote that you can change power2.spyx, then load it again and it will be recompiled on the fly. You can also attachpower2.spyx so it is reloaded whenever you make changes:sage: attach "power2.spyx"Cython is used for its speed. Here is a timed test on a 2.6 GHz Opteron:sage: %time [n for n in range(10^5) if is2pow(n)][1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 sWall time: 0.60 sNow, the code in the file power2.spyx is valid Python, and if we copy this to a file powerslow.py and load that,we get the following:sage: load "powerslow.py"sage: %time [n for n in range(10^5) if is2pow(n)][1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]CPU times: user 1.01 s, sys: 0.04 s, total: 1.05 sWall time: 1.05 sBy the way, we could gain even a little more speed with the Cython version with a type declaration, by changing defis2pow(n): to def is2pow(unsigned int n):.4.3.4 Interrupt and Signal HandlingWhen writing Cython code for <strong>Sage</strong>, special care must be taken to ensure the code can be interrupted with CTRL-C.Since Cython optimizes for speed, Cython normally does not check for interrupts. For example, code like the followingcannot be interrupted:sage: cython(’while True: pass’)# DON’T DO THISWhile this is running, pressing CTRL-C has no effect. The only way out is to kill the <strong>Sage</strong> process. On certainsystems, you can still quit <strong>Sage</strong> by typing CTRL-\ (sending a Quit signal) instead of CTRL-C.42 Chapter 4. Writing Code for <strong>Sage</strong>
<strong>Sage</strong> Developer’s <strong>Guide</strong>, Release 6.1.1Using sig_on() and sig_off()To enable interrupt handling, use the sig_on() and sig_off() functions. You should put sig_on() before andsig_off() after any Cython code which could potentially take a long time. These two must always be called inpairs, i.e. every sig_on() must be matched by a closing sig_off().In practice your function will probably look like:def sig_example():# (some harmless initialization)sig_on()# (a long computation here, potentially calling a C library)sig_off()# (some harmless post-processing)return somethingYou can put sig_on() and sig_off() in all kinds of Cython functions: def, cdef or cpdef. You cannot putthem in pure Python code (i.e. files with extension .py).It is possible to put sig_on() and sig_off() in different functions, provided that sig_off() is called beforethe function which calls sig_on() returns. The following code is invalid:# INVALID code because we return from function foo()# without calling sig_off() first.cdef foo():sig_on()def f1():foo()sig_off()But the following is valid since you cannot call foo interactively:cdef int foo():sig_off()return 2+2def f1():sig_on()return foo()For clarity however, it is best to avoid this. One good example where the above makes sense is the new_gen()function in The PARI C Library Interface.A common mistake is to put sig_off() towards the end of a function (before the return) when the function hasmultiple return statements. So make sure there is a sig_off() before every return (and also before everyraise).Warning: The code inside sig_on() should be pure C or Cython code. If you call Python code, an interrupt islikely to mess up Python.Also, when an interrupt occurs inside sig_on(), code execution immediately stops without cleaning up. Forexample, any memory allocated inside sig_on() is lost. See Advanced Functions for ways to deal with this.When the user presses CTRL-C inside sig_on(), execution will jump back to sig_on() (the first one if there is astack) and sig_on() will raise KeyboardInterrupt. These can be handled just like other Python exceptions:def catch_interrupts():try:sig_on() # This MUST be inside the try4.3. Coding in Cython 43
- Page 1: Sage Developer’s GuideRelease 6.1
- Page 4 and 5: 7 Indices and tables 129Bibliograph
- Page 6 and 7: Sage Developer’s Guide, Release 6
- Page 8 and 9: Sage Developer’s Guide, Release 6
- Page 10 and 11: Sage Developer’s Guide, Release 6
- Page 12 and 13: Sage Developer’s Guide, Release 6
- Page 14 and 15: Sage Developer’s Guide, Release 6
- Page 16 and 17: Sage Developer’s Guide, Release 6
- Page 18 and 19: Sage Developer’s Guide, Release 6
- Page 20 and 21: Sage Developer’s Guide, Release 6
- Page 22 and 23: Sage Developer’s Guide, Release 6
- Page 24 and 25: Sage Developer’s Guide, Release 6
- Page 26 and 27: Sage Developer’s Guide, Release 6
- Page 28 and 29: Sage Developer’s Guide, Release 6
- Page 30 and 31: Sage Developer’s Guide, Release 6
- Page 32 and 33: Sage Developer’s Guide, Release 6
- Page 34 and 35: Sage Developer’s Guide, Release 6
- Page 36 and 37: Sage Developer’s Guide, Release 6
- Page 38 and 39: Sage Developer’s Guide, Release 6
- Page 40 and 41: Sage Developer’s Guide, Release 6
- Page 42 and 43: Sage Developer’s Guide, Release 6
- Page 44 and 45: Sage Developer’s Guide, Release 6
- Page 48 and 49: Sage Developer’s Guide, Release 6
- Page 50 and 51: Sage Developer’s Guide, Release 6
- Page 52 and 53: Sage Developer’s Guide, Release 6
- Page 54 and 55: Sage Developer’s Guide, Release 6
- Page 56 and 57: Sage Developer’s Guide, Release 6
- Page 58 and 59: Sage Developer’s Guide, Release 6
- Page 60 and 61: Sage Developer’s Guide, Release 6
- Page 62 and 63: Sage Developer’s Guide, Release 6
- Page 64 and 65: Sage Developer’s Guide, Release 6
- Page 66 and 67: Sage Developer’s Guide, Release 6
- Page 68 and 69: Sage Developer’s Guide, Release 6
- Page 70 and 71: Sage Developer’s Guide, Release 6
- Page 72 and 73: Sage Developer’s Guide, Release 6
- Page 74 and 75: Sage Developer’s Guide, Release 6
- Page 76 and 77: Sage Developer’s Guide, Release 6
- Page 78 and 79: Sage Developer’s Guide, Release 6
- Page 80 and 81: Sage Developer’s Guide, Release 6
- Page 82 and 83: Sage Developer’s Guide, Release 6
- Page 84 and 85: Sage Developer’s Guide, Release 6
- Page 86 and 87: Sage Developer’s Guide, Release 6
- Page 88 and 89: Sage Developer’s Guide, Release 6
- Page 90 and 91: Sage Developer’s Guide, Release 6
- Page 92 and 93: Sage Developer’s Guide, Release 6
- Page 94 and 95: Sage Developer’s Guide, Release 6
- Page 96 and 97:
Sage Developer’s Guide, Release 6
- Page 98 and 99:
Sage Developer’s Guide, Release 6
- Page 100 and 101:
Sage Developer’s Guide, Release 6
- Page 102 and 103:
Sage Developer’s Guide, Release 6
- Page 104 and 105:
Sage Developer’s Guide, Release 6
- Page 106 and 107:
Sage Developer’s Guide, Release 6
- Page 108 and 109:
Sage Developer’s Guide, Release 6
- Page 110 and 111:
Sage Developer’s Guide, Release 6
- Page 112 and 113:
Sage Developer’s Guide, Release 6
- Page 114 and 115:
Sage Developer’s Guide, Release 6
- Page 116 and 117:
Sage Developer’s Guide, Release 6
- Page 118 and 119:
Sage Developer’s Guide, Release 6
- Page 120 and 121:
Sage Developer’s Guide, Release 6
- Page 122 and 123:
Sage Developer’s Guide, Release 6
- Page 124 and 125:
Sage Developer’s Guide, Release 6
- Page 126 and 127:
Sage Developer’s Guide, Release 6
- Page 128 and 129:
Sage Developer’s Guide, Release 6
- Page 130 and 131:
Sage Developer’s Guide, Release 6
- Page 132 and 133:
Sage Developer’s Guide, Release 6
- Page 134 and 135:
Sage Developer’s Guide, Release 6
- Page 136 and 137:
Sage Developer’s Guide, Release 6