Download Python/PyTango/IPython in a Nutshell

Document related concepts
no text concepts found
Transcript
Python/PyTango/IPython in a Nutshell
Version March 24, 2017
by
Thorsten Kracht
Contents
1
Introduction
2
Miscellaneous
2.0.1 Hello world . . . . . . . . . . . . . . . . . . . . . . .
2.0.2 Invoking Python . . . . . . . . . . . . . . . . . . . . .
2.0.3 Command line arguments . . . . . . . . . . . . . . . .
2.0.4 Executing a string of commands from the command line
2.0.5 The name of the executing script . . . . . . . . . . . .
2.0.6 Indentation using XEmacs . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
7
7
8
8
Variables
3.1 Type . . . . . . . . . . . . . . . .
3.2 Scope, local, global, builtin . . . .
3.3 Numbers . . . . . . . . . . . . . .
3.3.1 Operators . . . . . . . . . .
3.4 Strings . . . . . . . . . . . . . . .
3.4.1 Formatting . . . . . . . . .
3.4.2 Splitting strings . . . . . .
3.4.3 Regular expressions . . . .
3.5 Lists . . . . . . . . . . . . . . . . .
3.5.1 list comprehension . . . . .
3.5.2 copy a list . . . . . . . . . .
3.5.3 join(), split() . . . . . . . .
3.5.4 Searching . . . . . . . . . .
3.5.5 Sorting . . . . . . . . . . .
3.5.6 Loops over a list in pairs . .
3.5.7 zip (parsing vmstat output)
3.6 Dictionaries . . . . . . . . . . . . .
3.6.1 Iterating over a dictionary .
3.6.2 copy a dictionary . . . . . .
3.7 Tuples . . . . . . . . . . . . . . . .
3.7.1 Tuples to lists . . . . . . . .
3.8 Sets . . . . . . . . . . . . . . . . .
3.9 Special global variables . . . . . .
3
4
5
6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
9
9
10
10
11
11
11
13
13
14
14
15
15
15
15
16
16
17
17
17
17
18
Modules and Packages
4.1 Some Statements on Modules and Packages . . . . . . . . .
4.2 Importing modules . . . . . . . . . . . . . . . . . . . . . .
4.3 Demo: Importing modules from packages and sub-packages
. . . . . . . . . . . .
4.4 The toplevel name space, builtins
4.5 Injecting a variable into the name space of a module . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
19
20
21
22
22
Classes
5.1 General remarks . . . . . . .
5.2 Class definition . . . . . . . .
5.3 Multiple constructors . . . . .
5.4 Inspect the members of a class
5.5 The class of an instance . . .
5.6 Import classes from a module
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
23
23
24
24
24
24
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5.7
5.8
5.9
5.10
5.11
5.12
5.13
5.14
6
7
8
9
Inheritance . . . . . . . . .
Exceptions are classes . . .
Default attributes handler . .
delattr(), getattr(), setattr() .
The @staticmethod decorator
The @classmethod decorator
The property function . . . .
The @property decorator . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24
25
25
25
26
26
26
27
Control Statements
6.1 If . . . . . . . . . . . . . . . . .
6.1.1 Operators . . . . . . . .
6.1.2 Truth . . . . . . . . . .
6.2 Loops . . . . . . . . . . . . . .
6.2.1 Break an outer loop . . .
6.2.2 Loop over a list in pairs .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
28
28
28
29
29
30
31
Input/Output
7.1 Print . . . . . . . . . . . . . . . . .
7.2 Internal write . . . . . . . . . . . .
7.3 sys.stdin.readline() . . . . . . . . .
7.4 sys.stdout.write . . . . . . . . . . .
7.5 File I/O . . . . . . . . . . . . . . .
7.5.1 Reading dbHosts from a file
7.6 touch . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
32
32
32
32
33
33
33
34
Built-in Functions
8.1 chr(), ord() . . . . . . . .
8.2 dir() . . . . . . . . . . . .
8.3 exec() . . . . . . . . . . .
8.4 eval() . . . . . . . . . . .
8.5 delattr(), getattr(), setattr()
8.6 globals() . . . . . . . . .
8.7 hasattr() . . . . . . . . . .
8.8 id() . . . . . . . . . . . .
8.9 int(), float(), str() . . . . .
8.10 int(), round() . . . . . . .
8.11 issubclass() . . . . . . . .
8.12 iter() . . . . . . . . . . .
8.13 lambda (closure) . . . . .
8.14 map, filter . . . . . . . . .
8.15 locals() . . . . . . . . . .
8.16 map() . . . . . . . . . . .
8.17 range() . . . . . . . . . .
8.18 sort(), sorted() . . . . . .
8.19 type(), isinstance() . . . .
8.20 yield . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35
35
35
35
36
36
36
36
36
37
37
37
37
38
38
38
38
39
39
39
39
Useful modules
9.1 argparse . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2 commands . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2.1 getoutput(), capturing shell command output, hostname
9.3 glob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.4 inspect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.5 math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.5.1 math.fabs . . . . . . . . . . . . . . . . . . . . . . . .
9.5.2 math.radians, math.degrees . . . . . . . . . . . . . . .
9.5.3 math.sin . . . . . . . . . . . . . . . . . . . . . . . . .
9.6 matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.6.1 General remarks . . . . . . . . . . . . . . . . . . . .
9.6.2 Simple vs. OO API . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
40
40
41
41
41
42
42
42
42
42
42
42
43
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9.7
9.8
9.9
9.10
9.11
9.12
9.13
9.14
9.15
9.16
9.6.3 Blocking mode . . . . . . . . . . . . . . . . . . . . . . . . .
9.6.4 Non-blocking, from IPython, debugging . . . . . . . . . . . .
9.6.5 Create a png, useful for web applications . . . . . . . . . . .
9.6.6 Subplots . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.6.7 Plotting from the MacroServer . . . . . . . . . . . . . . . . .
9.6.8 Scan simulation . . . . . . . . . . . . . . . . . . . . . . . . .
9.6.9 fioPlotter . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pyqtgraph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.7.1 General remarks . . . . . . . . . . . . . . . . . . . . . . . .
9.7.2 Scan simulation . . . . . . . . . . . . . . . . . . . . . . . . .
9.7.3 fioPlotter . . . . . . . . . . . . . . . . . . . . . . . . . . . .
numpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.8.1 array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.8.2 ndarray, slicing . . . . . . . . . . . . . . . . . . . . . . . . .
9.8.3 ndarray, ellipsis [...] . . . . . . . . . . . . . . . . . . . . . . .
9.8.4 arange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.8.5 linspace . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.8.6 ones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.8.7 zeros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
os . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.1 os.access() . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.2 os.chdir() . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.3 os.getcwd() . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.4 os.getenv() . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.5 os.getpid() . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.6 os.isatty() . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.7 os.kill() . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.8 os.listdir() (all files in a directory) . . . . . . . . . . . . . . .
9.9.9 os.mkdir() . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.10 os.path.basename() . . . . . . . . . . . . . . . . . . . . . . .
9.9.11 os.path.dirname() . . . . . . . . . . . . . . . . . . . . . . . .
9.9.12 os.path.exists() . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.13 os.path.getsize() . . . . . . . . . . . . . . . . . . . . . . . .
9.9.14 os.path.isdir() . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.15 os.path.isExecutable() . . . . . . . . . . . . . . . . . . . . .
9.9.16 os.path.isfile() . . . . . . . . . . . . . . . . . . . . . . . . . .
9.9.17 os.popen(), capturing shell command output . . . . . . . . . .
9.9.18 os.popen(), ps ax, MacroServer/haspp09 . . . . . . . . . . . .
9.9.19 os.remove(), os.rmdir() . . . . . . . . . . . . . . . . . . . . .
9.9.20 os.rename() (mv) . . . . . . . . . . . . . . . . . . . . . . . .
9.9.21 os.system(), execute a shell command, sensing the return-state
9.9.22 os.system(), calling ping . . . . . . . . . . . . . . . . . . . .
9.9.23 os.walk(), traverse dirs and sub-dirs . . . . . . . . . . . . . .
platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pprint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
shutil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.13.1 copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.14.1 signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.15.1 gethostname() . . . . . . . . . . . . . . . . . . . . . . . . . .
9.15.2 gethostbyaddr() . . . . . . . . . . . . . . . . . . . . . . . . .
string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.16.1 atoi() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.16.2 find() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.16.3 lower(), upper() . . . . . . . . . . . . . . . . . . . . . . . . .
9.16.4 partition, rpartition() . . . . . . . . . . . . . . . . . . . . . .
9.16.5 replace() . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.16.6 split(), join() . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
44
45
46
46
48
52
53
58
58
58
59
64
64
64
64
67
67
67
67
67
67
68
68
68
68
68
68
69
69
69
69
69
70
70
70
70
70
70
71
71
71
71
72
72
72
72
72
72
73
73
73
73
73
73
73
73
73
74
74
74
9.16.7 strip(), strip(), lstrip() . . . . . . . .
9.17 subprocess, capturing shell command output .
9.18 sys . . . . . . . . . . . . . . . . . . . . . . .
9.18.1 argv . . . . . . . . . . . . . . . . . .
9.18.2 exitfunc . . . . . . . . . . . . . . . .
9.18.3 getframe(), traceback . . . . . . . . .
9.18.4 path (PYTHONPATH) . . . . . . . .
9.18.5 stdin.readline() . . . . . . . . . . . .
9.18.6 threads . . . . . . . . . . . . . . . .
9.19 time . . . . . . . . . . . . . . . . . . . . . .
9.19.1 localtime(), date and time . . . . . .
9.19.2 strftime(), formatted date-time string .
9.19.3 doty(), day-of-the-year . . . . . . . .
9.19.4 sleep(), usleep() . . . . . . . . . . . .
9.19.5 time() . . . . . . . . . . . . . . . . .
9.20 traceback . . . . . . . . . . . . . . . . . . .
9.20.1 traceback.print tb . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
74
74
75
75
75
75
75
76
76
77
77
77
77
77
77
78
78
10 Functions
10.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.2 Argument passing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.3 Returning a list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
79
79
81
11 Exceptions
11.1 Catching exceptions . .
11.2 Traceback Information
11.3 Raising an exception .
11.4 User defined exception
11.5 Tango exceptions . . .
11.6 AttributeError . . . . .
11.7 Catching a time-out . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
82
82
82
83
83
83
84
84
12 IPython
12.1 General remarks . . . . . . . . . . . . . . . . . .
12.2 Configuration . . . . . . . . . . . . . . . . . . . .
12.3 Magic . . . . . . . . . . . . . . . . . . . . . . . .
12.3.1 Defining a magic command . . . . . . . .
12.4 Execute a list of magic commands . . . . . . . . .
12.5 Commands . . . . . . . . . . . . . . . . . . . . .
12.5.1 !, execute system command, capture output
12.5.2 bg . . . . . . . . . . . . . . . . . . . . .
12.5.3 edit . . . . . . . . . . . . . . . . . . . . .
12.5.4 env . . . . . . . . . . . . . . . . . . . . .
12.5.5 hist . . . . . . . . . . . . . . . . . . . . .
12.5.6 lsmagic . . . . . . . . . . . . . . . . . . .
12.5.7 macro . . . . . . . . . . . . . . . . . . . .
12.5.8 pdoc . . . . . . . . . . . . . . . . . . . .
12.5.9 pdef . . . . . . . . . . . . . . . . . . . .
12.5.10 psource . . . . . . . . . . . . . . . . . . .
12.5.11 pfile . . . . . . . . . . . . . . . . . . . .
12.5.12 quickref . . . . . . . . . . . . . . . . . .
12.5.13 reset . . . . . . . . . . . . . . . . . . . .
12.5.14 run . . . . . . . . . . . . . . . . . . . . .
12.5.15 save . . . . . . . . . . . . . . . . . . . . .
12.5.16 time . . . . . . . . . . . . . . . . . . . .
12.5.17 who . . . . . . . . . . . . . . . . . . . . .
12.5.18 whos . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
86
86
86
87
87
87
88
88
88
88
88
88
88
88
88
89
89
89
89
89
89
89
89
89
89
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13 Tango I/O Speed
13.1 Reading the Position Attribute . . . . . . . . . . . . . . .
13.2 Reading the Counts Attribute . . . . . . . . . . . . . . .
13.3 Precise Cycle Times for Reading the Position and Counts
13.4 Position reading while the motor is moving . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
90
90
90
91
93
14 Examples
14.1 Tango device access . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.1 Signal Generator as VcExecutor (with Offset, P09) . . . . . . .
14.1.2 VcExecutor reading a P201-9B Encoder via module serial (P02)
14.1.3 Zugvorrichtung, P03 (argparse) . . . . . . . . . . . . . . . . .
14.1.4 A VcExecutor returning a Tango attribute . . . . . . . . . . . .
14.1.5 Virtual Motor as VMExecutor . . . . . . . . . . . . . . . . . .
14.1.6 A VmExecutor controlling a DAC . . . . . . . . . . . . . . . .
14.1.7 A VmExecutor controlling the setPoint . . . . . . . . . . . . .
14.1.8 moveLowAcc.py, low acceleration moves . . . . . . . . . . . .
14.1.9 move.py, performance test . . . . . . . . . . . . . . . . . . . .
14.1.10 Re-starting a device server using Starter . . . . . . . . . . . . .
14.1.11 Counter and Timer . . . . . . . . . . . . . . . . . . . . . . . .
14.1.12 Motor attributes . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.13 hkl2Angles . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.14 Reading the gap, Tango7 . . . . . . . . . . . . . . . . . . . . .
14.1.15 Events, motor position . . . . . . . . . . . . . . . . . . . . . .
14.1.16 Attributes, ADC, DAC . . . . . . . . . . . . . . . . . . . . . .
14.1.17 Commands and attributes, VFCADC . . . . . . . . . . . . . .
14.1.18 Attributes, I/O Register, SIS3610 . . . . . . . . . . . . . . . .
14.1.19 Spectrum, MCA 8701 . . . . . . . . . . . . . . . . . . . . . .
14.2 Tango database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.2.1 Enable/disable simulation mode . . . . . . . . . . . . . . . . .
14.2.2 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.2.3 Change Many Motor Properties . . . . . . . . . . . . . . . . .
14.2.4 Change other Properties of VME Devices . . . . . . . . . . . .
14.3 I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.3.1 Single keystrokes, non-blocking . . . . . . . . . . . . . . . . .
14.3.2 Socket I/O, Client/Server . . . . . . . . . . . . . . . . . . . .
14.3.3 Socket I/O, Spectra . . . . . . . . . . . . . . . . . . . . . . .
14.4 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.1 Catching a time-out . . . . . . . . . . . . . . . . . . . . . . .
14.4.2 Catching a time-out, smart version . . . . . . . . . . . . . . .
14.4.3 Ctrl-C Handling . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.4 Exception handling . . . . . . . . . . . . . . . . . . . . . . .
14.4.5 Regular expressions . . . . . . . . . . . . . . . . . . . . . . .
14.4.6 yesno() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.7 Move all .cbf files in a directory to another directory . . . . . .
14.5 QtGui, QtCore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.5.1 QMainWindow and QThread exchange signals . . . . . . . . .
14.5.2 QDialog callback launches QMainWindow . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
97
97
97
98
98
102
103
105
107
108
109
110
111
111
112
113
113
114
114
115
115
116
116
117
117
118
119
119
119
122
122
122
122
123
123
124
124
124
125
125
126
15 Appendix
15.1 Pattern . . . . . . . . .
15.1.1 Adapter . . . . .
15.1.2 Command . . . .
15.1.3 Decorator . . . .
15.1.4 Facade . . . . .
15.1.5 Factory . . . . .
15.1.6 Functor (closure)
15.1.7 Iteration . . . . .
15.1.8 Observer . . . .
15.1.9 Singleton . . . .
15.1.10 Strategy . . . . .
15.1.11 Template . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
128
128
128
129
129
130
130
131
131
132
133
133
134
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Chapter 1
Introduction
This note is intended to help people getting started with Python to use the PyTango interface. It does not contain
explanations, instead it covers the various topics by examples. This should be useful at least for those who know one
other scripting language.
The PyTango manual can be found on the ’pink site’: www.tango-controls.org. The authors are M. Ounsy, A. Buteau,
V. Forchi, E. Taurel and T. Coutinho.
Python can be studied in “Learning Python” by Mark Lutz and David Asher, “Programming Python” by Mark Lutz, all
printed by O’Reilly.
Chapter 2
Miscellaneous
2.0.1
Hello world
Here is the mandatory first example:
$ python -c "print ’hello world’"
2.0.2
Invoking Python
An interactive session is started by:
$ python
CTRL-d ends the session. The startup file for the interactive session is specified by the environment variable PYTHONSTARTUP.
Python scripts are invoked by:
$ python fileName.py
If the first line of the script contains the interpreter, it can be invoked by ./fileName.py.
#!/usr/bin/env python
#
# the following lines execute the startup script. They are optional.
#
import os
filename = os.environ.get(’PYTHONSTARTUP’)
if filename and os.path.isfile(filename):
execfile(filename)
print "hello world"
2.0.3
Command line arguments
Command line arguments are passed via the array sys.argv:
#!/usr/bin/env python
import sys
if len( sys.argv) != 3:
print "mvAllFiles.py <srcDir> <destDir>"
sys.exit(255)
srcDir = sys.argv[1]
destDir = sys.argv[2]
2.0.4
Executing a string of commands from the command line
$ python -c "import HasyUtils;HasyUtils.checkMacroServerEnvironment()"
The parameter is always the name of the script.
2.0.5
The name of the executing script
#!/usr/bin/env python
import os
print os.path.abspath( __file__ )
2.0.6
Indentation using XEmacs
When in Python mode, xemacs uses 8 spaces for each indent level by default. This value can be changed by inserting
the following lines in the xemacs startup file (e.g.: ˜/.xemacs/custom.el).
(custom-set-variables
’(py-indent-offset 4))
This works, if xemacs opens an empty file or if the file has been created using 4 spaces for each indent level.
Otherwise xemacs creates a local variable that reflects how the file was edited so far. You can check the value of
py-indent-offset by
M-x describe-variable py-indent-offset
Suppose we edit the following file:
#!/usr/local/bin/python
def func():
print "hello world"
# indent level: 8 spaces
func()
The commnd M-x describe-variable py-indent-offset produces the following output:
‘py-indent-offset’ is a variable declared in Lisp.
-- loaded from "python-mode"
Value: 8
This value is specific to the current buffer.
Default-value: 4
Documentation:
*Amount of offset per level of indentation.
‘C-c :’ can usually guess a good value when
you’re editing someone else’s Python code.
To solve this problem you have to indent the line print "Hello world" manually to 4 spaces, then invoke the
emacs command "C-c :" (py-guess-indent-offset).
Chapter 3
Variables
3.1
Type
The builtin function type() (8.19) returns the type of an object.
3.2
Scope, local, global, builtin
Name resolution happens in three stages (LGB):
local Names that are defined inside a function have local scope. The function locals() returns a dictionary containing
the local symbol table.
The function inspect.getmodule( object) (9.4) returns the objects module.
global Modules create global namespaces. The global statement which is executed inside a function makes module
names accessible. The function globals() returns a dictionary containing the modules global symbol table.
builtin Pre-defined Python names are in the module __builtin__.
Here is an example for local and global name references:
#!/usr/bin/env python
x = 1
y = 2
def func():
global x
x = 10
z = x + y
return z
print func()
print " x:", x
3.3
a
b
c
d
e
f
=
=
=
=
=
=
# necessary becaus we want to change the global x
# changes the global x
# uses the global y
# changed to 10
Numbers
1234
999L
1.23e3
0123
0xff
2 + 3j
#
#
#
#
#
#
integer
long integer
floating-point
octal
hex
complex
3.3.1
Operators
Expression operators:
+ - * / mathematical operators
% division remainder
>> << bitwise shift
lambda args: expr unnamed function
Bitwise operators:
& bitwise and
| bitwise or
ˆ bitwise excl. or
Here is an example of bit manipulations:
In [15]: a = 15
In [16]: bin(a)
Out[16]: ’0b1111’
In [17]: a &= ˜6
In [18]: bin(a)
Out[18]: ’0b1001’
In [19]: a |= 2
In [20]: bin(a)
Out[20]: ’0b1011’
3.4
Strings
#!/usr/bin/env python
import string
str = ’hello world’
#
# length
#
print len( str)
#
# to upper case letters
#
print str.upper()
# -> HELLO WORLD
#
# find a substring
#
print str.find( ’ll’)
# -> 2
print str.find( ’he’)
# -> 0
print str.find( ’moin’) # -> -1
#
# convert to number
#
print string.atoi( "11") + 1
# -> 12
#
# concatenation
#
str = str + "abc"
#
# repeating
#
str = " " * 320
#
# the escape character
#
print "abc\’d"
#
# indexing
#
print str[0]
print str[-1]
#
# slicing
#
print str[:3]
print str[1:]
print str[:-1]
3.4.1
# -> abc’d
# -> h
# -> o
# -> hel
# -> ello world
# -> hello worl
Formatting
#
# %s, %c, %d, %i (integer), %u (unsigned int), %o
# %x, %X, %e, %E, %f, %F, %g, %G, %%
#
a = "ein test %d %g %s" % ( 1, 1.23, ’hello’)
3.4.2
Splitting strings
See section 9.16.6.
3.4.3
Regular expressions
Here are a few most common examples:
#!/usr/bin/env python
import re
#
# search a substring in a string
#
pattern = "A.C."
string = "xxABCDxx"
matchobj = re.search( pattern, string)
if( matchobj):
print matchobj.start()
# -> 2
#
# divide a string into groups
#
patt = re.compile( "A(\d*)B(\d*)C(\d*)")
res = patt.match( "A1B12C123")
print res.group(1),res.group(2),res.group(3) # -> 1 12 123
Metacharacters:
\ | ( ) [ { ˆ $ * + ?
Pattern syntax:
. any character but newline
ˆ,$ start/end of line
* zero or more occ. of the prec. char. or group
+ one or more occ. of the prec. char. or group
? zero or one occ. of prec. char. or group (ungreedy)
[a-z] range fo chars, [abc] group of chars
[ˆ...] anything but range fo chars.
\ escape character
\t tab
\n newline
\\ backslash
\b start or end of word
\B next string not in word
\< start of word
\> end of word
\d digit
\D non-digit
\s a whitespace character
\S a non-whitespace character
\w any word charcter
\W any non-word character
\| multiple patterns
(...) group
Real life example
#!/usr/bin/env python
import re
line = "/var/tmp/ds.log/MacroServer_haspp09_[2016-11-08_00-14-22].log:SardanaTP.W007 ERROR
2016-11-03 13:44:11,757 p09/door/haspp09.01: An error occurred while running Macro \
’shclose() -> 368fa2ea-a1c3-11e6-831e-54bef70cdbee’"
patt = re.compile( r".*(\d{4})-(\d{2})-(\d{2})\s*(\d{2}):(\d{2}):(\d{2}).*:\s*(.*)’(.*)’")
res = patt.match( line)
if res:
for elm in res.groups():
print "elm:", elm
else:
print "no match"
# output:
# elm: 2016
# elm: 11
# elm: 03
# elm: 13
#
#
#
#
elm:
elm:
elm:
elm:
3.5
44
11
An error occurred while running Macro
shclose() -> 368fa2ea-a1c3-11e6-831e-54bef70cdbee
Lists
Basic operations:
a = []
a = [1]*5
L = [2]*3
a.append( 12)
a.extend( L)
a.sort()
a.reverse()
del a[0]
del a
len( a)
#
#
#
#
#
#
#
#
#
#
creates an empty list
creates
[1, 1, 1, 1, 1]
creates
[2, 2, 2]
appends an element
appends a list to a list [1, 1, 1, 1, 1, 2, 2, 2]
sorts a list
reverses a list
deletes an element
deletes the list
the length
a = [’spam’, ’eggs’, 100, 1234]
a[0]
a[-1]
# ’spam’, first element
# 1234, last element
a[0:2] = [1, 12]
a[0:2] = []
a[1:1] = [’bletch’, ’xyzzy’]
b = a[2:]
b = a[:]
#
#
#
#
#
[1, 12, 100, 1234]
[100, 1234]
[1, ’bletch’, ’xyzzy’, 1234]
[’xyzzy’, 1234]
copies a list, see below
#
#
#
#
[2, 3]
2
[1, [2, 3, ’xtra’], 4]
[2, 3, ’xtra’]
#
#
#
#
[2, 3, 4, 5] list concatenation
[2, 123, 3, 4, 5]
[2, 123, 3, 4]
[123, 3, 4]
Manipulations:
q = [2, 3]
p = [1, q, 4]
p[1]
p[1][0]
p[1].append(’xtra’)
q
r = [4, 5]
s = q + r
s.insert( 1, 123)
s.pop()
s.pop(0)
Printing:
freshfruit = [’ banana’, ’ loganberry ’, ’passion fruit
print [weapon.strip() for weapon in freshfruit]
Searching:
if elm in list:
print elm, "is in the list"
3.5.1
list comprehension
Here are a few examples for list comprehensions:
#
# Print a list. List comprehension works only with
’]
# expressions. Since {\tt print} is a statement, we have
# to import the print-function from __future__:
#
#!/usr/bin/env python
from __future__ import print_function
lst = [ ’c’, ’b’, ’a’]
[ print( elm) for elm in sorted( lst)]
#
# create a list
#
In [1]: lst = [n for n in range(10)]
#
# create a list using a contraint
#
In [3]: lst = [n for n in range(10) if n > 2]
#
# create a list of tuples
#
In [5]: lst = [(n,n+1) for n in range(10) if n > 2]
#
# create
#
In [12]:
In [13]:
In [14]:
3.5.2
a dictionary
lst1 = [0, 1, 2, 3]
lst2 = [’a’, ’b’, ’c’, ’d’]
hsh = { k: lst2[k] for k in lst1}
copy a list
In [8]: a = [1,2,3]
In [9]: b = a
# not a copy, b points to a
In [10]: id(a)
Out[10]: 3085175820L
In [11]: id(b)
Out[11]: 3085175820L
In [12]: b = a[:]
# [:] create a slice of the fulle list
In [13]: id(b)
Out[13]: 3085175788L
3.5.3
join(), split()
>>> lst = [’a’, ’b’, ’c’]
>>> str = ";".join(lst)
>>> str
’a;b;c’
>>> str.split(’;’)
[’a’, ’b’, ’c’]
>>> str.split(’;’,1)
[’a’, ’b;c’]
3.5.4
Searching
if "-t" in sys.argv:
print " found -t "
3.5.5
Sorting
Sorting in place
The order is reversed by:
In [12]: a = [’c’, ’b’, ’a’]
In [13]: a.sort()
In [14]: a
Out[14]: [’a’, ’b’, ’c’]
In [15]: a.reverse()
In [16]: a
Out[16]: [’c’, ’b’, ’a’]
Return a sorted list
In [4]: a = [’c’, ’b’, ’a’]
In [5]: sorted(a)
Out[5]: [’a’, ’b’, ’c’]
Sorting a list of devices
bw4/exp/mot1
bw4/exp/mot10
bw4/exp/mot11
bw4/exp/mot12
bw4/exp/mot13
...
The following example shows how to sort the list:
import string
import re
def cmpr( x, y):
pattern = re.compile( ".+mot(\d+)")
return cmp( string.atoi( pattern.match( x).group(1)),
string.atoi( pattern.match( y).group(1)))
self.devices = self.db.get_device_exported( "*exp/mot*")
self.devices.sort( cmpr)
3.5.6
Loops over a list in pairs
Here is an example of how to loop over a list in pairs 6.2.2.
3.5.7
zip (parsing vmstat output)
The following script parses the output of the ’vmstat 1 1’ command.
#!/usr/bin/env python
import os
’’’
$ vmstat 1 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----r b
swpd
free
buff cache
si
so
bi
bo
in
cs us sy id wa st
1 0
36 9343440 139596 4079320
0
0
185
52 358 274 6 3 89 1 0
’’’
lines = os.popen( ’vmstat 1 1’).readlines()
dct = dict( zip( lines[-2].split(), lines[-1].split()))
print "dct", dct
’’’
output:
dct {’wa’: ’1’, ’sy’: ’3’, ’b’: ’0’, ’us’: ’6’, ’bo’: ’52’, ’cache’: ’4079320’, ’bi’: ’185’,
’free’: ’9341332’, ’st’: ’0’, ’si’: ’0’, ’r’: ’0’, ’so’: ’0’, ’swpd’: ’36’, ’in’: ’358’,
’cs’: ’274’, ’id’: ’89’, ’buff’: ’139588’}
’’’
3.6 Dictionaries
Dictionaries are string-indexed arrays. Section 14.2.2 shows how these data types are used.
#!/usr/bin/env python
hsh = {}
#
tel = {’jack’: 4098, ’sape’:
tel[’guido’] = 4127
print tel
#
print tel[’jack’]
#
del tel[’sape’]
tel[’irv’] = 4127
print tel
#
print tel.keys()
#
print tel.has_key(’guido’) #
print ’guido’ in tel
#
3.6.1
create empty dicionary
4139}
-> {’sape’: 4139, ’guido’: 4127, ’jack’: 4098}
-> 4098
->
->
->
->
{’guido’: 4127, ’irv’: 4127, ’jack’: 4098}
[’jack’, ’irv’, ’guido’]
True
True
Iterating over a dictionary
Iterate over the keys of a dictionary:
In [4]: hsh = {’a’: 1, ’b’: 2}
In [5]: for k in hsh:
print k
...:
a
b
Iterate over the keys-value pairs of a dictionary:
In [1]: hsh = {’a’: 1, ’b’: 2}
In [2]: for k,v in hsh.iteritems():
...:
print k, v
...:
a 1
b 2
3.6.2
copy a dictionary
In [28]: dct = {’a’:1, ’b’:2}
In [29]: newDct = dct.copy()
In [30]: newDct
Out[30]: {’a’: 1, ’b’: 2}
In [31]: id(dct)
Out[31]: 139006540
In [32]: id(newDct)
Out[32]: 139009396
3.7 Tuples
#!/usr/bin/env python
t = 12345, 54321, ’hello!’
print t[0]
print t
#
# tuples may be nested
#
u = t, (1, 2, 3, 4, 5)
print u
# -> 12345
# -> (12345, 54321, ’hello!’)
# ((12345, 54321, ’hello!’), (1, 2, 3, 4, 5))
empty = ()
singleton = ’hallo’, # note the trailing comma
print singleton
# -> (’hallo’,)
3.7.1
Tuples to lists
In [38]: a = (1,2,3)
In [39]: b = list(a)
In [40]: a
Out[40]: (1, 2, 3)
In [41]: b
Out[41]: [1, 2, 3]
3.8
Sets
#!/usr/bin/env python
basket = [’apple’, ’orange’, ’apple’, ’pear’, ’orange’, ’banana’]
#
# create a set without duplicates
#
fruit = set(basket)
#
# membership testing
#
print ’pear’ in fruit # -> True
a = set(’abracadabra’)
b = set(’alacazam’)
print a
# -> set([’a’, ’r’, ’b’, ’c’, ’d’]), unique letters in a
print a - b
print a | b
print a & b
print a ˆ b
3.9
#
#
#
#
#
#
-> set([’r’, ’b’, ’d’]), letters in a but not in b
-> set([’a’, ’c’, ’b’, ’d’, ’m’, ’l’, ’r’, ’z’])
letters in either a or b
-> set([’a’, ’c’] letters in both a and b
-> set([’b’, ’d’, ’m’, ’l’, ’r’, ’z’])
letters in a or b but not both
Special global variables
__doc__
__file__
__name__
the modules documentation string
the pathname of the file from which the module was loaded
the modules name
Chapter 4
Modules and Packages
4.1 Some Statements on Modules and Packages
• Modules contain definitions (of functions and variables) and statements. They organize namespaces.
• Modules have their private symbol table which acts as the global symbol table for all functions inside the module.
• Modules correspond to files.
• If a module is executed as a script, the __name__ variable is set to __main__:
if __name__ == "__main__":
modMain()
• Packages organize modules.
• A directory containing an __init__ file is a package.
• The list sys.path contains the Python search path. It can be extended at runtime:
In [1]: import sys
In [2]: sys.path.insert( 0, "/home/userUser/pythonDir")
In [3]: sys.path
Out[3]:
[’/home/userUser/pythonDir’,
’’,
’/usr/bin’,
’/usr/lib/python2.7’,
...]
• The environment variable $PTHONPATH is inserted into sys.path.
• Names that are created in a module are called attributes (of the module object).
• The module name is stored in __name__.
• The dict dictionary stores the modules symbol table.
• The dir() function returns the modules symbol table.
>>> import time
>>> dir(time)
[’__doc__’, ’__file__’, ’__name__’, ’__package__’, ..., ’asctime’, ’clock’,
’ctime’, ’daylight’, ’gmtime’, ’localtime’, ’mktime’, ’sleep’, ...]
• The built-in variables and functions are in the module __builtin__:
In [4]: import __builtin__
In [5]: dir( __builtin__)
Out[5]:
[’ArithmeticError’,
’AssertionError’,
...]
4.2 Importing modules
• The import statement makes all names of a module available, e.g.:
import time
time.sleep(1)
A function that has been imported using this syntax has to be fully qualified when invoked, modulePath.functionName.
• The import-as statement makes all names of a module available and assigns a short-hand to the module path:
import sardana.macroserver.macro as ms
This allows you to refer to the Type variable using ms.Type instead of sardana.macroserver.macro.Type.
• The from-import statement imports names into the importing modules symbol table. To import single names:
from time import sleep
sleep(1)
To import all module names:
from time import *
Notice that the from-import imported names are referenced without leading module path, e.g. ’sleep()’ NOT
’time.sleep()’.
• Comparing import and from-import we see that the latter reduces the typing effort. However, considering bigger software projects the modulePath.functionName notation enhances the readability of the code. Therefore
the import syntax is recommended, import-as is of course also ok.
• The function dir() or dir( someObj) returns a list of names belonging to the respective scope. It is well suited
to understand the effect of import and from-import statements.
• import and from are executed once. They cannot be used to refresh modules that have already been loaded.
• The built-in function reload() re-loads a module which has been imported before. Note that the module is
specified omitting quotes.
import HasyUtils
...
reload( HasyUtils)
• The dictionary sys.modules contains the loaded modules.
• A module name becomes an attribute after the import.
4.3 Demo: Importing modules from packages and sub-packages
This section elaborates a bit on importing modules. Suppose we have the following package structure:
|-- main.py
‘-- p1
|-- __init__.py
|-- mod1.py
‘-- p2
|-- __init__.py
‘-- mod2.py
# empty
# contains class cl1
# empty
# contains class cl2
The program main.py refers to mod1 and mod2 belonging to the packages p1 and p2 with p2 being the sub-package
of p1.
The from-import syntax brings the symbols of mod1 and mod2 directly into mains name space. Therefore main can
use them without further qualification:
#!/usr/bin/env python
from p1.mod1 import *
from p1.p2.mod2 import *
o = cl1()
o = cl2()
#
# the following print-statement suppresses the default symbols like ’__builtins__’, ’__doc__
#
print "global symbol table:", [sym for sym in dir() if sym.find("__") == -1]
# print-out:
#
this is p1.mod1.cl1.__init__
#
this is p1.p2.mod2.cl2.__init__
#
global symbol table: [’cl1’, ’cl2’, ’o’]
#
The import statement, see below, brings only p1 into mains name space:
#!/usr/bin/env python
import p1.mod1
import p1.p2.mod2
o = p1.mod1.cl1()
o = p1.p2.mod2.cl2()
print "global symbol table:", [sym for sym in dir() if sym.find("__") == -1]
# print-out:
# this is p1.mod1.cl1.__init__
# this is p1.p2.mod2.cl2.__init__
# global symbol table: [’o’, ’p1’]
#
You may ask yourself whether the line import p1.p2.mod2 of the example above is really needed. In fact it is not.
The module p2.mod2 can be made available through p1 by adding import p2.mod2 to the p1 package init file,
p1/ init .py.
Packages may refer to sub-modules. The from-.-import syntax is a relative path specification:
|-- main.py
‘-- p1
|-- __init__.py
|-- mod1.py
|-- mod1Defs.py
‘-- p2
|-- __init__.py
‘-- mod2.py
# contains ’from . import mod1Defs’
# contains ’gConst = 9.81’
This is how main.py makes use of a definition from p1/mod1Defs.py:
#!/usr/bin/env python
import p1.mod1
import p1.p2.mod2
o = p1.mod1.cl1()
o = p1.p2.mod2.cl2()
print "gConst", p1.mod1Defs.gConst
print "main global symbol table:", [sym for sym in dir() if sym.find("__") == -1]
print "p1 global symbol table:", [sym for sym in dir(p1) if sym.find("__") == -1]
# print-out:
#
this is p1.mod1.cl1.__init__
#
this is p1.p2.mod2.cl2.__init__
#
gConst 9.81
#
main global symbol table: [’o’, ’p1’]
#
p1 global symbol table: [’mod1’, ’mod1Defs’, ’p2’]
4.4
The toplevel name space, builtins
builtins . dict is a dictionay defined in the toplevel name space. Sometimes this is a nice way to pass information
between program parts.
4.5
Injecting a variable into the name space of a module
The script demo.py imports the module testMod. The function load var() is part of testMod. It injects the variable a
into the name space of demo. load var() modifies the dictionary of varibles that are local to demo. The dictionary is
passed as an argument. (Eugen Wintersbergers brilliant idea is acknowledged).
#!/usr/bin/env python
#
# file demo.py
#
from testMod import *
load_var( locals())
print "a=",a
The file testMod.py contains the function load var() that injects the variable a into the name space of demo.
#!/usr/bin/env python
#
def load_var( d):
d[’a’] = 12
if __name__ == "__main__":
pass
Chapter 5
Classes
5.1
General remarks
For Python classes the following statements apply:
There is multiple inheritance.
All class members are public.
Base class members can be redefined in a derived class.
Classes should be derived from object to be compliant with new-style classes intoduced in Python2.2.
The methods object is the first argument (e.g. self)
x.f() is exactly equivalent to MyClass.f(x)
5.2
Class definition
#!/usr/bin/env python
class MyClass( object):
"A simple example class"
i = 123455
#
# the constructor
#
def __init__( self):
print " __init__"
self.data = []
#
# the destructor
#
def __del__( self):
print " __del__"
def f( self):
return ’hello world’
x = MyClass();
print x.f()
# -> __init__
# -> hello world
# -> __del__
Data members need not to be declared. We can start with an empty class:
#!/usr/bin/env python
class Employee(object):
pass
john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = ’John Doe’
john.dept = ’computer lab’
john.salary = 1000
print john.name
5.3
Multiple constructors
#!/usr/bin/env python
class MyClass( object):
#
# args
- tuple of anonymous arguments
# kwargs - dictionary of named arguments
#
def __init__( self, *args, **kwargs):
print " __init__"
print "args", args, "kwargs", kwargs
5.4
Inspect the members of a class
See section 9.4 about how to inspect the members of an object.
5.5
The class of an instance
In [12]: class myClass(object): pass
In [13]: o = myClass()
In [14]: isinstance( o, myClass)
Out[14]: True
In [15]: o.__class__.__name__
Out[15]: ’myClass’
5.6
Import classes from a module
See section 4.2 for how to import classes.
5.7
Inheritance
class DerivedClassName(BaseClassName):
...
# if the base class is defined in another module
class DerivedClassName(modname.BaseClassName):
...
# multiple inheritance
class DerivedClassName(base1, base2, base2):
5.8
Exceptions are classes
The statement
raise Class, instance
is a shorthand for:
raise instance
# shorthand for raise instance.__class__, instance
#!/usr/bin/env python
class B(object):
pass
class C(B):
pass
class D(C):
pass
for c in [B, C, D]:
try:
raise c()
except D:
print "D"
except C:
print "C"
except B:
print "B"
print " done "
Note that the section 14.4.4 gives an example of how to catch exceptions in PyTango.
5.9
Default attributes handler
Here is an example of how a class can handle references to undefined attributes, methods and variables.
#!/usr/bin/env python
class clss(object):
def __getattr__(self, name):
def handlerFunc( *args, **kwargs):
print "called with ", name, args, kwargs
if name == ’d’:
print "called from member d"
return
return handlerFunc
c = clss()
c.abc( 1, b="hallo")
c.d
5.10
delattr(), getattr(), setattr()
See section 8.5.
5.11 The @staticmethod decorator
The decorator @staticmethod turns a function into a static method which does not depend of self. These kind of
functions could also live in the module name space. The staticmethod decorator is used, if functions are somehow
related to a class and should be stored there.
#!/usr/bin/env python
class cl1(object):
i = 12345
@staticmethod
def staticfunc():
print "staticfunc", cl1.i
pass
cl1.staticfunc()
5.12 The @classmethod decorator
The decorator @classmethod turns a function into a class method which does not depend of self but receives the
class. These kind of functions can be used to add extra constructors:
#!/usr/bin/env python
class cl1(object):
def __init__( self):
pass
@classmethod
def constructor1( klass, town):
self = klass()
self.town = town
return self
pass
c1 = cl1.constructor1( ’Paris’)
print c1.town
5.13 The property function
The property function returns an object which operates a managed attribute:
class Oven( object):
def __init__( self):
self._temperature = 253
def setTemp( self, value):
self._temperature = value
def getTemp( self):
return self._temperature
def delTemp( self):
del self._temperature
temp = property( getTemp, setTemp, delTemp, "the temperature of the oven")
o = Oven()
print o.temp
o.temp = 260
print o.temp
5.14 The @property decorator
The @property decorator makes height a getter method for a read-only attribute:
#!/usr/bin/env python
class A( object):
def __init__( self):
self._height = 1.89
@property
def height( self):
return self._height
a = A()
print a.height
a.height = 2
Traceback (most recent call last):
File "t1.py", line 14, in <module>
a.height = 2
AttributeError: can’t set attribute
Chapter 6
Control Statements
6.1 If
x = int(raw_input("Please enter an integer: "))
if x < 0:
x = 0
print ’Negative changed to zero’
elif x == 0:
print ’Zero’
elif x == 1:
print ’Single’
else:
print ’More’
if a is None:
...
6.1.1
Operators
Logical operators:
x or y logical or, y is evaluated, if x is false
x and y logical and, y is evaluated, if x is true
not x negation
Comparison operators:
== tests value equivalence
!= not equal
¡ less
¿ greater
¡= less equal
=¿ greater or equal
is tests the identity of objects
is not tests the identity of objects
a | b bitwise or
a ˆ b bitwise exclusive or
a & b bitwise and
a << b, a >> b shift left or right
a + b, a - b addition/concatenation, subtraction
a * b, a / b, a % b multiplication/repetition, division, remainder/format
-a, + a, ˜a unary negation, identity, bitwise complement
x[i], x[i:j], x.y, x(...) indexing, slicing, qualification, function calls
(...), [...], {...}, ‘...‘ tuple, list, dictionary, conversion to strings
6.1.2
Truth
True means any nonzero number or nonempty object
False means not true: a zero number, empty object, None
6.2
Loops
Python knows break and continue. The else clause is executed, if for is normally exhausted. Here are loop examples:
#!/usr/local/bin/python
a = [ ’cats’, ’and’, ’dogs’]
for x in a:
print x,
print
#
# range( 10) runs from 0 to 9
#
for i in range( len( a)):
print i, a[i]
In the following example it is tested whether the loop exausted.
#!/usr/local/bin/python
#
# range( 2, 100) runs from 2 to 99
#
for n in range(2, 100):
for x in range(2, n):
if n % x == 0:
print n, ’equals’, x, ’*’, n/x
break
else:
# loop fell through without finding a factor
print n, ’is a prime number’
The following loops run over list elements:
knights = {’gallahad’: ’the pure’, ’robin’: ’the brave’}
for k, v in knights.iteritems():
print k, v
#
# -> gallahad the pure
# -> robin the brave
#
for i, v in enumerate([’tic’, ’tac’, ’toe’]):
print i, v
#
# -> 0 tic
# -> 1 tac
# -> 2 toe
# zip allows to loop over two sequences at the same time
questions = [’name’, ’quest’, ’favorite color’]
answers = [’lancelot’, ’the holy grail’, ’blue’]
for q, a in zip(questions, answers):
print ’What is your %s? It is %s.’ % (q, a)
#
# -> What is your name? It is lancelot.
# -> What is your quest? It is the holy grail.
# -> What is your favorite color? It is blue.
#
for element in [1, 2, 3]:
print element
for element in (1, 2, 3):
print element
for key in {’one’:1, ’two’:2}:
print key
for char in "123":
print char
for line in open("myfile.txt"):
print line
Some while loops:
#
# while
#
while 1:
print "running forever "
while a > b:
print "a > b"
if a == 10:
break
else:
print "we didn’t hit a <break>"
6.2.1
Break an outer loop
This is how outer loops can be broken:
#!/usr/bin/env python
class breakLoop( Exception): pass
try:
for i in range(10):
for j in range(5):
if i > 1 and j > 2:
raise breakLoop
except breakLoop:
print "loop was broken", i, j
output: loop was broken 2 3
6.2.2
Loop over a list in pairs
from itertools import izip
def pairs( lst):
a = iter(lst)
return izip(a, a)
for i, j in pairs( range(10)):
print "%d %d" % (i, j)
’’’
the output:
0 1
2 3
4 5
6 7
8 9
’’’
Chapter 7
Input/Output
7.1
Print
In [1]: print "hello world"
hello world
In [2]: print " i %d x %g " % (3, 3.14)
i 3 x 3.14
In [3]: a = 12.345678901234
In [4]: print "%s" % "{}".format(a)
12.3456789012
In [5]: print repr(a)
12.345678901234
In [6]: print "%g" % a
12.3457
Whenever print thinks that the current writing position is somewhere in the middle of a line, it adds a leading blank.
This can be avoided by using sys.stdout.write.
7.2
Internal write
#!/usr/bin/env python
rate = 12
temp = "Rate: %d " % rate
print temp
#
# preparing a format string
#
fmtString = " %%-%ds, %%s, sim. %%s" % (lenMax)
print fmtString % (a, b, c)
7.3
sys.stdin.readline()
import sys
print "give some input",
line = sys.stdin.readline()
print "\nyou typed", line
7.4
sys.stdout.write
#!/usr/bin/env python
import sys
import time
for i in range(10):
sys.stdout.write(’.’)
sys.stdout.flush()
time.sleep(1)
7.5
File I/O
out = open( ’data.test’, ’w’)
# out = open( ’data.test’, ’a’) append
L = [ ’def’, ’ghi’]
out.write( "abc\n")
out.writelines( L)
out.close()
inp = open( ’data.test’, ’r’)
print "<"
print inp.read()
# -> abc
#
defghi
print ">"
inp.close()
inp = open( ’data.test’, ’r’)
print inp.readline()
# -> abc
inp.close()
inp = open( ’data.test’, ’r’)
print inp.readlines()
# -> [’abc\n’, ’defghi’]
inp.close()
7.5.1
Reading dbHosts from a file
Here is a typical example for using readlines().
#!/usr/bin/env python
import traceback
import sys
fname = "/online_dir/" + "dbHostsTangoExplorer.lis"
try:
inp = open( fname, ’r’)
except Exception, e:
print " ", sys.exc_info()[0]
print " ", e
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback, limit=None, file=sys.stdout)
sys.exit( 255)
dbHosts = []
for line in inp.readlines():
if line.strip().find( ’#’) == 0:
continue
dbHosts.append( line.strip())
inp.close()
7.6
touch
To create an empty file:
open( fileName, ’a’).close()
Chapter 8
Built-in Functions
8.1
chr(), ord()
In [5]: ord(’a’)
Out[5]: 97
In [6]: chr(97)
Out[6]: ’a’
8.2
dir()
Returns attributes, the contents of dict , of objects (and modules). See section 4 for information about modules and
name spaces.
print dir()
print dir([])
the attributes of lists
print dir( sys)
modules are also objects
print dir( __builtins__)
8.3
exec()
The exec statement compiles and executes a python statement.
#!/usr/bin/env python
from PyTango import *
devices = { ’mot1’ :
"p09/motor/exp.01"}
for l in devices.keys():
exec "%s = DeviceProxy( ’%s’)" % (l, devices[l])
Another example:
for elm in dir(self):
exec "temp = type(self.%s)" % elm
print "%s %s " % ( repr(elm), temp)
8.4
eval()
The eval() function evaluates an expression and returns the result.
>>> a = 1
>>> eval("a+2")
3
8.5
delattr(), getattr(), setattr()
The setattr() assigns a value to an attributes of an object, getattr() returns the attribute of an object, delattr() deletes
it.
setattr(car, "speed", 320)
# the same as: car.speed = 320
getattr( car, "speed")
# the same as: car.speed
delattr( car, "speed")
# the same as: del car.speed
8.6
globals()
Returns a dictionary containing the current scopes global variables.
>>> dir()
[’__builtins__’, ’__doc__’, ’__name__’, ’__package__’]
>>> globals()[’a’] = 123
>>> dir()
[’__builtins__’, ’__doc__’, ’__name__’, ’__package__’, ’a’]
>>> a
123
8.7
hasattr()
Tests whether an object has an attribute:
>>> import time
>>> hasattr( time, "sleep")
True
8.8
id()
Returns an integer that may serve as the identity of an object.
In [18]: a = [1,2,3]
In [19]: b = a
In [20]: id(a)
Out[20]: 138930700
In [21]: id(b)
Out[21]: 138930700
That means ’b’ is not a copy of ’a’ but a reference to ’a’.
8.9
int(), float(), str()
The functions in this section convert strings to numbers and vice versa.
In [4]: str(4)
Out[4]: ’4’
In [5]: int("5")
Out[5]: 5
In [6]: float("5")
Out[6]: 5.0
8.10
int(), round()
In [9]: int(3.9)
Out[9]: 3
In [10]: round(3.9)
Out[10]: 4.0
8.11
issubclass()
In [9]: issubclass( obj, ms.Macro)
Out[9]: True
8.12
iter()
The iter () and next() functions make the fib class an iterator:
class fib:
def __init__( self):
self.n1 = 1
self.n2 = 1
def next( self):
(self.n1, self.n2, oldn2) = (self.n1+self.n2, self.n1, self.n2)
return oldn2
def __iter__( self):
return self
f = fib()
for i in f:
print i
if i > 10: break
The iter() function can be applied to any sequence:
k = iter( range(5))
while True:
try:
print k.next()
except:
break
8.13
lambda (closure)
Lambdas can be used with map() or filter. This is demonstrated in 8.14
Lambdas can also be used to contruct closures. These are functions which refer to variables that are latched at the time
when the close is created. This is how it works:
#!/usr/bin/env python
def f1(x):
print "f1:", x
a =
f =
a =
g =
f()
g()
’one’
lambda a=a: f1(a)
’two’
lambda a=a: f1(a)
The trick is the ’a=a’ argument of lambda. This way the current value of ’a’ is frozen in a local variable.
Here is another example for constructing a closure:
#!/usr/bin/env python
def f1(x):
print "f1:", x
def genFunc( b):
return lambda : f1(b)
a = ’one’
f = genFunc( a)
a = ’two’
g = genFunc( a)
f()
g()
8.14
map, filter
In [14]: map( (lambda x: x + 1), [ 1, 2, 3])
Out[14]: [2, 3, 4]
In [15]: filter( (lambda x: x % 2 == 0), [ 1, 2, 3, 4, 5, 6])
Out[15]: [2, 4, 6]
8.15
locals()
Returns a dictionary containing the current scopes local variables. See section 4.5 where it is used to modify the module
name space from another module.
8.16
map()
Returns a list by applying a function to an input list.
In [7]: a = (u’h’, u’a’, u’l’, u’l’, u’o’)
In [8]: "".join(map(str, a))
Out[8]: ’hallo’
8.17
range()
The range function generates a sequence of numbers:
print range(5)
print range( 1, 9)
print range( 0, 10, 2)
8.18
# -> [0, 1, 2, 3, 4]
# -> [1, 2, 3, 4, 5, 6, 7, 8]
# -> [0, 2, 4, 6, 8]
sort(), sorted()
Section 3.5.5 demonstrates how to sort a list.
8.19
type(), isinstance()
In [1]: a = [1,2]
In [2]: type( a) is list
Out[2]: True
In [3]: isinstance(a, list)
Out[3]: True
In [4]: a = u’abc’
In [5]: isinstance(a, (str, unicode))
Out[5]: True
See section 5.5 for an example of how to find the class of an object.
8.20
yield
See section 15.1.7.
Chapter 9
Useful modules
9.1 argparse
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser(
formatter_class = argparse.RawDescriptionHelpFormatter,
description="Tango server utility",
epilog=’’’\
Examples:
TngUtility.py -s Macro
starts servers beginning with ’Macro’
TngUtility.py -l Macro
lists servers and related devices
’’’)
#
# notice that ’pattern’ is a positional argument
#
parser.add_argument(’pattern’, help=’a pattern to match the server name or "all"’)
parser.add_argument(’-k’, dest="kill", action="store_true", help=’kill server’)
#parser.add_argument(’-p’, dest="pattern", help=’a pattern to match the server name or "all"
parser.add_argument(’-l’, dest="list", action="store_true", help=’list server and devices’)
parser.add_argument(’-s’, dest="start", action="store_true", help=’start server’)
args = parser.parse_args()
print
print
print
print
"kill %s" % args.kill
"list %s" % args.list
"start %s" % args.start
"pattern %s" % args.pattern
The is the output of ’TngUtility.py –help’:
usage: TngUtility.py [-h] [-k] [-l] [-s] pattern
Tango server utility
positional arguments:
pattern
a pattern to match the server name or "all"
optional arguments:
-h, --help show this help message and exit
-k
kill server
-l
list server and devices
-s
start server
Examples:
TngUtility.py -s
starts servers
TngUtility.py -l
lists servers
Macro
beginning with ’Macro’
Macro
and related devices
9.2 commands
9.2.1
getoutput(), capturing shell command output, hostname
Returns the result of a shell command
>>> import commands
>>> a = commands.getoutput( "hostname")
>>> a
’haso107tk’
If the command output conains several lines, they can be split:
>>> import commands
>>> lines = commands.getoutput( "ls").split(’\n’)
>>> lines
Notice that, if a call to a sub-shell has to be protected by a time-out, it has to be done this way 14.4.2.
9.3 glob
Find files using Unix-like pattern:
In [1]: import glob
In [2]: glob.glob( ’*.fio’)
Out[2]:
[’tst1_00018.fio’,
’tst_00086.fio’,
’tst_00087.fio’,
’tst_00094.fio’,
’tst1_00004.fio’,
’tst_00090.fio’,
’tst_00092.fio’,
’tst_00089.fio’,
’au_alo_14_0001.fio’,
’tst_00088.fio’,
’tst_00095.fio’,
’tst_00091.fio’,
’tst1_00005.fio’]
In [3]: glob.glob( ’tst1_*.fio’)
Out[3]: [’tst1_00018.fio’, ’tst1_00004.fio’, ’tst1_00005.fio’]
Using iglob as an iterator:
In [7]: for i in glob.iglob(’tst1*.fio’):
print i
...:
tst1_00018.fio
tst1_00004.fio
tst1_00005.fio
9.4 inspect
The inspect module retrieves useful information about an object:
import inspect
inspect.getmembers( o)
return a list of (name, value) pairs with all memers of an object
inspect.isclass( o)
return True, if the object is a class
inspect.getmodule(o)
return the name of the module
9.5 math
9.5.1
math.fabs
In [11]: import math
In [12]: math.fabs(-5)
Out[12]: 5.0
9.5.2
math.radians, math.degrees
In [14]: import math
In [15]:
Out[15]:
In [16]:
Out[16]:
9.5.3
math.radians(90)
1.5707963267948966
math.degrees(math.radians(90))
90.0
math.sin
In [18]: import math
In [19]: math.sin(math.radians(90))
Out[19]: 1.0
9.6 matplotlib
The matplotlib home page is on matplotlib.org. This site contains lots of information including tons of examples.
Currently we are using version 0.99. The documentation of this version is no longer available on the matplotlib home
page. However, you will find the docu in the web.
9.6.1
General remarks
For us there are 3 typical use cases for displaying graphics with matplotlib:
• A python script displays some data and waits for the user to close the figure window. This is the blocking mode
which invokes plt.show(). See 9.6.3 for an example.
• An application repeatedly sends graphics output to the figure widget for e.g. monitoring purposes. Control
always stays at the application. This is the non-blocking mode which invodes plt.draw(). See 9.6.4 for an
example.
• Detached applications, e.g. the MacroServer, produce non-blocking graphics output. See 9.6.7 examples.
9.6.2
Simple vs. OO API
Matplotlib offers two different APIs, a simple API and an object oriented API. The files mplSimple.py and mplObjects.py, see below, display examples for each of these. Both programs produce the same output, see 9.1.
The code for the simple interface looks easy-to-use: all functions are taken from the pyplot module. No objects are
explicitly referenced. The interesting part starts with plt.subplot() which implicitly creates figure and axes objects.
Since pyplot keeps track of the current objects, the following calls to xlabel() and ylabel() change the recently created
axes object. Since the underlying objects are only treated implicitly, a re-use of these objects is clearly not the purpose
of the simple API. This interface has been designed for applications that exit after data are displayed. The disadvantages
of the simple API are that the user has less control and that the commands have to be executed in a strict sequence.
#!/usr/bin/env python
#
# file name: mplSimple.py
#
import matplotlib
matplotlib.use( ’TkAgg’)
import matplotlib.pyplot as plt
import numpy as np
t = np.arange( 0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
c = np.cos(2*np.pi*t)
plt.ion()
plt.subplot( 2, 1, 1)
plt.plot( t, s, ’r’)
plt.xlabel( "Phase")
plt.ylabel( "Sin")
plt.subplot( 2, 1, 2)
plt.plot( t, c)
plt.xlabel( "Phase")
plt.ylabel( "Cos")
plt.draw()
Ths OO interface is well suited for applications integrating graphics output in some data processing sequence. Data
structures can be re-used and the graphics window remains open for many diplay cycles.
#!/usr/bin/env python
#
# file name: mplObjects.py
#
# IPython: from mplObjects import *
#
import matplotlib
matplotlib.use( ’TkAgg’)
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
if not plt.get_fignums():
fig = plt.figure(1, figsize=(11.6,8.2))
else:
fig = plt.figure(1)
fig.clear()
sin = fig.add_subplot( 2, 1, 1, ylabel="Sin")
cos = fig.add_subplot( 2, 1, 2, ylabel="Cos")
t = np.arange( 0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
c = np.cos(2*np.pi*t)
line_sin, = sin.plot( t, s, ’r’)
sin.set_xlabel( "Phase")
line_cos, = cos.plot( t, c)
cos.set_xlabel( "Phase")
plt.draw()
Figure 9.1: Sine and cosine
9.6.3
Blocking mode
Here is a Python script that displays a 1D plot. The function plt.show() blocks the program execution until the graphics
window 9.2 is closed.
#!/usr/bin/env python
import matplotlib.pyplot as plt
import numpy as np
plt.plot(np.random.rand(100))
plt.ylabel(’Random Numbers’)
plt.xlabel(’x-Axis’)
plt.show()
Figure 9.2: Random Numbers
9.6.4
Non-blocking, from IPython, debugging
Suppose you want to test matplotlib interactively from IPython without preparing a figure by hand. In this case you
have to import a piece of code (mpl.py) by:
In [1]: from mpl import *
Here is the contents of mpl.py.
#!/usr/bin/env python
import matplotlib
matplotlib.use( ’TkAgg’)
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
fig = plt.figure(1, figsize=(11.6,8.2))
sin = fig.add_subplot( 2, 1, 1, xlabel="Phase", ylabel="Sinus", title="Sin")
cos = fig.add_subplot( 2, 1, 2, xlabel="Phase", title="Cos")
t = np.arange( 0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
c = np.cos(2*np.pi*t)
line_x, = sin.plot( t, s)
line_y, = cos.plot( t, c, ’r’)
plt.draw()
By using the ’from mpl import *’ syntax the symbols of mpl.py are available on the IPython command line, e.g.:
In [2]: plt.get_fignums()
Out[2]: [1]
In [3]: fig.get_axes()
Out[3]:
[<matplotlib.axes.AxesSubplot object at 0xa2c886c>,
<matplotlib.axes.AxesSubplot object at 0xa2eaf4c>]
9.6.5
Create a png, useful for web applications
#!/usr/bin/env python
import sys
import numpy as np
import matplotlib
matplotlib.use(’Agg’)
import matplotlib.pyplot as plt
def r():
plt.ion()
fig = plt.figure(1, figsize=(11.6,8.2))
plt.hist(np.random.rand(100))
fig.savefig(’test.png’)
# fig.savefig( sys.stdout)
if __name__ == ’__main__’:
r()
9.6.6
Subplots
Figure 9.3 shows some useful matplotlib features.
#!/usr/bin/env python
import matplotlib.pyplot as plt
import numpy as np
x = np.arange( 0.01, 10, 0.01)
y = np.exp(-(x-5)*(x-5)/3)
fig = plt.figure( 1, figsize = (11.6, 8.2))
plt.figtext( 0.5, 0.95, "A figure containing various plots", va=’center’, ha = ’center’)
plt.subplot(2,2,1)
plt.plot(x, y)
plt.axis([0,10,0,1.2])
plt.ylabel(’Gauss’)
plt.xlabel(’x-Axis’)
plt.subplot(2,2,2)
plt.hist(y, 50)
plt.xlabel(’x-Axis’)
plt.subplot(2,3,4)
plt.plot( x,y, ’b’)
plt.axis([0,10,0,1.2])
plt.title( "no log", fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
plt.grid(True)
plt.subplot(2, 3, 5)
plt.loglog( x, y, ’g’)
plt.axis([0,10,0,1.2])
plt.title( "log-x, log-y", fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
plt.grid(True)
plt.subplot( 2, 3, 6)
plt.semilogx( x, y, ’r--’)
plt.axis([0,10,0,1.2])
plt.title( "log-x", fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
plt.grid(True)
plt.show()
Figure 9.3: SubPlots
9.6.7
Plotting from the MacroServer
If the following code is copied to the file $HOME/sardanaMacros/mpl demo.py, the macros are available after a restart
of the MacroServer. They can be invoked by:
$ spock
Spock 1.0.0 -- An interactive laboratory application.
help
object?
-> Spock’s help system.
-> Details about ’object’. ?object also works, ?? prints more.
p09/door/haso107klx [1]: mpl_various
p09/door/haso107klx [2]: mpl_scan
The macro mpl various creates the display 9.4, the macro mpl scan is continuously updating a graphics screen. The
final plot is displayed in 9.5.
Figure 9.4: mpl various
The ofther macros in mpl demo.py are mpl clear, which clears the graphics window, and mpl close, which closes the
graphics window. Note that the graphics windows survives a spock session unless it it explicitly closed. This is because
the matplotlib commands are executed on the MacroServer.
Figure 9.5: mpl scan
This is the contents of bf mpl demo.py.
#!/usr/bin/env python
#
# file name: mpl_demo.py
#
__all__ = ["mpl_scan", "mpl_various", "mpl_close", "mpl_clear", "mpl_ms"]
from sardana.macroserver.macro import macro, Type
import time
import matplotlib.pyplot as plt
import numpy as np
@macro()
def mpl_scan( self):
"""
this macro simulates a scan.
two plots are created, new points are added
"""
plt.ion()
if not plt.get_fignums():
fig = plt.figure( 1, figsize = (11.6, 8.2))
else:
fig = plt.figure(1)
fig.clear()
fig.text( 0.5, 0.05, "A figure containing two plots", va=’center’, ha=’center’)
energy = [e for e in range( 8900, 9100, 2)]
c1 = [ (np.sin(e) + 2*np.random.random()) for e in energy]
c2 = [ np.tan(e) for e in energy]
ax_c1 = fig.add_subplot(211)
ax_c2 = fig.add_subplot(212)
ax_c1.set_autoscale_on( True)
ax_c2.set_autoscale_on( True)
line_c1, = ax_c1.plot( energy, c1, ’b’)
line_c2, = ax_c2.plot( energy, c2, ’ro’)
ax_c1.set_xlim( xmin=energy[0], xmax=energy[-1])
ax_c2.set_xlim( xmin=energy[0], xmax=energy[-1])
for i in range( len(energy)):
line_c1.set_data(energy[0:i+1], c1[0:i+1])
line_c2.set_data(energy[0:i+1], c2[0:i+1])
plt.draw()
@macro()
def mpl_various( self):
"""
creates some plots to demonstrate various matplotlib features
"""
plt.ion()
if not plt.get_fignums():
fig = plt.figure( 1, figsize = (11.6, 8.2))
fig.text( 0.5, 0.05, "A figure containing various plots", va=’center’, ha=’center’)
else:
fig = plt.figure(1)
fig.clear()
x = np.arange( 0.01, 10, 0.01)
y = np.exp(-(x-5)*(x-5)/3)
gauss = fig.add_subplot(2,2,1)
gauss.plot(x, y)
gauss.axis([0,10,0,1.2])
gauss.set_ylabel(’Frequency’)
gauss.set_xlabel(’x-Axis’)
gauss.set_title( ’Gauss’)
hist = fig.add_subplot(2,2,2)
hist.hist(y, 50)
hist.set_xlabel(’x-Axis’)
hist.set_title(’Histogramm’)
nolog = fig.add_subplot(2,3,4)
nolog.plot( x,y, ’b’)
nolog.axis([0,10,0,1.2])
nolog.set_title( "no log", fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
nolog.grid(True)
loglog = fig.add_subplot(2, 3, 5)
loglog.loglog( x, y, ’g’)
loglog.axis([0,10,0,1.2])
loglog.set_title( "log-x, log-y", fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
loglog.grid(True)
logx = fig.add_subplot( 2, 3, 6)
logx.semilogx( x, y, ’r--’)
logx.axis([0,10,0,1.2])
logx.set_title( "log-x", fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
logx.grid(True)
plt.draw()
#
# one draw() is not enough
#
plt.draw()
@macro()
def mpl_close( self):
""" closes the graphics widget"""
plt.close()
#
# clear-axes is needed
#
plt.cla()
plt.close()
@macro()
def mpl_clear( self):
""" clears the graphics window"""
fig = plt.figure(1)
fig.clear()
plt.draw()
#
# need a second draw() - I don’t know why
#
plt.draw()
@macro( [["command", Type.String, None, "a matplotlib command"],])
def mpl_ms( self, command):
""" execute a matplotlib command on the MacroServer
mpl_ms plt.get_fignums()
mpl_ms plt.close()
mpl_ms fig.draw() # fig is available
mpl_ms fig.show()
"""
fig = plt.figure(1)
temp = "res = %s" % command
exec temp
self.output( "command %s returns %s" % (command, res))
9.6.8
Scan simulation
The following script displays two plots being repeatedly updated with arrays of increasing length. Compare the same
procedure in pyqtgraph 9.7.2.
The following script simulates a scan
#!/usr/bin/env python
#
# file name: mpl_scan.py
#
from sardana.macroserver.macro import macro, Type
import time
import matplotlib.pyplot as plt
import numpy as np
dt = None
ax_dt = None
def display():
global dt, ax_dt
xMin = 0
xMax = 50
xDelta = 0.02
x = np.arange( xMin, xMax, xDelta)
t = np.tan(2*np.pi*x)
tm = range( len(t))
plt.ion()
if not plt.get_fignums():
fig = plt.figure( 1, figsize = (11.6, 8.2))
else:
fig = plt.figure(1)
fig.clear()
fig.text( 0.5, 0.95, "A figure containing two plots", va=’center’, ha=’center’)
ax_tan = fig.add_subplot(211)
ax_tan.grid( True)
ax_tan.set_autoscale_on( True)
ax_tan.set_xlabel( ’Phase’)
ax_tan.set_ylabel( ’tan’)
ax_tan.set_title( ’the tan() function’)
tan, = ax_tan.plot( x, t, ’b’)
ax_tan.set_xlim( xmin=x[0], xmax=x[-1])
ax_dt = fig.add_subplot(212)
ax_dt.grid( True)
ax_dt.set_autoscaley_on( True)
ax_dt.set_xlabel( ’no. of display calls’)
ax_dt.set_ylabel( ’time[s]’)
ax_dt.set_title( ’time to display various lenths of both plots’)
dt, = ax_dt.plot( x, tm, ’r’)
ax_dt.set_xlim( 0, len( x) - 1)
tm = []
start = time.time()
for i in range( len(x)):
tan.set_data(x[0:i], t[0:i])
tm.append( time.time() - start)
start = time.time()
dt.set_data(range(i), tm[0:i])
ax_dt.relim()
ax_dt.autoscale_view(True,False,True)
plt.draw()
Figure 9.6: matplotlib: scan simulation
9.6.9
fioPlotter
The following piece of code parses .fio files. The graphics is produced in a widget (9.7) or a png file.
#!/usr/bin/env python
’’’
this module reads and plots fio files. It can be invoked from
- the command line, blocking mode
$ fioPlotter.py -f fileName.fio
Figure 9.7: fioPlotter output
- the command line, to create png files
$ fioPlotter.py -p -f fileName.fio
- ipython and python scripts, non-blocking mode
import fioPlotter as fp
a = fp.fioPlotter("<fileName>")
a.plot()
’’’
from optparse import OptionParser
import math, sys
import matplotlib
flagStandalone = False
class fioPlotter:
def __init__(self, fileName, flagPng):
self.comments = []
self.user_comments = []
self.parameters = []
self.dataSets = []
self.fileName = fileName
self.flagPng = flagPng
self._read( fileName)
#
# /home/p12user/dirName/gen_00001.fio -> gen_00001
#
self.scanName = fileName.split("/")[-1].split(".")[0]
#
# enable the desired display mode: avoid show()
# but update the plot only at the end
#
if not flagStandalone:
plt.ion()
self.fig = plt.figure( 1, figsize = (11.6, 8.2))
plt.draw()
else:
self.fig = plt.figure( 1, figsize = (11.6, 8.2))
return
def clear( self):
’’’
clears the figure widget
’’’
self.fig.clear()
plt.draw()
def plot( self):
’’’
plots the contents of a fio file
’’’
length = len(self.dataSets)
col = math.ceil(math.sqrt(length))
row = math.ceil( length/col)
plt.figtext( 0.5, 0.95, self.scanName, va=’center’, ha = ’center’)
for i in range( 0, length):
plt.subplot( col, row, i + 1)
plt.title( self.dataSets[i].deviceName, fontsize = 10,
x = 0.95, y = 0.85, ha=’right’, va=’top’)
plt.plot( self.dataSets[i].x, self.dataSets[i].y, "b", linewidth = 1)
#
# we want the blocking mode, if the script is called from the command line
#
if self.flagPng:
self.fig.savefig( self.scanName + ’.png’)
elif flagStandalone:
plt.show()
else:
plt.draw()
def _read( self, name):
’’’
!
! user comments
!
%c
comments
%p
parameterName = parameterValue
%d
Col 1 AU_ALO_14_0001 FLOAT
Col 2 AU_ALO_14_0001 FLOAT
Col 3 AU_ALO_14_0001_RING FLOAT
data data data etc.
’’’
print "reading", name
try:
inp = open( name, ’r’)
except IOError as e:
print "Failed to open {0}, {1}".format( name, e.strerror)
sys.exit(255)
lines = inp.readlines()
inp.close()
flagComment = 0
flagParameter = 0
flagData = 0
for line in lines:
line = line.strip()
if line.find( "!") == 0:
self.user_comments.append( line)
flagComment = False
flagParameter = False
flagData = False
elif line.find( "%c") == 0:
flagComment = True
flagParameter = False
flagData = False
continue
elif line.find( "%p") == 0:
flagComment = False
flagParameter = True
flagData = False
continue
elif line.find( "%d") == 0:
flagComment = False
flagParameter = False
flagData = True
continue
#
if flagComment:
self.comments.append( line)
#
# parName = parValue
#
if flagParameter:
lst = line.split( "=")
self.parameters.append( {lst[0]: lst[1]})
if not flagData:
continue
lst = line.split()
if lst[0] == "Col":
#
# the ’Col 1 ...’ description does not create a
# new FIO_dataset because it contains the x-axis for all
#
if lst[1] == "1":
pass
else:
self.dataSets.append( fioDataset( lst[2]))
else:
for i in range(1, len( self.dataSets)):
self.dataSets[i-1].x.append( lst[0])
self.dataSets[i-1].y.append( lst[i])
class fioDataset:
’’’
the class represents a column of a FIO file. The first column is the
x-axis which is used by all columns, name_in, e.g. test_00001_C1
’’’
def __init__(self, name_in):
self.name = name_in
lst = self.name.split(’_’)
if len(lst) > 1:
self.deviceName = lst[-1]
if self.deviceName.find( "0") == 0:
self.deviceName = "ScanName"
else:
self.deviceName = "n.n."
self.x = []
self.y = []
return
if __name__ == ’__main__’:
flagStandalone = True
usage = "usage: %prog <-p> fileName.fio "
parser = OptionParser(usage=usage)
parser.add_option( "-f", action="store", type="string",
dest="fileName", help="name of the .fio file")
parser.add_option( "-p", action="store_true", dest="flagPng",
default = False, help="create png file")
(options, args) = parser.parse_args()
if options.fileName is None:
parser.print_help()
sys.exit(255)
if options.flagPng:
matplotlib.use( ’TkAgg’)
import matplotlib.pyplot as plt
a = fioPlotter( options.fileName, options.flagPng)
a.plot()
else:
import matplotlib.pyplot as plt
pyplot
import matplotlib.pyplot as plt
cla()
clear the current axis
clf()
clears the current figure
close(), close( <num>), close( fig), close(’all’)
close a/all figure window(s)
ion(), ioff()
turns the interactive mode on/off
isinteractive()
returns the interactice status
show()
shows the figure
axis Class
import matplotlib.pyplot as plt
figure Class
A figure corresdongs to a graphics window. Opening a second figure opens a second window.
import matplotlib.pyplot as plt
clear()
clears the figure
fig = plt.gcf()
return the reference to the current figure
9.7 pyqtgraph
The pyqtgraph home page is on pyqtgraph.org. This site contains some information including a link to the documentation.
9.7.1
General remarks
• Requirement: Python 2.7
9.7.2
Scan simulation
The following script displays two plots being repeatedly updated with arrays of increasing length. Compare the same
procedure in matplotlib 9.6.8.
#!/usr/bin/env python
#
# file name: pg_scan.py
#
# this script can be executed, e.g., from ipython
#
# In [1]: import pg_scan
# In [2]: pg_scan.display()
#
# pg_scan simulates a measurement. Two plots, tan and dt,
# are displayed from within a loop. The length of the data
# fields increase. The plot dt shows the time it takes to
# display the tan data. No QtGui mainloop is involved.
#
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
import time
import pyqtgraph.functions as fn
win = None
def display():
global win
xMin = 0
xMax = 50
xDelta = 0.02
x = np.arange( xMin, xMax, xDelta)
t = np.tan(2*np.pi*x)
app = QtGui.QApplication.instance()
if app is None:
pg.setConfigOption( ’background’, ’w’)
pg.setConfigOption( ’foreground’, ’k’)
app = pg.mkQApp()
if win is None:
win = pg.GraphicsWindow( title="Scan the Tango Function")
win.clear()
#win.setBackground( QtGui.QBrush(QtGui.QColor(240,240,240)))
win.addLabel( "A figure containing two plots", row = 1, col = 1)
tan = win.addPlot( row=2, col=1)
tan.showGrid( x = True, y = True)
tan.setTitle( title = "The tan() Function")
tan.setLabel( ’left’, ’tan’)
tan.setLabel( ’bottom’, ’phase’)
tan.enableAutoRange( x = False, y = True)
tan.setXRange( xMin - 0.25, xMax + 0.25)
dt = win.addPlot( row=3, col=1)
dt.showGrid( x = True, y = True)
dt.setTitle( title = "time to plot various lengths of two plots")
dt.setLabel( ’left’, ’time[s]’)
dt.setLabel( ’bottom’, ’no. of display calls’)
dt.enableAutoRange( x = False, y = True)
dt.setXRange( 0, (xMax - xMin)/xDelta)
tm = []
start = time.time()
for i in range( len(x)):
tan.clear()
tan.plot( x[0:i], t[0:i], pen=( 0, 0, 255))
tm.append(time.time() - start)
start = time.time()
dt.clear()
dt.plot( range(i), tm[:i], pen=( 255, 0, 0))
app.processEvents()
9.7.3
fioPlotter
The following script displays the contents of a .fio file. Compare the same procedure in matplotlib 9.6.9.
#!/usr/bin/env python
’’’
this module reads and plots fio files. It can be invoked from
Figure 9.8: pyqtgraph: scan simulation
- the command line, blocking mode
$ pg_fioPlotter.py -f fileName.fio
- ipython and python scripts, non-blocking mode
import pg_fioPlotter as fp
a = fp.fioPlotter("<fileName>")
a.plot()
’’’
from optparse import OptionParser
import math, sys
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
app = None
win = None
a = None
class fioDataset:
’’’
the class represents a column of a FIO file. The first column is the
x-axis which is used by all columns, name_in, e.g. test_00001_C1
Figure 9.9: pyqtgraph: fioPlotter
’’’
def __init__(self, name_in):
self.name = name_in
lst = self.name.split(’_’)
if len(lst) > 1:
self.deviceName = lst[-1]
if self.deviceName.find( "0") == 0:
self.deviceName = "ScanName"
else:
self.deviceName = "n.n."
self.x = []
self.y = []
return
class fioPlotter:
def __init__(self, fileName):
self.comments = []
self.user_comments = []
self.parameters = []
self.dataSets = []
self.fileName = fileName
self._read( fileName)
#
# /home/p12user/dirName/gen_00001.fio -> gen_00001
#
self.scanName = fileName.split("/")[-1].split(".")[0]
return
def _read( self, name):
’’’
!
! user comments
!
%c
comments
%p
parameterName = parameterValue
%d
Col 1 AU_ALO_14_0001 FLOAT
Col 2 AU_ALO_14_0001 FLOAT
Col 3 AU_ALO_14_0001_RING FLOAT
data data data etc.
’’’
print "reading", name
try:
inp = open( name, ’r’)
except IOError as e:
print "Failed to open {0}, {1}".format( name, e.strerror)
sys.exit(255)
lines = inp.readlines()
inp.close()
flagComment = 0
flagParameter = 0
flagData = 0
for line in lines:
line = line.strip()
if line.find( "!") == 0:
self.user_comments.append( line)
flagComment, flagParameter, flagData = False, False, False
elif line.find( "%c") == 0:
flagComment, flagParameter, flagData = True, False, False
continue
elif line.find( "%p") == 0:
flagComment, flagParameter, flagData = False, True, False
continue
elif line.find( "%d") == 0:
flagComment, flagParameter, flagData = False, False, True
continue
#
if flagComment:
self.comments.append( line)
#
# parName = parValue
#
if flagParameter:
lst = line.split( "=")
self.parameters.append( {lst[0]: lst[1]})
if not flagData:
continue
lst = line.split()
if lst[0] == "Col":
#
# the ’Col 1 ...’ description does not create a
# new FIO_dataset because it contains the x-axis for all
#
if lst[1] == "1":
pass
else:
self.dataSets.append( fioDataset( lst[2]))
else:
for i in range(1, len( self.dataSets)):
self.dataSets[i-1].x.append( float(lst[0]))
self.dataSets[i-1].y.append( float( lst[i]))
def plot( self):
’’’
plots the contents of a fio file
’’’
length = len(self.dataSets)
nCol = int(math.ceil(math.sqrt(length)))
nRow = int(math.ceil( length/nCol))
win.clear()
win.addLabel( self.scanName, row = 1, col = 1, colspan = nCol)
for i in range( 0, length):
r = int( math.ceil(i/nCol) + 2)
c = i % nCol + 1
plt = win.addPlot( row=r, col=c)
plt.setContentsMargins( 10, 10, 10, 10)
plt.showGrid( x = True, y = True)
plt.setTitle( title = self.dataSets[i].deviceName)
plt.plot( self.dataSets[i].x, self.dataSets[i].y, pen = (0, 0, 255))
app = QtGui.QApplication.instance()
if app is None:
pg.setConfigOption( ’background’, ’w’)
pg.setConfigOption( ’foreground’, ’k’)
app = pg.mkQApp()
if win is None:
win = pg.GraphicsWindow( title="The fioPlotter")
win.resize( 1000, 800)
win.clear()
if __name__ == ’__main__’:
usage = "usage: %prog -f fileName.fio "
parser = OptionParser(usage=usage)
parser.add_option( "-f", action="store", type="string", dest="fileName", help="name of t
(options, args) = parser.parse_args()
if options.fileName is None:
parser.print_help()
sys.exit(255)
a = fioPlotter( options.fileName)
a.plot()
app.exec_()
9.8 numpy
The NumPy home page is on www.numpy.org.
9.8.1
array
In [38]: import numpy as np
In [39]: a = [1,2,3,4]
In [40]: b = np.array(a)
In [41]: type a
-------> type(a)
Out[41]: <type ’list’>
In [42]: type b
-------> type(b)
Out[42]: <type ’numpy.ndarray’>
9.8.2
ndarray, slicing
In [1]: import numpy as np
In [2]: a = np.array( range(24))
In [3]: a[0:6:2]
Out[3]: array([0, 2, 4])
A slice is selected by i:j:k with i as the first and j as the last index, k being the step width.
9.8.3
ndarray, ellipsis [...]
The ellipsis covers all remaining elements:
In [1]: import numpy as np
In [2]: a = np.array( range(24)).reshape( 4, 2, 3)
In [3]: b = a[0][...]
In [4]: b
Out[4]:
array([[0, 1, 2],
[3, 4, 5]])
In [5]: b[...] = 12
In [6]: b
Out[6]:
array([[12, 12, 12],
[12, 12, 12]])
In [7]: a
Out[7]:
array([[[12, 12, 12],
[12, 12, 12]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23]]])
In [8]: a.__array_interface__[’data’]
Out[8]: (31198960, False)
In [9]: b.__array_interface__[’data’]
Out[9]: (31198960, False)
Line 3 creates the symbol b as a reference to a. Lines 8 and 9 show that the virtual addresses are identical.
The ellispsis can also be used in an assignment:
In [1]: import numpy as np
In [2]: a = np.array( range(24)).reshape( 4, 2, 3)
In [3]: a
Out[3]:
array([[[ 0,
[ 3,
1,
4,
2],
5]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23]]])
In [4]: c = np.ones(6).reshape(2,3)
In [5]: c
Out[5]:
array([[ 1.,
[ 1.,
In [6]:
1.,
1.,
1.],
1.]])
a[0][...] = c
In [7]: a
Out[7]:
array([[[ 1,
[ 1,
1,
1,
1],
1]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23]]])
In [8]: c[...] = 2
In [9]: c
Out[9]:
array([[ 2.,
[ 2.,
2.,
2.,
In [10]: a
Out[10]:
array([[[ 1,
[ 1,
1,
1,
2.],
2.]])
1],
1]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23]]])
To create an array filled with a number:
In [8]: a = np.array( [12] * 10)
In [9]: a
Out[9]: array([12, 12, 12, 12, 12, 12, 12, 12, 12, 12])
This array can then be set to some other value:
In [10]: a[...] = 11
In [11]: a
Out[11]: array([11, 11, 11, 11, 11, 11, 11, 11, 11, 11])
This works also with more-dimensional arrays:
In [18]: a = np.array( [12] * 10).reshape(2,5)
In [19]: a
Out[19]:
array([[12, 12, 12, 12, 12],
[12, 12, 12, 12, 12]])
In [20]: a[...] = 11
In [21]: a
Out[21]:
array([[11, 11, 11, 11, 11],
[11, 11, 11, 11, 11]])
To set a part of the array:
In [21]: a
Out[21]:
array([[11, 11, 11, 11, 11],
[11, 11, 11, 11, 11]])
In [22]: a[0][...] = 10
In [23]: a
Out[23]:
array([[10, 10, 10, 10, 10],
[11, 11, 11, 11, 11]])
9.8.4
arange
In [24]: import numpy as np
In [25]: a = np.arange(0, 10, 1, dtype=float)
In [26]: a
Out[26]: array([ 0.,
9.8.5
1.,
2.,
3.,
4.,
linspace
In [30]: import numpy as np
In [31]: a = np.linspace( 0, 2*np.pi, 100)
In [32]: s = np.sin(a)
9.8.6
ones
In [27]: import numpy as np
In [28]: a = np.ones((3,4))
In [29]:
Out[29]:
array([[
[
[
9.8.7
a
1.,
1.,
1.,
1.,
1.,
1.,
1.,
1.,
1.,
1.],
1.],
1.]])
zeros
In [13]: import numpy as np
In [14]: a = np.zeros(5)
In [15]: a
Out[15]: array([ 0.,
0.,
In [16]: a.dtype
Out[16]: dtype(’float64’)
In [17]: a.shape
Out[17]: (5,)
In [18]: a.ndim
Out[18]: 1
9.9 os
9.9.1
os.access()
Test file permissions:
In [9]: import os
0.,
0.,
0.])
5.,
6.,
7.,
8.,
9.])
In [10]: os.access( "/online_dir/online.xml", os.R_OK)
Out[10]: True
In [11]: os.access( "/online_dir/online.xml", os.X_OK)
Out[11]: False
In [12]: os.access( "/online_dir/online.xmllll", os.R_OK)
Out[12]: False
9.9.2
os.chdir()
Changes the proces working directory:
import os
os.chdir( ’/home/someUser’)
9.9.3
os.getcwd()
Returns the current working directory.
>>> import os
>>> os.getcwd()
’/home/p15user’
9.9.4
os.getenv()
Returns the size of a file.
>>> import os
>>> os.getenv( "HOME")
’/home/p15user’
9.9.5
os.getpid()
Returns the process PID.
In [1]: import os
In [2]: os.getpid()
Out[2]: 18399
9.9.6
os.isatty()
Returns True, if the file description points to a tty.
In [1]: import os
In [2]: os.isatty(1)
Out[2]: True
9.9.7
os.kill()
Sends a signal to a process.
In [1]: import os
In [2]: os.kill( 12345, -9)
9.9.8
os.listdir() (all files in a directory)
Returns the files of the specified directory.
In [1]: import os
In [2]: os.listdir(’.’)
Out[2]:
[’.Spectra_misc.pl’,
’nxTest.py˜’,
’nxTest.py’,
’fio2h5.py˜’,
...]
Another example:
#!/usr/bin/env python
import os
for file in os.listdir( "/home/user/temp"):
if file.endswith( ".py"):
print "file", file
And another example:
import os
path = ’.’
files = [ f for f in os.listdir(path) if os.path.isfile(os.path.join(path,f)) ]
9.9.9
os.mkdir()
Creates a directory.
In [3]: import os
In [4]: os.mkdir( ’/online_dir/MotorLogs’)
In [5]: os.path.isdir( ’/online_dir/MotorLogs’)
Out[5]: True
9.9.10
os.path.basename()
Returns the base part of the pathname.
>>> import os
>>> os.path.dirname( ’/home/user/temp/file.lis’’)
’file.lis’
9.9.11
os.path.dirname()
Returns the directory part of the pathname.
>>> import os
>>> os.path.dirname( ’/home/user/temp/file.lis’’)
’/home/user/temp’
9.9.12
os.path.exists()
Returns True, if a file exists.
>>> import os
>>> os.path.exists( ’/online_dir’)
True
9.9.13
os.path.getsize()
Returns the size of a file.
In [1]: import os
In [2]: os.path.getsize( ’/online_dir/online.xml’)
Out[2]: 51289
9.9.14
os.path.isdir()
Returns True, if the argument points to an existing directory.
In [2]: import os
In [3]: os.path.isdir(’/etc’)
Out[3]: True
9.9.15
os.path.isExecutable()
This function does not exist. However, the following example helps:
In [15]: import os
In [16]: os.path.isfile( "/online_dir/TkIrc.pl") and os.access( "/online_dir/TkIrc.pl", os.X
Out[16]: True
9.9.16
os.path.isfile()
Returns True, if the argument points to a regular file.
In [7]: import os
In [8]: os.path.isfile(’/etc/fstab’)
Out[8]: True
9.9.17
os.popen(), capturing shell command output
>>> import os
>>> argout = os.popen(’ls -al’).read()
>>> print argout
total 40
drwxr-xr-x 2 kracht users
20480 Dec
drwxr-xr-x 96 kracht hasylab 12288 Dec
-rwxr-xr-x 1 kracht hasylab
194 Aug
-rwxr-xr-x 1 kracht hasylab
450 Dec
9
9
1
9
14:22
11:36
14:06
14:16
.
..
Clean.pl
t1.py
Notice that, if a call to a sub-shell has to be protected by a time-out, it has to be done this way 14.4.2.
9.9.18
os.popen(), ps ax, MacroServer/haspp09
#!/usr/bin/env python
import os
srvName = "MacroServer/haso107klx"
#
# MacroServer/haspp09 -> MacroServer, haspp09
#
tsName, instance = srvName.split("/")
#
# temp: "MacroServer haspp09"
#
temp = "%s %s" % (tsName, instance)
inp = os.popen(’ps ax’).read()
lst = inp.split(’\n’)
for line in lst:
if line.find( temp) > 0:
print "server ", srvName, "exists"
9.9.19
os.remove(), os.rmdir()
Remove a single file:
>>> import os
>>> os.remove( ’/tmp/FileToBeRemoved’)
haspp15oh1
Remove an empty directory:
>>> import os
>>> os.rmdir( ’DirToBeRemoved’)
haspp15oh1
9.9.20
os.rename() (mv)
os.rename( ’oldName’, ’newName’)
9.9.21
os.system(), execute a shell command, sensing the return-state
The function os.system() executes a shell command and return the return-state:
In [1]: import os
In [2]: a = os.system( "notExist")
sh: 1: notExist: not found
In [3]: a
Out[3]: 32512
In [4]: a = os.system( "hostname")
haso107d1
In [5]: a
Out[5]: 0
9.9.22
os.system(), calling ping
Sometimes it is necessary to sense whether a host is online.
In [1]: import os
In [2]: a =
os.system( "ping -c 1 -w 1 -q haspp08 > /dev/null 2>&1")
In [3]: a
Out[3]: 0
In [4]: a =
In [5]: a
Out[5]: 512
os.system( "ping -c 1 -w 1 -q haspp88 > /dev/null 2>&1")
9.9.23
os.walk(), traverse dirs and sub-dirs
import os
rootDir = ’/home/kracht/Misc/IVP/fiotest_00794’
for dirName, subDirs, files in os.walk(rootDir):
print(’Directory: %s’ % dirName)
print(’subDirs: %s’ % str( subDirs))
for fname in files:
print(’ %s’ % fname)
9.10 platform
In [1]: import platform
In [2]: platform.platform()
Out[2]: ’Linux-3.2.0-4-amd64-x86_64-with-debian-7.7’
In [3]: platform.platform().find( ’debian’) > 0
Out[3]: True
9.11 pprint
Produces human readable output of data structures.
In [1]: import pprint
In [2]: tel = {’jack’:
In [3]: pprint.pprint(
{’jack’: 4098, ’sape’:
In [4]: pprint.pprint(
{
’jack’: 4098,
’sape’: 4139}
4098, ’sape’: 4139}
tel)
4139}
tel, indent=5, width=20)
Using the constructor:
In
In
In
In
{
[1]: import pprint
[2]: tel = {’jack’: 4098, ’sape’: 4139}
[3]: pp = pprint.PrettyPrinter( indent=3, width=20)
[4]: pp.pprint( tel)
’jack’: 4098,
’sape’: 4139}
9.12 random
Return a random number [0., 1.).
import random
print random.random()
9.13 shutil
9.13.1
copy
In [4]: import shutil
In [5]: shutil.copy( ’/online_dir/onlineIVP.xml’, ’/online_dir/online.xml’)
9.14 signal
9.14.1
signal
import signal
def signalHandler( signum, frame):
print "signalHander: %d " % (signum)
signal.signal( signal.SIGHUP, signalHandler)
9.15 socket
9.15.1
gethostname()
Returns the hostname:
>>> import socket
>>> socket.gethostname()
’haspp23’
9.15.2
gethostbyaddr()
>>> import socket
>>> res = socket.gethostbyaddr( ’131.169.38.134’)
>>> res
(’haspts04.desy.de’, [], [’131.169.38.134’])
>>> res[0]
’haspts04.desy.de’
9.16 string
9.16.1
atoi()
Converts a string to a number.
import string
i = string.atoi( "123")
9.16.2
>>>
>>>
0
>>>
1
>>>
-1
find()
str = "hello world"
str.find("hello")
str.find("ello")
str.find("hallo")
9.16.3
lower(), upper()
Converts a string to lower/upper case letters.
import string
lowerCase = string.lower( "Python")
upperCase = string.upper( "Python")
9.16.4
partition, rpartition()
Both functions return a 3-tupel. rpartition uses the last occurence of the string to split it.
>>> "pre.test.fio".rpartition(’.’)[0]
’pre.test’
>>> "pre.test.fio".partition(’.’)[0]
’pre’
9.16.5
replace()
>>> import string
>>> par = "a<space>b"
>>> string.replace(par, "<space>", " ")
’a b’
9.16.6
split(), join()
Returns a list of tokens: String.split( [delimiter [,maxsplit]])
>>> lst = [’a’, ’b’, ’c’]
>>> str = ";".join(lst)
>>> str
’a;b;c’
>>> str.split(’;’)
[’a’, ’b’, ’c’]
>>> str.split(’;’,1)
[’a’, ’b;c’]
9.16.7
strip(), strip(), lstrip()
The function strip() removes leading and trailing white space.
In [7]: "\nabc\n".strip()
Out[7]: ’abc’
In [8]: "\nabc\n".lstrip()
Out[8]: ’abc\n’
In [9]: "\nabc\n".rstrip()
Out[9]: ’\nabc’
9.17 subprocess, capturing shell command output
#!/usr/bin/env python
import subprocess
p = subprocess.Popen( ’ls’, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
lines = []
while True:
line = p.stdout.readline()
if line == ’’ and p.poll() != None:
break
lines.append(line)
print lines
9.18 sys
9.18.1
argv
#!/usr/bin/env python
import sys
for arg in sys.argv:
print arg
9.18.2
exitfunc
The following script shows how a funtion is defined that us automatically executed at the before image exit.
#!/usr/bin/env python
import sys
def exitFunc():
print " this is exit "
sys.exitfunc = exitFunc
print " hello world "
9.18.3
getframe(), traceback
The function sys. getframe() returns traceback information.
#!/usr/bin/env python
import sys
def func2():
for n in range( 0, 5):
try:
code = sys._getframe(n).f_code
print "traceback: depth: %d function: %s file: %s line: %d" % \
(n, code.co_name, code.co_filename, code.co_firstlineno)
except ValueError:
print "level ", n, "is too deep"
break
def func1():
return func2()
func1()
#
# output:
# traceback: depth: 0 function: func2 file: frame.py line: 4
# traceback: depth: 1 function: func1 file: frame.py line: 14
# traceback: depth: 2 function: <module> file: frame.py line: 2
# level 3 is too deep
9.18.4
path (PYTHONPATH)
The variable sys.path is a list of strings containing the Python search path. The code below displays the list and shows
how to insert an additional directory. The python search path can also be extended by modifying the PYTHONPATH
environment variable, e.g.: export PYTHONPATH=$PYTHONPATH:/home/User/SomeDir.
In [1]: import sys
In [2]: sys.path
Out[2]:
[’’,
’/usr/bin’,
’/usr/lib/python2.7’,
’/usr/lib/python2.7/plat-linux2’,
’/usr/lib/python2.7/lib-tk’,
’/usr/lib/python2.7/lib-old’,
’/usr/lib/python2.7/lib-dynload’,
’/usr/local/lib/python2.7/dist-packages’,
’/usr/lib/python2.7/dist-packages’,
’/usr/lib/python2.7/dist-packages/PIL’,
’/usr/lib/python2.7/dist-packages/gtk-2.0’,
’/usr/lib/pymodules/python2.7’,
’/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode’,
’/usr/lib/python2.7/dist-packages/IPython/extensions’]
In [3]: sys.path.insert( 0, "/home/User/someDir")
In [4]: sys.path
Out[4]:
[’/home/User/someDir’,
’’,
’/usr/bin’,
’/usr/lib/python2.7’,
’/usr/lib/python2.7/plat-linux2’,
’/usr/lib/python2.7/lib-tk’,
’/usr/lib/python2.7/lib-old’,
’/usr/lib/python2.7/lib-dynload’,
’/usr/local/lib/python2.7/dist-packages’,
’/usr/lib/python2.7/dist-packages’,
’/usr/lib/python2.7/dist-packages/PIL’,
’/usr/lib/python2.7/dist-packages/gtk-2.0’,
’/usr/lib/pymodules/python2.7’,
’/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode’,
’/usr/lib/python2.7/dist-packages/IPython/extensions’]
9.18.5
stdin.readline()
>>> import sys
>>> someName = sys.stdin.readline()
hello
>>> someName
’hello\n’
9.18.6
threads
import time
from threading import Thread
class THRD( Thread):
def __init__( self):
Thread.__init__( self)
def run(self):
count = 0
while 1:
count += 1
time.sleep(1)
print "this is thread "
if count > 20:
print " thread ends"
break
p = THRD()
p.start()
9.19 time
9.19.1
localtime(), date and time
Print the current date:
#!/usr/bin/env python
import time
tm = time.localtime()
print "%4d-%02d-%02d" % ( tm.tm_year, tm.tm_mon, tm.tm_mday)
#
# produces: 2016-12-08
#
Here is the complete localtime structure:
(tm_year=2010, tm_mon=11, tm_mday=3, tm_hour=14,
tm_min=18, tm_sec=34, tm_wday=2, tm_yday=307, tm_isdst=0)
9.19.2
strftime(), formatted date-time string
>>> import time
>>> time.strftime("%d %b %Y %H:%M:%S", time.localtime())
’15 Dec 2011 11:39:54’
9.19.3
doty(), day-of-the-year
Calculate day ot the year:
import time
def doty():
tm = time.localtime()
part = tm.tm_hour/24. + tm.tm_min/1440. + tm.tm_sec/1440./60.
return (tm.tm_yday - 1. + part)
9.19.4
sleep(), usleep()
The function sleep() take any numerical argument:
import time
time.sleep(0.01)
9.19.5
time()
The function time.time() returns the number of seconds since epoch as a floating point number.
#!/usr/bin/env python
import time
time_start = time.time()
time.sleep( 0.1)
print time.time() - time_start
9.20 traceback
9.20.1
traceback.print tb
This function tells you where the exception occured:
#!/usr/bin/env python
import sys
import traceback
def func():
try:
a = 1/0
except Exception, e:
print " ", sys.exc_info()[0]
print " ", e
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback, limit=None, file=sys.stdout)
func()
The output:
<type ’exceptions.ZeroDivisionError’>
integer division or modulo by zero
File "t1.py", line 7, in func
a = 1/0
Chapter 10
Functions
10.1
Definition
#!/usr/bin/env python
def plus( x, y):
"""a documentation string (plus.__doc__)"""
return x + y
print plus( 3, 5)
10.2
Argument passing
Arguments are passed by assigning local names to objects.
Strings and numbers are immutable objects. They cannot be changed from the function. Lists and dictionaries are
mutable and can be changed.
#!/usr/bin/env python
def func( a, b):
a = 1
# has only a local effect
b[0] = 2
# changes the list in the calling function
return
c = 3
d = [4, 5]
func( c, d)
print " c ", c
print " d ", d
Arguments may be collected in a list:
def scanFunc( *a):
print a
return
scanFunc( 1, 2, 3)
Arguments can be unpacked:
#!/usr/bin/env python
def func( a, b, c):
print a, b, c
return
a = [1, 2, 3]
func( *a)
Arguments may be collected in a dictionary:
#!/usr/bin/env python
def scanFunc( **a):
print a
return
scanFunc( start = 0,
stop = 10,
delta = 1)
Functions can have default values for arguments:
def yes_or_no(prompt, retries=4, complaint=’Yes or no, please!’):
while True:
ok = raw_input(prompt)
if ok in (’y’, ’ye’, ’yes’): return True
if ok in (’n’, ’no’, ’nop’, ’nope’): return False
retries = retries - 1
if retries < 0: raise IOError, ’refusenik user’
print complaint
print yes_or_no( "do you really want it ")
Here are examples for keyword arguments:
def scan( start, stop=100, delta=1):
print "scan from ", start, " to ", stop, "by ", delta
scan(
scan(
scan(
scan(
10)
10, 200, 5)
10, 200, delta=5)
10, stop=200, delta=5)
#
#
#
#
->
->
->
->
scan
scan
scan
scan
from
from
from
from
10
10
10
10
to
to
to
to
100
200
200
200
by
by
by
by
1
5
5
5
Receiving a list:
def func( *a):
print a
func( ’a’, 2, 3)
Receiving a dictionary:
def func( **a):
print a
func( start= 0, stop= 10)
Collecting a list and a dictionary:
def scan( fname, *lst, **dct):
print fname, lst, dct
scan( ’tst.fio’, ’1st comment’, ’2nd comment’, start=0, stop=10, delta=1)
range() receives an unpacked list.
In [4]: a = [0,10]
In [5]: range(*a)
Out[5]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
func() receives an unpacked dictionary.
def func( name, start=0, stop=10):
print name, start, stop
dct = {’name’: ’tst’, ’start’: 1, ’stop’: 2}
func( **dct)
10.3
Returning a list
def someNumbers( m):
value = []
for n in range(m):
value.append( n)
return value
print someNumbers( 5)
# -> [0, 1, 2, 3, 4]
Chapter 11
Exceptions
11.1 Catching exceptions
Those parts of the code that may lead to errors can be protected by a try-except block. The first example shows how to
catch all exceptions:
from lxml import etree
import sys
xmlFile = ’/online_dir/online.xml’
parser = etree.XMLParser( ns_clean=True, remove_comments=True)
try:
tree = etree.parse( xmlFile, parser)
except Exception, e:
(eType, value, tracebackObject) = sys.exc_info()
print "eTpye", str(eType)
print "value", str(value)
print e
root = tree.getroot()
for dev in root:
for elm in dev:
if not elm.tag == ’name’:
continue
print elm.tag, elm.text
Here is an example of how to catch a specific exception:
try:
inp = open( name, ’r’)
except IOError as e:
print "Failed to open {0}, {1}".format( name, e.strerror)
sys.exit(255)
11.2 Traceback Information
The following script shows how an exception is caught and how the traceback information is retrieved and printed.
#!/usr/bin/env python
import traceback
import sys
def funcCrash():
a = 1/0
return
try:
funcCrash()
except Exception, e:
print "catching the exception"
_, _, tb = sys.exc_info()
traceback.print_tb(tb)
tb_info = traceback.extract_tb(tb)
filename, line, func, text = tb_info[-1]
print ">>> File %s, line %s, in %s \n
%s" % (filename, line, func, text)
This is the output:
catching the exception
File "./trace.py", line 11, in <module>
funcCrash()
File "./trace.py", line 7, in funcCrash
a = 1/0
>>> File ./trace.py, line 7, in funcCrash
a = 1/0
11.3 Raising an exception
This is how exceptions may be raised.
#!/usr/local/bin/python
try:
raise Exception(’good’, ’morning’)
except Exception, e:
print type(e)
# the exception instance
print e
# __str__ allows args to printed directly
a, b = e
# __getitem__ allows args to be unpacked directly
print a, b
11.4 User defined exception
#!/usr/bin/env python
class MyException( Exception):
def __init__( self, *argin):
self.value = argin
def __str__( self):
return repr( self.value)
try:
raise MyException( "this", "is", "an", "exception")
except MyException, e:
# referencing value member explicitly
print "caught exception ", e.value
# using __str__ function member
print "caught exception ", e
11.5 Tango exceptions
To raise a Tango exception say:
if not doorname:
PyTango.Except.throw_exception( "n.n.",
"no doorname supplied",
"vc_pilatus.__init__")
To re-throw an exception use:
try:
door = PyTango.DeviceProxy( doorname)
except PyTango.DevFailed, e:
PyTango.Except.re_throw_exception( e,
"from DeviceProxy",
"failed to create proxy to door %s " % doorname,
"Hasylab.getSardanaProxies")
This is how an exception is caught:
#!/usr/bin/env python
import PyTango
try:
dev = PyTango.DeviceProxy( "abc")
except PyTango.DevFailed, e:
PyTango.Except.print_exception( e)
To customize the ouput:
try:
val = proxy.read_attribute( attr).value
except PyTango.DevFailed, e:
print "
%-15s: error" % (attr)
for arg in e.args:
print "
Desc: %s" % (arg.desc)
#print "origin: %s" % (arg.origin)
#print "reason: %s" % (arg.reason)
#print "severity: %s" % (arg.severity)
11.6 AttributeError
The AttributeError exception is raised e.g., if a proxy lacks an attribute.
...
try:
motor = PyTango.DeviceProxy( fullName)
except PyTango.DevFailed, e:
PyTango.Except.print_exception( e)
print "configureDevices cannot create a proxy to " + fullName + " terminate configuratio
continue
#
# abs has no UnitLimitMin/˜Max
#
try:
min = motor.UnitLimitMin
max = motor.UnitLimitMax
except AttributeError, name:
print "configureDevices: attribute error", name
continue
...
11.7 Catching a time-out
The following script demonstrates how an operation which may run forever is protected by a time-out handler.
#!/usr/bin/env python
import signal, sys, time
#
# an exception that is raised by handlerALRM
#
class TMO( Exception):
def __init__( self, *argin):
self.value = argin
def __str__( self):
return repr( self.value)
def handlerALRM( signum, frame):
print "handlerALRM: called with ", signum
raise TMO( "tmo-exception")
def main():
#
# connect SIGARLM to handlerALRM
#
signal.signal( signal.SIGALRM, handlerALRM)
#
# produce a SIGALRM after 1s.
#
signal.alarm(1)
try:
#
# in a realistic example time.sleep() is replaced by
# code that may run into a time-out
#
time.sleep(3)
except TMO, e:
print "Caught", e
signal.alarm(0)
if __name__ == ’__main__’:
main()
Chapter 12
IPython
12.1
General remarks
IPython is an interactive shell for Python.
12.2
Configuration
The IPython configuration is stored in $HOME/.config/ipython. This can be changed by setting IPYTHONDIR
or by the command line option -ipythondir.
The %edit command uses the EDITOR environment variable to select an editor.
IPython startup files are are profile-specific, located in e.g. $HOME/.config/ipython/profile_spockdoor/startup.
Here is an example:
#!/usr/bin/env python
#
# file name ˜/.config/ipython/profile_spockdoor/startup/00-start.py
#
import os, time, atexit
#
# the exit handler copies the log file to /online_dir
# saving the old version
#
def _spockExitHandler():
if os.path.exists( ’/online_dir/ipython_log.py’):
os.system( ’vrsn -nolog -s /online_dir/ipython_log.py’)
#
# get the ipython shell
#
ip = get_ipython()
#
# -o log include output
# -r raw log ’wm exp_dmy01’ instead of get_ipython().magic(u’wm exp_dmy01’)
# -t with timestamp
#
if os.path.exists( "%s/ipython_log.py" % os.environ[’PWD’]):
os.system( "vrsn -nolog -s %s/ipython_log.py" % os.environ[’PWD’])
os.system( "/bin/rm %s/ipython_log.py" % os.environ[’PWD’])
ip.magic( ’%logstart -o -r -t’)
#
# store the current motor attributes in a new version of /online_dir/MotorLogs/motorLog.lis
#
# -x execute
# -q quiet
# -c the name of the calling program is written to the log file
#
os.system(’MotorLogger.py -x -q -c spock’)
os.system( "ln -sf %s/ipython_log.py /online_dir/ipython_log.py" % os.environ[’PWD’])
#
# write some text to the log file
#
# ip.logger.log_write( unicode( "# some text \n"))
#
# register exit handler
#
atexit.register( _spockExitHandler)
12.3
Magic
The command magic displays the list of magic keywords. All commands are first tested against this list. If the test
fails, the command is sent to Python.
This is the syntax for finding information about a magic command:
wa?
The flag automagic (can be set by a command line argument) determines whether magic keywords need a leading
%.
The command
%automagic
toggles the automagic mode.
12.3.1
Defining a magic command
import string
import IPython.ipapi
def func( self, parameters= ’’):
params=parameters.split()
print "hello world", params
ip = IPython.ipapi.get()
ip.expose_magic( ’mname’, func)
These lines define the macro %mname. They could be part of ipy_user_conf.py.
12.4
Execute a list of magic commands
For certain purposes it may be convenient to execute a list of magic commands. Here is an example:
#!/usr/bin/env python
import IPython
ip = IPython.get_ipython()
mg = "mg_ivp"
comList = [
"change_mg -g %s -t d1_t01 -c d1_c01" % mg,
"ascan exp_dmy01 0 1 10 0.1",
"delete_mg %s" % mg,
]
for com in comList:
ip.magic(com)
12.5
Commands
12.5.1
!, execute system command, capture output
In [7]: !uname -a
Linux haso107d1 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux
In [8]: a = !uname -a
In [9]: a
Out[9]: [’Linux haso107d1 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux’]
In [10]: b = "uname -a"
In [11]: a = !{b}
In [12]: a
Out[12]: [’Linux haso107d1 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux’]
If the exclamation mark precedes a command, it is passed to the OS.
12.5.2
bg
%bg func(a, b, c)
runs a command in a separate thread.
12.5.3
edit
%edit fname
edits a file or macro.
12.5.4
env
%env
displays the environment variables.
12.5.5
hist
%hist
shows the previous commands.
12.5.6
lsmagic
%lsmagic
lists the magic functions.
12.5.7
macro
%macro m1 2-10
makes the lines 2 to 10 a macro named m1. The line numbers can be found with %hist.
12.5.8
pdoc
%pdoc wa
prints the doc string of an object.
12.5.9
pdef
%pdef obj
prints the definition header of any callable object. For classes it prints the constructor information.
12.5.10
psource
%psource obj
prints the source code of an object.
12.5.11
pfile
%pfile obj
prints the entire source file where the object was defined.
12.5.12
quickref
%quickref
Quick reference card.
12.5.13
reset
%reset
remove all user defined names.
12.5.14
run
The run command executes a Python file and loads the variables into the current namespace.
In [10]: !cat file.py
#!/usr/bin/env python
a = 12
In [11]: run file.py
In [12]: a
Out[12]: 12
12.5.15
save
%save filename n1-n2 ...
saves commands to a file.
12.5.16
time
%time command
shows the execution time.
12.5.17
who
%who
12.5.18
whos
%whos
like whos but with extra information.
Chapter 13
Tango I/O Speed
In the chapter you find some scripts that measure the I/O time of Tango attribute readings. Results are given for local
and remote I/O.
13.1
Reading the Position Attribute
#!/usr/bin/env python
#
# this script reads the position of a motor 10000 times
# and measures the total time
#
# result: local I/O: 4 kHz, remote I/O: 2.2 kHz
#
import sys, time
import PyTango
#
try:
proxyMotor = PyTango.DeviceProxy( "haspp99:10000/p09/motor/d1.65")
except PyTango.DevFailed, e:
PyTango.Except.print_exception(e)
sys.exit()
n = 10000.
time_start = time.time()
for i in range(int(n)):
pos = proxyMotor.Position
time_diff = time.time() - time_start
print " %d position reads take %g sec" % ( int(n), time_diff)
#
#
#
#
#
from local host:
10000 position reads take 2.51724 sec
from remote host:
10000 position reads take 4.48184 sec
13.2
Reading the Counts Attribute
#!/usr/bin/env python
import sys, time
import PyTango
#
# this script reads the Counts attribute 10000 times
# and measures the total time
#
# result: local I/O: 5.4 kHz, remote I/O: 2.4 kHz
#
#
try:
proxyCounter = PyTango.DeviceProxy( "haspp99:10000/p09/counter/d1.32")
except PyTango.DevFailed, e:
PyTango.Except.print_exception(e)
sys.exit()
n = 10000.
time_start = time.time()
for i in range(int(n)):
counts = proxyCounter.Counts
time_diff = time.time() - time_start
print " %d counts reads take %g sec" % ( int(n), time_diff)
#
#
#
#
#
from local host:
10000 counts reads take 1.86422 sec
from remote host:
10000 counts reads take 4.1467 sec
13.3
Precise Cycle Times for Reading the Position and Counts
Below you find a script that uses a timer and a counter to make precise measurements of the cycle times (reading
position and counts). Figure 13.1 and 13.2 show the results for local and remote access. ’Remote’ means that the
python script runs on a PC with a different TangoDB.
#!/usr/bin/env python
import sys, time, math
import PyTango
import matplotlib
matplotlib.use( ’TkAgg’)
import matplotlib.pyplot as plt
import numpy as np
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
this script assumes that
- the counter channel is fed with a 1 MHz clock
- the counter is gated by the timer
this script executes 10000 cycles
- read the counter
- calculate the difference with the old counter reading
the counter reading gives us a precise time base
- read the position
results
- total time
- average cycle time
- maximum cycle time
- standard deviation
conclusion:
- the cycle time is consistent with the other examples
which execute single reads of the position and the counts
- the maximum cycle time is a bit larger for the remote access
and also the standard deviation
try:
proxyMotor = PyTango.DeviceProxy( "haso107d1:10000/p09/motor/d1.65")
proxyCounter = PyTango.DeviceProxy( "haso107d1:10000/p09/counter/d1.32")
proxyTimer = PyTango.DeviceProxy( "haso107d1:10000/p09/dgg2/d1.01")
except PyTango.DevFailed, e:
PyTango.Except.print_exception(e)
sys.exit()
proxyCounter.Reset()
proxyTimer.Stop()
proxyTimer.SampleTime = 1000
proxyTimer.Start()
nMax = 2000.
x = np.arange( 0.0, nMax, 1)
y = np.zeros( nMax)
n = 10000.
countsOld = 0.
diffMax = 0.
sum = 0.
sumq = 0.
time_start = time.time()
for i in range(int(n)):
counts = float(proxyCounter.Counts)
diff = counts - countsOld
if diff < nMax:
y[int(diff)] += 1
else:
y[int(nMax - 1)] += 1
sum += diff
sumq += diff*diff
if diff > diffMax:
diffMax = diff
countsOld = counts
pos = proxyMotor.Position
time_diff = time.time() - time_start
s = math.sqrt( (sumq - sum*sum/n)/(n-1))
print
print
print
print
print
#
#
#
#
#
#
#
#
#
#
#
#
#
#
" %d cycles (Position, Counts) take %g sec" % ( int(n), time_diff)
" Cycle time:"
" average %g msec " % (sum/n/1000.)
" max
%g msec" % (diffMax/1000.)
" std-dev %g msec" % ( s/1000.)
from local host:
10000 cycles (Position, Counts) take 4.71505 sec
Cycle time:
average 0.471522 msec
max
2.433 msec
std-dev 0.0736271 msec
from remote host:
10000 cycles (Position, Counts) take 8.7081 sec
Cycle time:
average 0.870914 msec
max
96.073 msec
std-dev 0.956201 msec
plt.plot( x, y, ’r’)
plt.ylabel( ’Frequency’)
plt.xlabel( ’Cycle time in micro-secs, local access’)
plt.show()
Figure 13.1: Tango I/O Cycle Time, Local Access
13.4
Position reading while the motor is moving
The following script demonstrates the jitter of the position reading of a moving motor. A motor (conversion = 4000)
is moved to a start position then to an end position. While the motor moves to the end position, the position attribute
is constantly read. The plots 13.3 and 13.4 show the distribution of the differences. Both distributions show a discrete
spectrum because out motor is a stepping motor and the slew rate is in the order of the loop cycle time.
What do we learn from these plots? Let’s assume that we want to open a shutter when the motor reaches a certain
position. Looking at 13.3 we see that we can do this with a position error of 0.001 units or better. Notice that the x-axis
is scaled. The value of 1000 corresponds to 0.001.
#!/usr/bin/env python
import sys, time, math
import PyTango
import matplotlib
matplotlib.use( ’TkAgg’)
import matplotlib.pyplot as plt
import numpy as np
try:
proxyMotor = PyTango.DeviceProxy( "haspp99:10000/p09/motor/d1.65")
Figure 13.2: Tango I/O Cycle Time, Remote Access
except PyTango.DevFailed, e:
PyTango.Except.print_exception(e)
sys.exit()
posStart = 0
posEnd = 10
#
# move to the start position
#
proxyMotor.Position = posStart
while proxyMotor.state() == PyTango.DevState.MOVING:
print "moving to start position %g/%g " % (proxyMotor.Position, posStart)
time.sleep(0.1)
nMax = 3000.
x = np.arange( 0.0, nMax, 1)
y = np.zeros( nMax)
n = 1000000.
posOld = proxyMotor.Position
proxyMotor.Position = 10
for i in range(int(n)):
pos = proxyMotor.Position
posDiff = pos - posOld
posOld = pos
#print " %d posDiff %g" % (i, posDiff)
posDiff *= 1000000.
if proxyMotor.state() == PyTango.DevState.ON:
print "Motor stopped aborting loop"
break
if int(posDiff) == 0:
continue
if posDiff < nMax:
y[int(posDiff)] += 1
else:
y[int(nMax - 1)] += 1
plt.figtext( 0.8, 0.8, "SlewRate: %d, Zeros are suppressed" % (proxyMotor.SlewRate), va=’cen
plt.plot( x, y, ’r’)
plt.ylabel( ’Frequency’)
plt.xlabel( ’Difference between consecutive position readings (*1E6)’)
plt.show()
Figure 13.3: Differences of the position reading, slew rate 4000
Figure 13.4: Differences of the position reading, slew rate 8000
Chapter 14
Examples
This chapter contains experiment control related Python examples. The Spock manual provides example code that
accesses the MacroServer.
14.1 Tango device access
14.1.1
Signal Generator as VcExecutor (with Offset, P09)
#!/bin/env python
#
# this Vc counter produces a Gauss peak, nPoint == 50
#
import HasyUtils
import random, math
class VC:
def __init__(self):
print " VC.init"
self.xMin = 0.
self.xMax = 50
self.width = 3.
self.height = 800.
self.x = 0.
self.x0 = 25.
self.count = 0
self.offset = 0.
#
# dev_state
#
def dev_state( self):
return self.proxies[0].State()
#
# Counts
#
def read_Counts( self):
self.x += 0.2
self.count += 1
if self.x >= self.xMax:
self.x = 0
self.x0 = random.random()*self.width + self.xMax/2.
self.height = 1000.*random.random() + 500.
temp = (self.x - self.x0)/self.width;
temp = self.height*math.exp( -temp*temp/self.width)
print "readCounts returns ", temp
return temp
def write_Counts( self, argin):
return 1
#
# Offset
#
def read_Offset( self):
return self.offset
def write_Offset( self, argin):
self.offset = argin
return 1
#
# reset
#
def Reset(self):
return True
14.1.2
VcExecutor reading a P201-9B Encoder via module serial (P02)
#!/bin/env python
#
import PyTango
import serial
class VC:
def __init__(self):
self.ser = serial.Serial(’/dev/ttyUSB0’)
def __del__(self):
self.ser.close()
def dev_state(self):
return PyTango.DevState.ON
def read_Counts(self):
val = 0
try:
self.ser.write(’?\r’)
#ser.write(’1111011101101001011101011011101100110000\r’)
val_bin = self.ser.read(41)
val_raw = int(val_bin[:26], 2)
val = val_raw*360. / 2**26
except Exception, e:
print "exception"
print e
val = -1
return val
def write_Counts(self, argin):
return 1
def Reset(self):
return True
14.1.3
Zugvorrichtung, P03 (argparse)
#!/usr/bin/env python
#
## script for BT Conrad S. - sweep scan using phyton
##
## usage:
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
1) adjust motors / devices acording to current device onnections
see line 128 (at moment) - proxy connects to tango devices
2) copy this script into "online" foler and make it
executable for P03user (i.e. as p03user do)
a) cp cs_sweep.py /gpfs/current/raw/online/
b) cd /gpfs/current/raw/online/
chmod u+x cs_sweep.py
4) script can now be excecuted from within online folder by
[from fresh terminal window: cd /gpfs/current/raw/online/ and then]
./cs_sweep.py [opt_args]
!!! Do NOT stop reading here !!!
The script writes its oputput into the directory from where it was called
with a filename having the extension ".dat"
When called without arguments, it takes the defaults defined in here,
e.g. for filename and motor movement ranges
The script can be called with optional args allowing to change the defaults
Note: You can pass one or multiple args.
If an argument is missing, the default is taken
Order of arguments doesn’t matter
Opt args are:
-p (or aquivalent --prefix):
the filename prefix for the output file
a 5 digit counter will be added automatically
-sx (or aquivalent --startX): the start position of 1st motor
-ex (or aquivalent --stopX):
the stop position of 1st motor
-sy (or aquivalent --startY): the start position of 2nd motor
-ey (or aquivalent --stopY):
the stop position of 2nd motor
-l (or aquivalent --loopMax): the maximum number of loops (before script
ends by itself)
-d (or aquivalent --debug):
NOT needed - just some additional screen
output I used when writing the stuff
Hence, script calls can be e.g. like this
./cs_sweep.py -p=dummy
(output file should be named dummy, i.e. dummy_<5 digit counter>.dat,
and defaults for all other actions implied)
or
./cs_sweep.py -p=dummy -l=3 -sx=2
(output file should be named dummy, number of loops should be 3 and
1st motor starting position to use is 2. defaults for all other actions implied)
or
./cs_sweep.py -p=dummy -l=2 -sx=2 -ex=4 -sy=3 -ey=6
(output file should be named dummy, number of loops should be 2,
1st motor should move from 2 to 4 and 2nd motor should move from 3 to 6.)
##
## The script runs until the max. number of loops defined is reached or
## can be stopped with the ’space bar’
##
##
## history
##
## ver 0.0 - the first - script for test environment
##
* T.K. + W.O. + A.R., Oct 14, 2016
##
## ver 0.1 - modifications according to P03 BL and enhancements, Oct 14, 2016 by A.R./FSEC
##
* argument parsing added
##
* shutter control added
##
* comments added
##
import time, sys
import PyTango
import HasyUtils
import argparse
class breakLoop( Exception): pass
## here we define the optional arguments and their defaults
## the --<name> defines the name of the variable used laten in the script
## e.g. --prefix results that a variable args.prefix exists
##
(args.prefix because of the args = parser.... call lateron)
parser = argparse.ArgumentParser(description=’CS sweep scan’)
parser.add_argument(’-p’,’--prefix’, type=str, default="cs_sweep_p03",
help=’the filename prefix for the output file (counter will be added)’)
parser.add_argument(’-l’,’--loopMax’, type=int, default=10,
help=’the maximum number of loops (defaults to 10)’)
parser.add_argument(’-sx’,’--startX’, type=int, default=0,
help=’the start position of 1st motor (exp_mot<NN>) (defaults to 0)’)
parser.add_argument(’-ex’,’--stopX’, type=int, default=1,
help=’the stop position of 1st motor (defaults to 1)’)
parser.add_argument(’-sy’,’--startY’, type=int, default=0,
help=’the start position of 2nd motor (exp_mot<NN>) (defaults to 0)’)
parser.add_argument(’-ey’,’--stopY’, type=int, default=-1,
help=’the stop position of 2nd motor (defaults to 0)’)
parser.add_argument(’-d’,’--debug’, type=int, default=0,
help=’a debug flag (defaults to 0)’)
args = parser.parse_args()
out = None
# print something to the screen if set
if args.debug == 1:
print "prefix: %s, startX: %g, stopX: %g, startY: %g, stopY: %g, loopMax: %g\n" % ( args
args.startX, args.stopX, args.startY,
args.stopY, args.loopMax)
## establish proxy connects to devices involved
## use motor 26 as X (still defined as diode_x in online as of Oct. 14)
## use motor 25 as Y (still defined as diode_y in online as of Oct. 14)
## assign ADCs 1 and 2 (for the 0-10V signals Conrad will provide)
## use P03 vfcadc01 (the diode on primary BS)
## use output register 1 ’oreg1 in online’, i.e. connected to fast shutter at momentt
## W.O. to adjust
##
try:
diode_x = PyTango.DeviceProxy( "p03/motor/expmi.26")
diode_y = PyTango.DeviceProxy( "p03/motor/expmi.25")
adc_kraft = PyTango.DeviceProxy( "p03/adc/exp.01")
adc_weg = PyTango.DeviceProxy( "p03/adc/exp.02")
i0 = PyTango.DeviceProxy( "p03/vfc/exp.01")
fshttr = PyTango.DeviceProxy( "p03/register/exp.out01")
except:
print "failed to create the proxies"
sys.exit( 255)
## definition to put single line to screen and into file
def recordData():
print "%g %g %g %g %g" % ( diode_x.position,
diode_y.position,
adc_kraft.value,
adc_weg.value,
i0.value)
out.write( "%g %g %g %g %g %f\n" % ( diode_x.position,
diode_y.position,
adc_kraft.value,
adc_weg.value,
i0.value, time.time()))
if HasyUtils.inkey() == 32:
return False
return True
## definition for call (moving into starting position)
##
def moveToStart():
if( diode_x.state() != PyTango.DevState.ON or
diode_y.state() != PyTango.DevState.ON):
print "state != ON"
return False
diode_x.position = args.startX
diode_y.position = args.startY
while( diode_x.state() == PyTango.DevState.MOVING or
diode_y.state() == PyTango.DevState.MOVING):
time.sleep(0.5)
print "moving to start", diode_x.position, diode_y.position
if HasyUtils.inkey() == 32:
print "terminated by space-bar"
return False
return True
## make use of hasyutils and create a decent filename from the prefix given
## this also adds the 5 digit counter
##
fName = HasyUtils.createScanName( args.prefix)
if args.debug == 1:
print "fName: %s\n" % ( fName)
## move to strating position or die
##
ret = moveToStart()
if not ret:
sys.exit( 255)
## create the output file (in the current directory)
##
out = open( fName + ".dat", "w")
out.write("!\n")
out.write("! Started at %s %f\n" % (HasyUtils.getDateTime(), time.time()))
out.write("! recording %s %s %s %s %s time\n" % (diode_x.name(),diode_y.name(),adc_kraft.nam
out.write("!\n")
## open the fast shutter (i.e. set register to low)
##
fshttr.value=0
## now loop until max num of loops is reached or space bar is pressed to abort
## data logging time reolution is currently 0.2s (I wouldn’t go too low,
## maybe down to 0.05 (?) you may try ....)
## W.O. to adjust
##
try:
for i in range( args.loopMax):
out.write( "! sweep %d\n" % i)
print "! sweep %d/%d \n" % (i, args.loopMax)
diode_x.position = args.stopX
diode_y.position = args.stopY
while( diode_x.state() == PyTango.DevState.MOVING or
diode_y.state() == PyTango.DevState.MOVING):
time.sleep(0.2)
if not recordData():
raise breakLoop
diode_x.position = args.startX
diode_y.position = args.startY
while( diode_x.state() == PyTango.DevState.MOVING or
diode_y.state() == PyTango.DevState.MOVING):
time.sleep(0.2)
if not recordData():
raise breakLoop
except breakLoop:
## close fast shutter
fshttr.value=1
print "The eagle has landed!"
## close file
##
out.close()
## close fast shutter (in case of normal termination and to be save at all)
##
fshttr.value=1
14.1.4
A VcExecutor returning a Tango attribute
This is virtual counter that returns the value of an attribute:
#!/usr/bin/env python
import PyTango
class VC:
def __init__(self):
print " VC.init"
self.proxies = []
# self.proxies.append( PyTango.DeviceProxy( "haso107klx:10000/p09/counter/exp.01"))
self.proxies.append( PyTango.DeviceProxy( "p09/counter/exp.01"))
#
# dev_state
#
def dev_state( self):
return self.proxies[0].State()
#
# Counts
#
def read_Counts( self):
print "vc_attribute:: read-counts "
return self.proxies[0].Counts
def write_Counts( self, argin):
return 1
#
# reset
#
def Reset(self):
#print "vc_attribute:: resetting ", self.proxies[0].name()
#self.proxies[0].Reset()
return True
The corresponding entry in online.xml is:
<device>
<name>exp_xattr</name>
<tags>expert,user</tags>
<type>counter</type>
<module>counter_tango</module>
<device>p09/vcexecutor/attribute.01</device>
<control>tango</control>
<hostname>haso107klx:10000</hostname>
</device>
Notice that this device was named ’exp xattr’ because it should appear in the list of counters behind, e.g., exp c32.
14.1.5
Virtual Motor as VMExecutor
This section demonstrates how to implement a virtual motor using the VmExecutor class.
One property is needed, e.g.:
VmCode
/home/p17user/prog/vm_1.py
This is the code itself.
#!/bin/env python
import PyTango
class VM:
#
# init_device
#
def __init__( self):
self.ResultSim = None
self.PositionSim = None
self.proxies = []
self.proxies.append( PyTango.DeviceProxy( "p17/motor/oh1.03"))
self.proxies.append( PyTango.DeviceProxy( "p17/motor/oh1.04"))
self.proxies.append( PyTango.DeviceProxy( "p17/motor/oh1.07"))
return
#
# dev_state
#
def dev_state( self):
argout = PyTango.DevState.ON
#
# if one device is in FAULT the VM is in FAULT too
#
for proxy in self.proxies:
if proxy.state() == PyTango.DevState.FAULT:
argout = PyTango.DevState.FAULT
break
if argout == PyTango.DevState.ON:
#
# if one device is MOVING the VM is MOVING too
#
for proxy in self.proxies:
if proxy.state() == PyTango.DevState.MOVING:
argout = PyTango.DevState.MOVING
break
return argout
#
# Position
#
def read_Position( self):
return self.proxies[0].read_attribute( "Position").value
def write_Position( self, argin):
if( argin < self.proxies[0].UnitLimitMin or
argin > self.proxies[0].UnitLimitMax):
PyTango.Except.throw_exception(
"vm1",
"requested position outside limits %g %g " % (self.proxies[0].UnitLimitMin, self.proxies[0].
"VmExecutor")
for proxy in self.proxies:
proxy.write_attribute( "Position", argin)
return 1
#
# UnitLimitMax
#
def read_UnitLimitMax( self):
return self.proxies[0].UnitLimitMax
def write_UnitLimitMax( self, argin):
self.UnitLimitMax = argin
#
# UnitLimitMin
#
def read_UnitLimitMin( self):
return self.proxies[0].UnitLimitMin
def write_UnitLimitMin( self, argin):
self.UnitLimitMin = argin
#
# CwLimit, CcwLimit
#
def read_CwLimit( self):
return self.proxies[0].CwLimit
def read_CcwLimit( self):
return self.proxies[0].CcwLimit
#
# PositionSim
#
def read_PositionSim( self):
if self.PositionSim is None:
PyTango.Except.throw_exception( "vm1", "PositionSim is undefined", "VmExecutor")
return self.PositionSim
def write_PositionSim( self, argin):
self.PositionSim = argin
self.ResultSim = []
self.ResultSim.append( "x: %g " % argin)
def read_ResultSim( self):
if self.ResultSim is None:
PyTango.Except.throw_exception( "vm1", "ResultSim is undefined", "VmExecutor")
return self.ResultSim
def StopMove( self):
for proxy in self.proxies:
proxy.StopMove()
return 1
14.1.6
A VmExecutor controlling a DAC
#!/usr/bin/env python
import PyTango
class VM:
#
# init_device
#
def __init__( self):
self.ResultSim = None
self.PositionSim = None
self.proxies = []
self.proxies.append( PyTango.DeviceProxy( "p23/dac/d1.01"))
return
#
# dev_state
#
def dev_state( self):
argout = PyTango.DevState.ON
#
# if one device is in FAULT the VM is in FAULT too
#
for proxy in self.proxies:
if proxy.state() == PyTango.DevState.FAULT:
argout = PyTango.DevState.FAULT
break
if argout == PyTango.DevState.ON:
#
# if one device is MOVING the VM is MOVING too
#
for proxy in self.proxies:
if proxy.state() == PyTango.DevState.MOVING:
argout = PyTango.DevState.MOVING
break
return argout
#
# Position
#
def read_Position( self):
return self.proxies[0].read_attribute( "Voltage").value
def write_Position( self, argin):
if( argin < self.proxies[0].VoltageMin or
argin > self.proxies[0].VoltageMax):
PyTango.Except.throw_exception(
"VmExecutor.DAC",
"requested position outside limits %g %g " % (self.proxies[0].VoltageMin,
self.proxies[0].VoltageMax),
"VmExecutor")
self.proxies[0].write_attribute( "Voltage", argin)
return 1
#
# UnitLimitMax
#
def read_UnitLimitMax( self):
return self.proxies[0].VoltageMax
def write_UnitLimitMax( self, argin):
self.proxies[0].write_attribute( "VoltageMax", argin)
#
# UnitLimitMin
#
def read_UnitLimitMin( self):
return self.proxies[0].VoltageMin
def write_UnitLimitMin( self, argin):
self.proxies[0].write_attribute( "VoltageMin", argin)
#
# CwLimit, CcwLimit
#
def read_CwLimit( self):
return 0
def read_CcwLimit( self):
return 0
#
# PositionSim
#
def read_PositionSim( self):
if self.PositionSim is None:
PyTango.Except.throw_exception( "VmExecutor.Dac", "PositionSim is undefined", "V
return self.PositionSim
def write_PositionSim( self, argin):
self.PositionSim = argin
self.ResultSim = []
self.ResultSim.append( "x: %g " % argin)
def read_ResultSim( self):
if self.ResultSim is None:
PyTango.Except.throw_exception( "VmExecutor.Dac", "ResultSim is undefined", "VmE
return self.ResultSim
def StopMove( self):
return 1
14.1.7
A VmExecutor controlling the setPoint
The following code can be a template for controlling the setpoint of a temperature controller.
#!/usr/bin/env python
import PyTango
class VM:
#
# init_device
#
def __init__( self):
self.ResultSim = None
self.PositionSim = None
self.UnitLimitMin = 0
self.UnitLimitMax = 500
self.proxies = []
self.proxies.append( PyTango.DeviceProxy( "hasXXX:10000/pXX/lks336heateroutput/lcx.01"))
return
#
# dev_state
#
def dev_state( self):
argout = PyTango.DevState.ON
#
# if one device is in FAULT the VM is in FAULT too
#
for proxy in self.proxies:
if proxy.state() == PyTango.DevState.FAULT:
argout = PyTango.DevState.FAULT
break
if argout == PyTango.DevState.ON:
#
# if one device is MOVING the VM is MOVING too
#
for proxy in self.proxies:
if proxy.state() == PyTango.DevState.MOVING:
argout = PyTango.DevState.MOVING
break
return argout
#
# Position
#
def read_Position( self):
return self.proxies[0].SetPoint
def write_Position( self, argin):
if( argin < self.proxies[0].UnitLimitMin or
argin > self.proxies[0].UnitLimitMax):
PyTango.Except.throw_exception(
"vm1",
"requested position outside limits %g %g " % (self.proxies[0].UnitLimitMin,
self.proxies[0].UnitLimitMax),
"VmExecutor")
self.proxies[0].SetPoint = argin
return 1
#
# UnitLimitMax
#
def read_UnitLimitMax( self):
return self.proxies[0].UnitLimitMax
def write_UnitLimitMax( self, argin):
self.UnitLimitMax = argin
#
# UnitLimitMin
#
def read_UnitLimitMin( self):
return self.proxies[0].UnitLimitMin
def write_UnitLimitMin( self, argin):
self.UnitLimitMin = argin
#
# CwLimit, CcwLimit
#
def read_CwLimit( self):
return 0
def read_CcwLimit( self):
return 0
#
# PositionSim
#
def read_PositionSim( self):
return 0
def write_PositionSim( self, argin):
pass
def read_ResultSim( self):
return ""
def StopMove( self):
return True
THe corresponding entry in online.xml is:
<device>
<name>exp_vm01</name>
<tags>expert,user</tags>
<type>type_tango</type>
<module>motor_tango</module>
<device>p09/vmexecutor/exp.01</device>
<control>tango</control>
<hostname>haso107klx:10000</hostname>
</device>
14.1.8
moveLowAcc.py, low acceleration moves
The following script demonstrates how to control moves which are executed with a very low acceleration. The problem
is that the de-acceleration lasts longer than 3s the Tango time-out. The problem is solved by monitoring the hardware
register contents. The call to GetStepRegister() invokes a check-motor-registers(). Yes, this script is a horrible hack.
Once the Oms server has been fixed in this respect, this example will be removed from the document.
#!/usr/bin/env python
#
# this script
# - executes a move with a motor
# - interrupts the movement
# - wait for the motion to be finished by looking at
#
the state() and the controller register
#
import time
import string
import sys
from PyTango import *
motorName = "someNode:10000:p19/motor/exp.65";
def execMove( proxy, pos):
proxy.Position = pos
stepsOld = None
count = 0
while 1:
print "state", proxy.state(), \
"Ctrl", proxy.StepPositionController, \
"Int", proxy.StepPositionInternal
if proxy.state() == DevState.ON:
if (not proxy.StepPositionController == proxy.StepPositionInternal) and \
(proxy.StepPositionController == stepsOld):
print "moveLowAcc: invoking check-motor-registers"
proxy.GetStepPosition()
return 1
stepsOld = proxy.StepPositionController
count += 1
if count == 10:
print "Calling stop move"
proxy.StopMove()
time.sleep(0.5)
proxy = DeviceProxy( motorName)
if len( sys.argv) == 1:
print " Position %g " % proxy.Position
sys.exit()
if len( sys.argv) != 2:
print "\n usage: ./moveLowAcc.py [pos]"
sys.exit()
pos = sys.argv[1]
execMove( proxy, float(pos))
print "motor position %g " % proxy.Position
14.1.9
move.py, performance test
The following script can be used to read the position of a motor or to make 10 moves, forth and back. The move speed
is measured by starting the script with the time command from a shell prompt:
$ time python move.py
#!/usr/bin/env python
import time, sys
import PyTango
proxy = PyTango.DeviceProxy( "someNode:10000/p03/smaractmotor/p03nano.01")
def move( pos):
proxy.position = float(pos)
while( proxy.state() == PyTango.DevState.MOVING):
time.sleep(0.01)
if len( sys.argv) == 1:
print " Position %g " % proxy.position
sys.exit()
if len( sys.argv) != 2:
print "\n usage: ./move.py [pos]"
sys.exit()
pos = float(sys.argv[1])
for i in range( 0, 10):
move( pos + 0.1)
print "motor position %g " % proxy.position
move(pos)
print "motor position %g " % proxy.position
14.1.10
Re-starting a device server using Starter
The following script stops the DGG2/PETRA-3 server and starts it.
#!/usr/bin/env python
import PyTango
import sys
import time
tangoHost = "hasppXX"
starterHost = "hasppXXeh1"
portNo = 10000
serverName = "DGG2/PETRA-3"
try :
starterProxy = PyTango.DeviceProxy( "//%s:%s/tango/admin/%s" % ( tangoHost, portNo, star
except :
print "Failed with exception !"
print sys.exc_info()[0]
exit
runningServers = starterProxy.command_inout("DevGetRunningServers", True)
if not serverName in runningServers:
print " %s not in runningServers" % serverName
sys.exit()
starterProxy.command_inout("DevStop", serverName)
while 1:
stoppedServers = starterProxy.command_inout("DevGetStopServers", True)
if serverName in stoppedServers:
break
print " %s stopped" % serverName
time.sleep(2)
starterProxy.command_inout("DevStart", serverName)
while 1:
runningServers = starterProxy.command_inout("DevGetRunningServers", True)
if serverName in runningServers:
break
print " %s started" % serverName
14.1.11
Counter and Timer
The following script shows how a counter and a timer are operated together:
• SampleTime is set to 1s.
• The counter es resetted (cleared).
• The timer is started.
• The script waits until the timer expires.
• The counter contents is displayed.
#!/usr/bin/env python
from PyTango import *
import time
try :
counter = DeviceProxy( "someHost:10000/p15/counter/exp.01")
timer = DeviceProxy( "someHost:10000/p15/timer/exp.01")
except :
print "Failed with exception !"
print sys.exc_info()[0]
exit
timer.SampleTime = 1.0
counter.Reset()
timer.Start()
while timer.state() == DevState.MOVING:
time.sleep(0.1)
print "remaining", timer.RemainingTime
print " counts ", counter.Counts
14.1.12
Motor attributes
The following example demonstrates how motor attributes are set to some default values:
#!/usr/bin/env python
from PyTango import *
def setDefaults( name):
defaults = {’Acceleration’: 10000,
’BaseRate’: 20,
’Conversion’: 1000,
’SettleTime’: 0.1,
’SlewRate’: 10000,
’SlewRateMax’: 1044000,
’SlewRateMin’: 0,
’StepBacklash’: 100,
’StepCalibration’: 0,
’StepCalibrationUser’: 0,
’StepLimitMax’: 500000,
’StepLimitMin’: -500000,
’UnitCalibration’: 0,
’UnitCalibrationUser’: 0}
dev = DeviceProxy( name)
try:
print "Device ", name
for key in defaults.keys():
print " ", key, " to ", defaults[ key]
attr = dev.read_attribute( key)
attr.value = defaults[ key]
dev.write_attribute( attr)
except DevFailed:
extype, value = sys.exc_info()[:2]
print "Failed with exception ", extype
for err in value:
print " reason ", err.reason
print " desc ", err.desc
print " origin ", err.origin
print " severity ", err.severity
sys.exit()
except:
print " Failed to access ", name
print sys.exc_info()[0]
sys.exit()
return 1
#
# ---- main
#
db = Database()
devices = db.get_device_exported( "*mot*")
for name in devices:
setDefaults( name)
14.1.13
hkl2Angles
The following script calculates the diffractometer angles from hkl.
#!/usr/bin/env python26
#
# usage: ./hkl2Angles.py 1 0 0
#
from PyTango import *
import sys
diff = DeviceProxy( "someHost:10000/test/e6c/diffrac")
dev = DeviceProxy( "someHost:10000/test/e6c/diffrac-sim-hkl")
diff.write_attribute( ’Simulated’, True)
dev.write_attribute( ’h’, float( sys.argv[1]))
dev.write_attribute( ’k’, float( sys.argv[2]))
dev.write_attribute( ’l’, float( sys.argv[3]))
angles = diff.read_attribute( "Angles")
print sys.argv
print angles.value
Output:
$ ./hkl2Angles.py 1 0 0
[’./hkl2Angles.py’, ’1’, ’0’, ’0’]
[[ 0.00000000e+00
0.00000000e+00
-9.00000000e+01
0.00000000e+00
[ 1.00000000e+00
0.00000000e+00
-9.00000000e+01
0.00000000e+00
[ 2.00000000e+00
0.00000000e+00
-9.00000000e+01
0.00000000e+00
[ 3.00000000e+00
0.00000000e+00
-9.00000000e+01
0.00000000e+00
[ 4.00000000e+00
0.00000000e+00
9.00000000e+01
0.00000000e+00
[ 5.00000000e+00
0.00000000e+00
9.00000000e+01
0.00000000e+00
[ 6.00000000e+00
0.00000000e+00
9.00000000e+01
0.00000000e+00
[ 7.00000000e+00
0.00000000e+00
9.00000000e+01
0.00000000e+00
[ 8.00000000e+00
0.00000000e+00
9.00000000e+01
0.00000000e+00
14.1.14
-9.34260863e+00
1.90908957e-33
-1.86852173e+01]
-1.70657391e+02
1.90908957e-33
1.86852173e+01]
9.34260863e+00 -1.80000000e+02
1.86852173e+01]
9.34260863e+00
1.80000000e+02
1.86852173e+01]
9.34260863e+00
1.90908957e-33
1.86852173e+01]
-9.34260863e+00 -1.80000000e+02
-1.86852173e+01]
-9.34260863e+00
1.80000000e+02
-1.86852173e+01]
-1.70657391e+02 -1.80000000e+02
1.86852173e+01]
-1.70657391e+02
1.80000000e+02
1.86852173e+01]]
Reading the gap, Tango7
The following code demonstrates how the undulator grap is read and how exceptions are printed in Tango7.
#!/usr/local/bin/python26
import time
from PyTango import *
proxy = DeviceProxy( "someHost:10000/someBL/attributemotor/gap")
time_max = -1
try:
for n in range( 1, 1000):
time_start = time.time()
pos = proxy.Position
print "%d pos %g readout time max %g " % (n, pos, time_max)
diff = time.time() - time_start
if( diff > time_max):
time_max = diff
time.sleep(1)
except DevFailed:
exctype , value = sys.exc_info()[:2]
print "Failed with exception ! " , exctype
for err in value:
print " reason" , err.reason
print " description" , err.desc
print " origin" , err.origin
print " severity" , err.severity
14.1.15
Events, motor position
The following lines show how a client can monitor a motor position using events. Before this script can be executed the
server has to be configured accordingly. A polling period has to be specified and e.g. the relative change that generates
the event. Both parameters can be set using jive. It is also necessary that the Events Notify Daemon is running.
#!/usr/bin/python
from PyTango import *
import time
class PyCallback:
def push_event( self, event):
if not event.err:
print event.attr_name, event.attr_value.value
else:
print event.errors
proxy = DeviceProxy( ’someHost:10000/p09/motor/exp.01’)
cb = PyCallback()
ev = proxy.subscribe_event( ’Position’, EventType.CHANGE, cb, [])
while 1:
time.sleep(0.1)
14.1.16
Attributes, ADC, DAC
The following script reads/writes the attributes of an ADC and a DAC. We assume that both devices are connected by
a cable. Note that we set the DAC voltage limits before we change the output voltage.
#!/usr/bin/python
from PyTango import *
import sys
import time
try :
dac1 = DeviceProxy( "someHost:10000/hires/exp/dac1")
adc1 = DeviceProxy( "someHost:10000/hires/exp/adc1")
dac1.VoltageMin = 0
dac1.VoltageMax = 10
dac1.Voltage = 3.5
print adc1.name(), ", attr:", attr.name, "=", adc1.value
except :
print "Failed with exception !"
print sys.exc_info()[0]
14.1.17
Commands and attributes, VFCADC
The following script shows how a VFCADC is operated. A DAC generates some voltage which is fed into the VFCADC. The VFC is gated by the timer t1. Note that gain, offset and polarity have to be set only once.
#!/usr/bin/python
from PyTango import *
import sys
import time
try :
dac1 = DeviceProxy( "someHost:10000/hires/exp/dac1")
vfc1 = DeviceProxy( "someHost:10000/hires/exp/vfc1")
t1
= DeviceProxy( "someHost:10000/hires/exp/t1")
#
# set the DAC output
#
dac1.voltage = 3.5
#
# Prepare the VFC. Gain, offset and polarity are memorized attributes.
# After they have been set once the are automatically written to the
# device when the server is initialized.
#
vfc1.Gain = 1
vfc1.SetGain()
vfc1.Offset = 0
vfc1.SetOffset()
vfc1.Polarity = 1
vfc1.SetPolarity()
#
# reset the VFC
#
vfc1.Reset()
#
# start the timer
#
t1.SampleTime = 0.5
t1.Start()
while( t1.Check()):
print " Timer: ", t1.Read()
time.sleep(0.1)
#
# read the VFC, notice that ’Value’ is normalized
# to the sample time whereas ’Counts’ not.
#
print " VFC, value ", vfc1.Value
print " VFC, counts ", vfc1.Counts
except :
print "Failed with exception !"
print sys.exc_info()[0]
14.1.18
Attributes, I/O Register, SIS3610
The following script shows how an input register senses the state of an output register.
#!/usr/bin/python
from PyTango import *
import sys
import time
try :
ireg1 = DeviceProxy( "someHost:10000/hires/exp/ireg1")
oreg1 = DeviceProxy( "someHost:10000/hires/exp/oreg1")
print "ireg1,
oreg1.Value =
print "ireg1,
oreg1.Value =
value ", ireg1.Value
1
value ", ireg1.Value
0
except :
print "Failed with exception !"
print sys.exc_info()[0]
14.1.19
Spectrum, MCA 8701
The following script shows how an MCA is operated. The timer is gating the ADC which feeds the MCA.
#!/usr/bin/env python
from PyTango import *
import sys
import time
try :
mca1 = DeviceProxy( "p09/mca/exp.01")
t1
= DeviceProxy( "p09/timer/exp.01")
#
# BankId can be 0 or 1
#
mca1.BankId = 0
t1.Stop()
mca1.Clear()
mca1.Start()
#
# start the timer
#
t1.SampleTime = 0.5
t1.Start()
while( t1.Check()):
print " Timer: ", t1.Read()
time.sleep(0.1)
mca1.Stop()
mca1.Read()
len = mca1.DataLength
print " Spectrum length ", len
attr = mca1.Data
for i in range(len):
if attr[i] > 0:
print i, ": ", attr[i]
except :
print "Failed with exception !"
print sys.exc_info()[0]
14.2
Tango database
14.2.1
Enable/disable simulation mode
The following script changes the SimulationMode property in the database. The new value is in effect, after the servers
have been restarted.
#!/usr/bin/python
#
# this script sets the SimulationMode property for all devices
# of the specified classes that belong to PETRA-3 servers. If the
# mode is not specified, the current value of the property is displayed
#
import string
from PyTango import *
classes = [ ’DGG2’, ’MCA8715’, ’OmsVme58’, ’SIS3610’,
’SIS3820’, ’TIP551’, ’TIP830u20’, ’VFCADC’]
db = Database()
if len( sys.argv) == 1:
print "\n usage: ./setSim.py [0|1]\n"
for clss in classes:
devices = db.get_device_name( clss + "/PETRA-3", clss)
for dev in devices:
print dev, "sim:", db.get_device_property( dev, [’SimulationMode’])
print "\n usage: ./setSim.py [0|1]\n"
sys.exit()
if (len( sys.argv) != 2) or (sys.argv[1] != ’0’ and sys.argv[1] != ’1’):
print "\n usage: ./setSim.py [0|1]\n"
sys.exit()
flag = string.atoi( sys.argv[1])
for clss in classes:
devices = db.get_device_name( clss + "/PETRA-3", clss)
for dev in devices:
db.put_device_property( dev,{’SimulationMode’: [ flag]})
print dev, db.get_device_property( dev, [’SimulationMode’])
14.2.2
Properties
The following scripts reads the list of device properties and prints the list of property/value pairs.
#!/usr/bin/python
from PyTango import *
db = Database()
name = "hires/exp/mot1"
#
# get the list of properties
#
b = db.get_device_property_list( name, ’*’)
#
# return a dictionary with properties and values
#
a = db.get_device_property( name, b)
for prop in a.keys():
print prop, ": ", a[ prop]
14.2.3
Change Many Motor Properties
The following lines demonstrate how to set the properties of the OmsVme58 devices for the (old) Vme58 cards:
#!/usr/bin/env python
import HasyUtils
for i in range( 1, 9):
HasyUtils.putDeviceProperty( ’p99/motor/eh2.%02d’ % i, ’AccuMax’, 33500000 )
HasyUtils.putDeviceProperty( ’p99/motor/eh2.%02d’ % i, ’AccuMin’, -33500000 )
HasyUtils.putDeviceProperty( ’p99/motor/eh2.%02d’ % i, ’Base’, 61440)
for
for
for
for
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
i in range( 9, 17):
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
i in range( 17, 25):
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
i in range( 25, 33):
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
i in range( 33, 41):
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
HasyUtils.putDeviceProperty(
14.2.4
’p99/motor/eh2.%02d’ % i, ’MaxVSerie’, 0)
’p99/motor/eh2.%02d’ % i, ’VmeCard’, 1)
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
%
%
%
%
%
i,
i,
i,
i,
i,
’AccuMax’, 33500000 )
’AccuMin’, -33500000 )
’Base’, 57344)
’MaxVSerie’, 0)
’VmeCard’, 1)
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
%
%
%
%
%
i,
i,
i,
i,
i,
’AccuMax’, 33500000 )
’AccuMin’, -33500000 )
’Base’, 53248)
’MaxVSerie’, 0)
’VmeCard’, 1)
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
%
%
%
%
%
i,
i,
i,
i,
i,
’AccuMax’, 33500000 )
’AccuMin’, -33500000 )
’Base’, 49152)
’MaxVSerie’, 0)
’VmeCard’, 1)
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
’p99/motor/eh2.%02d’
%
%
%
%
%
i,
i,
i,
i,
i,
’AccuMax’, 33500000 )
’AccuMin’, -33500000 )
’Base’, 45056)
’MaxVSerie’, 0)
’VmeCard’, 1)
Change other Properties of VME Devices
The following lines show how a property is set for various VME devices.
#!/usr/bin/env python
import HasyUtils
# SIS3610
for i in range( 1, 17):
HasyUtils.putDeviceProperty( ’p99/register/eh2.in%02d’ % i, ’VmeCard’, 1)
HasyUtils.putDeviceProperty( ’p99/register/eh2.out%02d’ % i, ’VmeCard’, 1)
# SIS3820
for i in range( 1, 33):
HasyUtils.putDeviceProperty( ’p99/counter/eh2.%02d’ % i, ’VmeCard’, 1)
# TIP551
for i in range( 1, 5):
HasyUtils.putDeviceProperty( ’p99/dac/eh2.%02d’ % i, ’VmeCard’, 1)
# TIP830
for i in range( 1, 9):
HasyUtils.putDeviceProperty( ’p99/adc/eh2.%02d’ % i, ’VmeCard’, 1)
# DGG2
for i in range( 1, 3):
HasyUtils.putDeviceProperty( ’p99/dgg2/eh2.%02d’ % i, ’VmeCard’, 1)
# MCA8715
for i in range( 1, 5):
HasyUtils.putDeviceProperty( ’p99/mca/eh2.%02d’ % i, ’VmeCard’, 1)
14.3 I/O
14.3.1
Single keystrokes, non-blocking
The following script shows how single keystrokes are read in a non-blocking mode.
#!/usr/bin/env python
import sys, termios
import __builtin__
def inkey():
if not ’inkeyInit’ in __builtin__.__dict__:
__builtin__.__dict__[’inkeyInit’] = 1
fd = sys.stdin.fileno()
old = termios.tcgetattr( fd)
new = termios.tcgetattr( fd)
new[3] = new[3] & ˜termios.ICANON & ˜termios.ECHO
#
# VMIN specifies the minimum number of characters to be read
#
new[6] [termios.VMIN] = 0
#
# VTIME specifies how long the driver waits for VMIN characters.
# the unit of VTIME is 0.1 s.
#
new[6] [termios.VTIME] = 1
termios.tcsetattr( fd, termios.TCSADRAIN, new)
sys.exitfunc = lambda: termios.tcsetattr( fd, termios.TCSADRAIN, old)
key = sys.stdin.read(1)
if( len( key) == 0):
key = -1
else:
key = ord( key)
return key
def main():
print "Press some keys, ’x’ terminates"
while True:
key = inkey()
if( key == ord( ’x’)): break
if( key != -1): print key
print "Bye"
if __name__ == "__main__":
main()
14.3.2
Socket I/O, Client/Server
The sockel class supports multiple connects from different clients.
#
# the class sockel in part of HasyUtils
#
class sockel( object):
"""
A socket server interface which has been created to handle connects
from Sardana macros to the SardanaMonitor and the message window.
The constructor checks for available ports in the range [port, port + 9]
"""
#
# one socket for the port, accept() generates new sockets
#
sckt = None
conCounter = 0
def __init__( self, host, port):
if sockel.sckt is None:
try:
sockel.sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except Exception, e:
print "socket() failed", e
sys.exit()
for i in range(10):
port += i
try:
sockel.sckt.bind((host, port))
except Exception, e:
print "bind() failed", e, ",trying next port"
continue
self.port = port
print "bind( %s, %d) ok" % (host, port)
sockel.sckt.listen(5)
break
else:
print "bind() failed"
sys.exit()
self.conn, addr = sockel.sckt.accept()
self.addr = addr
self.connNo = sockel.conCounter
sockel.conCounter += 1
def close( self):
#
# close the ’accepted’ socket only, not the main socket
# because it may still be in use by another client
#
if not self.conn is None:
self.conn.close()
def recv( self):
argout = None
try:
argout = self.conn.recv(1024)
except:
argout = None
return argout
def send( self, msg):
if self.conn is None:
return 0
argout = 0
try:
argout = self.conn.send( msg)
except:
self.conn = None
argout = 0
return argout
Here is a server utilizing the HasyUtils.sockel class. The function socketAcceptor is constantly waiting for new
connects. Threads are spawned for each client.
#!/usr/bin/env python
import HasyUtils
import thread
import os
PORT = 7650
def socketAcceptor():
# waits for new accepts on the original socket,
# receives the newly created socket and
# creates threads to handle each client separatly
while True:
s = HasyUtils.sockel( HasyUtils.getHostname(), PORT)
thread.start_new_thread( socketServer, (s, ))
def socketServer(s):
global msgBuf
while True:
msg = s.recv()
if msg is None:
print "received None, closing socket"
s.close()
break
if msg.find(’exit’) >= 0:
os._exit(1)
s.send( ">> %s" % msg.strip())
socketAcceptor()
An example client:
#!/usr/bin/env python
import socket
import sys
host = socket.gethostname()
port = 7650
sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#
# find the port where the server is accepting connects
#
for i in range(10):
try:
sckt.connect((host, port))
except Exception, e:
print "connect() failed", e
port += 1
continue
break
else:
print "connect() failed"
sckt.close()
sys.exit()
print "talking via port", port
sckt.send(’testMessage’)
data = sckt.recv(1024)
print ’Received’, repr(data)
sckt.close()
14.3.3
Socket I/O, Spectra
The following examples shows how a client connects to Spectra running in the asynchronous server mode on a remote
host.
#!/usr/bin/env python
import socket
hostname = ’hasXX’
portNo = 7777
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((hostname, portNo))
s.send(’*=2*3’)
data = s.recv(1024)
s.close()
print ’Received’, repr(data)
14.4
Miscellaneous
14.4.1
Catching a time-out
Here is an example for catching a time-out 11.7.
14.4.2
Catching a time-out, smart version
Here is an example for a smart time-out implementation. It is particularily needed, if sub-shells are involved.
#!/usr/bin/env python
import subprocess, time, sys
class Timeout(Exception): pass
def run(command, timeout=10):
’’’
code by flybywire, stackoverflow
’’’
proc = subprocess.Popen(command, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.PI
poll_seconds = .250
deadline = time.time()+timeout
while time.time() < deadline and proc.poll() == None:
time.sleep(poll_seconds)
if proc.poll() == None:
if float(sys.version[:3]) >= 2.6:
proc.terminate()
raise Timeout()
stdout, stderr = proc.communicate()
return stdout, stderr, proc.returncode
def doCheckHost( host):
’’’
we execute some command on a remote host and capture the output.
Since hosts may not reply, we need a time-out. The usual time-out
implementation (signal, alarm()) does not work for Popen()
’’’
com = [ "stat", "--format=’%Y’", "/online_dir/TangoDump.lis"]
try:
lst = run( com, timeout = 3)
except Exception, e:
print "Time-out for ", host
return None
return lst
def main():
for host in [’haspp98’, ’haspp99’]:
res = doCheckHost( host)
print "%s: %s" % (host, res)
if __name__ == ’__main__’:
main()
14.4.3
Ctrl-C Handling
#!/usr/bin/env python
import time
try:
while 1:
time.sleep( 0.5)
print "working"
except KeyboardInterrupt:
print "interrupted"
14.4.4
Exception handling
Here is an example of how to catch an exception and print the available information.
#!/usr/local/bin/python
import sys;
from PyTango import *
try:
mot = DeviceProxy( "notExist")
except DevFailed:
extype, value = sys.exc_info()[:2]
print "Failed with exception ", extype
for err in value:
print " reason ", err.reason
print " desc ", err.desc
print " origin ", err.origin
print " severity ", err.severity
sys.exit()
except:
print " Failed to access ", name
print sys.exc_info()[0]
sys.exit()
Here is an alternative method. It prints the exception to standard output:
#!/usr/local/bin/python
import sys;
from PyTango import *
try:
mot = DeviceProxy( "notExist")
except DevFailed, e:
Except.print_exception( e)
sys.exit()
except:
print " Failed to access ", name
print sys.exc_info()[0]
sys.exit()
14.4.5
Regular expressions
Section 3.4.3 contains an example for a regular expression.
14.4.6
yesno()
The following script shows how the user can be prompted for an answer.
#!/usr/bin/env python
import string
import sys
#
#
#
def yesno( prompt):
sys.stdout.write( prompt)
sys.stdout.flush()
answer = sys.stdin.readline().upper().strip()
if answer == ’Y’ or answer == ’YES’:
return 1
else:
return 0
if not yesno( "Do really want it"):
#
# nothing is executed
#
return
execute_critical_code()
14.4.7
Move all .cbf files in a directory to another directory
#!/usr/bin/env python
#
# mvAllFilesInDir.py
#
import os, sys, shutil
if len( sys.argv) != 3:
print "mvAllFiles.py <srcDir> <destDir>"
sys.exit(255)
srcDir = sys.argv[1]
destDir = sys.argv[2]
if not os.path.isdir( srcDir):
print "mvAllFiles.py: %s is not a directory" % srcDir
sys.exit(255)
if not os.path.isdir( destDir):
print "mvAllFiles.py: %s is not a directory" % destDir
sys.exit(255)
for file in os.listdir( srcDir):
if file.endswith( ".cbf"):
shutil.copy( "%s/%s" % (srcDir, file), "%s/%s" % (destDir, file))
if os.path.getsize( "%s/%s" % (srcDir, file)) != os.path.getsize( "%s/%s" % (destDir
print "%s/%s hasn’t been copied properly"
else:
os.remove( "%s/%s" % (srcDir, file))
print "move %s/%s to %s/%s ok" % (srcDir, file, destDir, file)
14.5 QtGui, QtCore
14.5.1
QMainWindow and QThread exchange signals
A QMainWindow and a QThread exchange signals.
#!/usr/bin/env python
#
# A QMainWindow uses a QThread to do some work
#
import sys
from PyQt4 import QtGui, QtCore
class WorkerThread(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def slotWork(self, i):
i = i + 1
print "worker.slotWork, emitting", i, ", finish at 5"
self.emit(QtCore.SIGNAL(’done(int)’), i)
if i == 5:
self.emit(QtCore.SIGNAL(’bye’))
def run(self):
#print ’Worker thread:’, self.currentThread()
print "Worker.run"
self.exec_()
def stop( self):
self.exit()
class MainWindow(QtGui.QMainWindow):
def __init__(self):
self.i = 1
QtGui.QMainWindow.__init__(self)
#print ’mainWindow.__init__:’, self.thread()
self.prepare()
self.connect(self.b1, QtCore.SIGNAL(’clicked()’),self.slotClicked)
self.connect(self.b2, QtCore.SIGNAL(’clicked()’),self.slotClose)
def prepare( self):
vbox = QtGui.QVBoxLayout()
self.b1 = QtGui.QPushButton(’Do %i’ % self.i)
self.b2 = QtGui.QPushButton(’Quit’)
vbox.addWidget( self.b1)
vbox.addWidget( self.b2)
w = QtGui.QWidget()
w.setLayout(vbox)
self.setCentralWidget( w)
def slotClicked(self):
self.emit(QtCore.SIGNAL(’work(int)’), self.i)
def slotDone(self, i):
self.i = i
self.b1.setText(’Do %i’ % self.i)
def slotClose( self):
self.close()
self.emit(QtCore.SIGNAL(’stop’))
def main(args):
app = QtGui.QApplication(sys.argv)
mw = MainWindow()
mw.show()
worker = WorkerThread()
app.connect(mw, QtCore.SIGNAL(’work(int)’), worker.slotWork)
app.connect(mw, QtCore.SIGNAL(’stop’), worker.stop)
app.connect(worker, QtCore.SIGNAL(’done(int)’), mw.slotDone)
app.connect(worker, QtCore.SIGNAL(’bye’), mw.slotClose)
#print ’Main thread:’, app.instance().thread()
worker.start()
app.exec_()
if __name__ == "__main__":
main(sys.argv)
14.5.2
QDialog callback launches QMainWindow
To demonstrate how a MainWindow can be opened/closed from the call-back function of a Dialog. The use case is the
SardanaMonitor IVP for CursorApp.
#!/usr/bin/env python
#
#
import sys
from PyQt4 import QtCore, QtGui
import time
i = 0
class mainWindow( QtGui.QMainWindow):
def __init__( self, parent):
QtGui.QMainWindow.__init__(self, parent)
self.b = QtGui.QPushButton("Hello",self)
self.b.clicked.connect( self.launch)
self.show()
def launch( self):
print "calling quit"
app.quit()
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
b = QtGui.QPushButton("ok",self)
self.resize( 100, 100)
b.clicked.connect( self.launch)
self.mw = None
def launch( self):
self.timer = QtCore.QTimer( self)
self.timer.timeout.connect( self.cb_timer)
self.timer.start(0)
def cb_timer( self):
global i
print "timer function", i
self.timer.start(1000)
if i == 5:
self.timer.stop()
return
if self.mw is None:
self.mw = mainWindow( self)
self.mw.b.setText( "Counter %d" % i)
i = i + 1
else:
self.mw.close()
self.mw = None
if __name__ == ’__main__’:
app = QtGui.QApplication(sys.argv)
d = Dialog()
d.exec_()
Chapter 15
Appendix
15.1
Pattern
15.1.1
Adapter
The Adapter pattern translates one interface to another.
#!/usr/bin/env python
class Animal(object):
def __init__( self, name):
self.name = name
def tellName( self):
print self.name,
class Dog( Animal):
def __init__( self, name):
Animal.__init__(self, name)
def bark(self):
print "wau"
class Cat(Animal):
def __init__( self, name):
Animal.__init__(self, name)
def miau(self):
print "miau"
class Adapter( object):
def __init__(self, obj, adaptedMethods):
self.obj = obj
self.__dict__.update( adaptedMethods)
def __getattr__( self, attr):
return getattr( self.obj, attr)
def main():
lst = []
dog = Dog( "Bello")
cat = Cat( "Seute")
lst.append( Adapter( dog, { ’make_noise’: dog.bark}))
lst.append( Adapter( cat, { ’make_noise’ : cat.miau}))
for i in lst:
i.tellName()
i.make_noise()
if __name__ == "__main__":
main()
15.1.2
Command
The following piece of code (source: en.wikipedia.org, modified) shows the basic components of the command pattern:
the client which prepares the command, the invoker which calls the command and the receiver which executes the
command:
#!/usr/bin/env python
class Invoker(object):
def __init__(self, flip_up_cmd, flip_down_cmd):
self.flip_up = flip_up_cmd
self.flip_down = flip_down_cmd
class Receiver(object):
def turn_on(self):
print "The light is on"
def turn_off(self):
print "The light is off"
class Client(object):
def __init__(self):
receiver = Receiver()
self._invoker = Invoker(receiver.turn_on, receiver.turn_off)
def switch(self, cmd):
cmd = cmd.strip().upper()
if cmd == "ON":
self._invoker.flip_up()
elif cmd == "OFF":
self._invoker.flip_down()
else:
print ’Argument "ON" or "OFF" is required.’
if __name__ == "__main__":
client = Client()
print "Switch ON test."
client.switch("ON")
print "Switch OFF test."
client.switch("OFF")
print "Invalid Command test."
client.switch("****")
15.1.3
Decorator
The first decorator example shows how a function is used to decorate a function.
#!/usr/bin/env python
def dec1(func):
"""A function decorator."""
def wrapper(*args, **kwargs):
print "before", func.__name__
return_value = func(*args, **kwargs)
print "after", func.__name__
return return_value
return wrapper
@dec1
def sum(a,b):
temp = a + b
print "sum", a,"+", b, ":", temp
return temp
result = sum(3, b=4)
print result
Output:
before sum
sum 3 + 4 : 7
after sum
7
The decorator dec2 wraps some code around the function sum.
class dec2(object):
"""A function decorator."""
def __init__( self):
self.func = None
def __call__( self, func):
self.func = func
return self.wrapper
def wrapper(self, *args, **kwargs):
print "before", self.func.__name__
return_value = self.func(*args, **kwargs)
print "after", self.func.__name__
return return_value
@dec2()
def sum(a,b):
return a+b
result = sum(3, b=4)
print result
15.1.4
Facade
The Facade pattern creates a simplified interface to some other code:
#!/usr/bin/env python
class Facade(object):
def start(self):
print "doing lots of complicated things to start"
def stop(self):
print "doing lots of complicated things to stop"
fac = Facade()
fac.start()
fac.stop()
15.1.5
Factory
The Shape class contains a factory function that returns objects of different classes.
#!/usr/bin/env python
class Color(object):
@staticmethod
def factory(type):
if type == "Red": return Red()
if type == "Blue": return Blue()
assert 0, "Bad color creation: " + type
class Red(Color):
def tell(self): print "Red "
class Blue(Color):
def tell(self): print "Blue "
def colorNameGen():
""" Generate color name strings: """
cols = Color.__subclasses__()
for type in cols:
yield type.__name__
colors = []
for i in colorNameGen():
colors.append( Color.factory(i))
for col in colors:
col.tell()
15.1.6
Functor (closure)
Functors are objects that can be called like a function. They are typically used as callback functions. And they typically
remember some value making the act as a closure.
#!/usr/bin/env python
class doSomethingWithAnInt(object):
def __init__( self, i):
self.i = i
def __call__( self):
print "frozen ", self.i
a = doSomethingWithAnInt(3)
a()
15.1.7
Iteration
This is a class that produces iterable objects:
class gen( object):
def __init__( self, n):
self.n_total = n
self.n = 0
def __iter__( self):
return self
def next( self):
if self.n < self.n_total:
temp = self.n
self.n += 1
return temp
else:
raise StopIteration()
g = gen(10)
print [n for n in g]
#
# prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#
The same can be achieved with a generator function:
def gen(n):
i = 0
while i < n:
yield i
i += 1
for i in gen(10):
print i
15.1.8
Observer
#!/usr/bin/env python
"""
the observer pattern defines a one-to-many relation between objects.
when the publisher changes stated, all the dependent object are notified.
"""
class Publisher(object):
def __init__(self):
self._observers = []
def register(self, observer):
if not observer in self._observers:
self._observers.append(observer)
def unregister(self, observer):
try:
self._observers.remove(observer)
except ValueError:
pass
def notify(self, modifier=None):
for observer in self._observers:
if modifier != observer:
observer.update(self)
# the publisher
class Data(Publisher):
def __init__(self, name=’’):
Publisher.__init__(self)
self.name = name
self.data = 0
def setData(self, data):
self.data = data
self.notify()
def getData(self):
return self.data
# the viewer objects
class HexDisplay(object):
def update(self, publisher):
print ’HexDisplay: Publisher %s has data 0x%x’ % (publisher.name, publisher.getData(
class DecimalDisplay(object):
def update(self, publisher):
print ’DecimalDisplay: Publisher %s has data %d’ % (publisher.name, publisher.getDat
def main():
data1 = Data(’Data 1’)
data2 = Data(’Data 2’)
display1 = DecimalDisplay()
display2 = HexDisplay()
data1.register(display1)
data1.register(display2)
data2.register(display2)
data2.register(display1)
print "Setting Data 1 = 10"
data1.setData(10)
print "Unregister HexDisplay from data1 and data2."
data1.unregister(display2)
data2.unregister(display2)
print "Setting Data 1 = 10"
data1.setData(10)
print "Setting Data 2 = 15"
data2.setData(15)
if __name__ == ’__main__’:
main()
15.1.9
Singleton
A Singleton pattern ensures that a class can have only one instance. Such classes are used to store global data. The
following code is copied from de.wikipedia.org.
#!/usr/bin/env python
class Singleton(object):
def __new__(type, *args):
if not ’_the_instance’ in type.__dict__:
type._the_instance = object.__new__(type)
return type._the_instance
def __init__(self):
if not ’_ready’ in dir(self):
self._ready = True
s1 = Singleton()
s2 = Singleton()
print "id(s1)", id( s1)
print "id(s2)", id( s2)
15.1.10
Strategy
The Strategy pattern helps fto implement different behavior for instances of a class.
#!/usr/bin/env python
#
class General(object):
def __init__( self, func = None):
if func:
self.execute = func
def execute( self):
print "General.execute"
def special1():
print "execute special1"
def special2():
print "execute special2"
gen0 = General()
gen1 = General( special1)
gen2 = General( special2)
gen0.execute()
gen1.execute()
gen2.execute()
15.1.11
Template
The Template pattern is used, if a class defers part of its functionality to a subclass.
#!/usr/bin/env python
class Doener(object):
def addSalat( self):
print "Adding salat"
def addSauce( self):
print "Adding sauce"
def addMeat( self):
self.selectMeat()
print "Adding :", self.meat
def make( self):
self.addSalat()
self.addSauce()
self.addMeat()
class ChickenDoener( Doener):
def selectMeat( self):
self.meat = "chicken"
d = ChickenDoener()
d.make()
Bibliography
[1] M. Ounsy, A. Buteau, V. Forchi, E. Taurel PyTango: Python bindings for Tango
[2] Mark Lutz, David Ascher, Learning Python, O’Reilly
Index
classmethod, 26
property, 27
staticmethod, 26
builtin , 9
builtins , 22
doc , 18
file , 18
name , 18
ADC, 114
argparse, 40
argv, 7
array, 13
breakLoop, 30
builtin, 9
capture shell output, 41
cbreak, 119
classes, 23
closure, 38, 131
cmp, 15
control statements, 28
Ctrl-C Handler, 123
DAC, 114
date, 77
decorator, 27, 129
dictionary, 16
environment variables, 68
events, 113
examples, 97
except, 82
exceptions, 82
exitfunc(), 75
factory, 130
files, 32
formatting strings, 11
from-import, 20
function
access(), 67
atoi(), 73
chdir(), 68
chr(), 35
commands.getoutput(), 41
dir(), 35
eval(), 36
exec(), 35
exitfunc(), 75
filter(), 38
find(), 73
float(), 37
getattr(), 36
gethostname(), 73
globals(), 36
hasattr(), 36
id(), 36
int(), 37
issubclass, 37
iter(), 37
lambda, 38
locals(), 38
localtime(), 77
lower(), 73
lstrip, 74
map(), 38
ord(), 35
os.getcwd(), 68
os.getenv(), 68
os.getpid(), 68
os.isatty(), 68
os.isdir(), 70
os.isfile(), 70
os.kill(), 68
os.listdir(), 69
os.mkdir(), 69
os.path.dirname(), 69
os.path.exists(), 69
os.path.getsize(), 70
os.path.isExecutable(), 70
os.popen(), 70
os.remove(), 71
os.rename(), 71
os.rmdir(), 71
os.system(), 71
os.walk(), 72
partition(), 74
range(), 39
replace(), 74
round(), 37
rpartition(), 74
rstrip, 74
setattr(), 36
sleep, 77
socket.gethostbyaddr(), 73
sort(), 39
sorted(), 39
split, 74
str(), 37
strip, 74
sys. getframe(), 75
sys.argv(), 75
sys.stdin.readlind(), 76
type(), 39
upper(), 73
Functions, 79
functor, 131
gap, 113
glob, 41
globals(), 9
hostname, 41, 73
identity, 36
if, 28
import, 20
inkey, 119
Input register, 115
ipython, 86
isatty(), 68
list, 13
locals(), 9
loops, 29
MCA 8701, 115
module
PrettyPrint, 72
random, 72
None, 28, 29
NoneType, 39
numpy
ellipsis, 64
slicing, 64
numpy.ndarray, 64
objects, 23
operators, 28
bit-manipulation, 10
expression, 10
Output register, 115
parameter
passing, 79
ping, 71
print, 32
print-function, 13
property, 26
PYTHONPATH, 75
raise, 82
regular expressions, 11
scope, 9
sets, 17
signal.alrm, 84
singleton, 133
SIS3610, 115
socket, 119, 122
sort, 15
sort(), 39
sorted(), 39
startup script, 7
startup scripts, 86
strategy, 133
string, 10
format, 32
subclass, 37
sys.argv, 7
sys.path, 75
Tango
Attributes, 114, 115
Commands, 114, 115
template, 134
threads, 76
time, 77
time-out, 84
traceback, 75, 82
print tb(), 78
truth, 29
try, 82
tuples, 17
unpack, 79
VFCADC, 114
vmstat, 15
walk, 72
while, 30
yesno, 124
yield, 131
zip, 15