Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

12/02/2018

Arista EOS - customized CLI

https://www.arista.com/assets/data/pdf/Whitepapers/Arista_EOS_parser.pdf

Arista EOS CLI is implemented in Python, so you can customize the CLI yourself. Of course it is limited to simple output instead of complicated contents.  

Step 1: Modify the CLI script

bn303.17:40:17#bash

Arista Networks EOS shell

[admin@bn303 ~]$ cd /usr/lib/python2.7/site-packages/CliPlugin/
[admin@bn303 CliPlugin]$ vi RoutingBgpShowCli.py
[admin@bn303 CliPlugin]$ sudo vi RoutingBgpCli.py

Step 2: save the new CLI script and load up during boot

copy the modified to /mnt/flash
the /usr/lib is file system in memory, unsustainable after reboot. 
vi /mnt/flash/rc.eos, so copy the save script to the location

11/29/2018

Python Notes (3) - Beautiful Python Code by Raymond Hettinger

https://www.youtube.com/watch?v=OSGv2VnC0go

Faster and prettier code:

1. Looping backwards
for color in reversed(colors):
    print color

2. Looping over collection and indices
for i, color in enumerate(colors):
    print i, ":", color

3. Zip of 2 lists
for name, color in zip(names, colors):
    print name, ":", color

! zip has higher memory req, prone to cache miss;
! in python 3.x, using izip instead of zip

4. Sorted list
for color in sorted(colors):
for color in sorted(colors, reverse=True):

def compare_length(c1, c2):
    if len(c1) < len(c2): return -1
    if len(c1) > len(c2): return 1
    return 0

for color in sorted(colors, cmp=compare_length):
for color in sorted(colors, key=len):

Looping over a dict with keys and values:
for k,v in d.items():     # req. memory to store list
for k,v in d.iteritems(): # use iterator instead of mem

Counting with dict
d ={}
for color in colors:
    d[color] = d.get(color, 0) + 1

d = defaultdict(int)
for color in colors:
    d[color] += 1

Grouping with dictionaries:
# group the list by length
names = ['Raymond', 'Rachel', 'Matthew', 'Roger', 'Betty']

#old
d = {}
for name in names:
    key = len(name)
    if key not in d:
        d[key] = []
    d[key].append(name)

#1
d = {}
for name in names:
    key = len(name)
    d.setdefault(key, []).append(name)

#2
d = defaultdict(list)
for name in names:
    key = len(name)
    d[key].append(name)

Function calls with keyword arguments
twitter_search('@obama', False, 20, True)

twitter_search('@obama', retweets=False, numtweets=20, 
               popular=True)


Packing/Unpacking = simultaneous state updates
x, y, dx, dy = ( x + dx *t,
                 y + dy *t,
                 influence(m,x,y),
                 influence(m,x,y))

Concatenating strings
', '.join(names)

Updating sequences
names = ['Raymond', 'Rachel', 'Matthew', 'Roger', 'Betty']

del names[0]
names.pop(0)
names.insert(0, 'mark')

#==>
names = deque(['Raymond', 'Rachel', 'Matthew', 'Roger', 'Betty'])

del names[0]
names.popleft()
names.appendleft('mark')

Python Notes (2)

1. Sort: 
  • sorted() vs list.sort()
    • Sorted() returns a new list vs list.sort() does in place. 
    • list.sort() only for list. But sorted() for all iterables. 
  • key function and (reverse=True)
  • Sorted by multiple elements, like by first item then 2nd. 
>>> p = [[1,2,3],[3,2,1],[2,4,6],[1,2,5],[1,3,7],[3,1,0],[1,7,2]]
>>> p.sort(key=lambda x:(x[0], x[2]))
>>> p
[[1, 7, 2], [1, 2, 3], [1, 2, 5], [1, 3, 7], [2, 4, 6], [3, 1, 0], [3, 2, 1]]
  • Sorted by reversed plus asc
>>> p = [[1,2,3],[3,2,1],[2,4,6],[1,2,5],[1,3,7],[13,1,0],[-1,7,2]]
>>> p.sort(key=lambda x:(-x[0], x[2]))
>>> p
[[13, 1, 0], [3, 2, 1], [2, 4, 6], [1, 2, 3], [1, 2, 5], [1, 3, 7], [-1, 7, 2]]


2. SET:

1) No duplicate
2) No order
3) Sets contain only hashable items, for __contain__ method
4) Sets have operator like "-"

_set = set([1,2,3,3]) # (1,2,3)


s1 = set([1,2,3,4])
s2 = set([2,3,5])

l1 = [1,2,3,4]
l2 = [2,3,5]
s1 - s2
set([1, 4])


l1 - l2
Error

3. Variable length arguments in function call

positional argument with unknown number of arguments
def __func__(*args):
    for count, item in enumerate(args):
        print '{0}. {1}'.format(count, thing)

named arguments
def __func__(**kwargs):
    for name, value in kwargs.items():
        print '{0} = {1}' % (name, value)

TCL:
proc __proc__ {first args} {}

4. How to re-import python module in interactive mode
>>> from myrange import *
>>> for i in myrange(1,3,1):
...     print i
...
1 <<<<< extra print out due to debug print
1
2

$ more myrange.py
class myrange:
    def __init__(self, start, end, step):
        self.start = start
        self.end = end
        self.step = step
        print self.step   <<<< need to remove this

Change the py file, and do 2 steps



>>> import myrange   <<< need to import module for reload()
>>> reload(myrange)
<module 'myrange' from 'myrange.py'>
>>> from myrange import *
>>> for i in myrange(1,3,1):
...     print i
...
1  <<<< corrected
2

5. Python class class/instance/internal variables

啥叫class/instance/internal variables? 
- classVar 是Object之间share,一个改,大家都改,也叫Static variable
- instanceVar,所以叫Self.instanceVar,就是object自己本地
- internal,就不说了

class Obj(object):
    classVar = [10,20,30]
    def __init__(self):
        self.instanceVar = [1,2,3]
        internalVar = [100,200,300]

o1 = Obj()
o2 = Obj()

o1.instanceVar.append(11)
o1.instanceVar.append(12)
o2.instanceVar.append(21)
o2.instanceVar.append(22)

print o1.instanceVar
print o2.instanceVar

o1.classVar.append(111)
o2.classVar.append(222)
print o1.classVar
print o2.classVar

Python Notes (1)

1. Python FAQ:
https://docs.python.org/2.7/faq/programming.html

2. Python module search path
https://docs.python.org/2.7/tutorial/modules.html#the-module-search-path

If you do an "import syslib", how does the python locate the library?


1. local directory <<<< surprised?!

2. PYTHONPATH

so if you have a locally mistaken syslib.py or syslib.pyc under the local directory, you gonna break this import. And if you see something wanky, print cmd.__file__ will be helpful (or cmd.__version__)


3. Python Set
https://docs.python.org/3/tutorial/datastructures.html#sets
  • {} and set() can be used to create set
  • But to create an empty one, must use set(), not {} which is to create a dictionary. 
  • set_ = {0}
4. 3 Ways to delete an element in a list
1) most efficient - del List[idx]
2) less efficient if need to have the element - List.pop(idx)
3) lest effificient - slice, List[:i] + List[i+1:]

5. Python reduce, filter
>>> l = [1,2,3,4]
>>> reduce( (lambda x,y: x*10+y), l)
1234
>>> reduce( (lambda x,y: x*100+y), l)
1020304
>>> l = range(1, 100, 5)
>>> l
[1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96]
>>> filter(lambda x:x%4, l)

[1, 6, 11, 21, 26, 31, 41, 46, 51, 61, 66, 71, 81, 86, 91]

6. Python Naming Convention

http://legacy.python.org/dev/peps/pep-0008/#code-lay-out
  • limit all lines to 79,docstring/comment to 72
class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
                color == 'red' and emphasis == 'strong' or
                highlight &gt; 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

  • Module: short, 
    • all-lower-case name, like pystock.py
  • Class: CapWords, like 
    • StockHist, StockInfo, StockERHist
  • Function: 
    • lower_case_with_underscore
  • Method and instance: 
    • lower_case_with_underscore
  • Constants: 
    • ALL_CAPITALS_WITH_UNDERSCORE
  • Internal attribute: 
    • _single_leading_underscore
    • NOT imported. 
  • empty sequence = FALSE, so 
    • YES: if not seq:... 
    • NO: if len(seq)
  • Attributes: 
    • self.lower_case_with_underscore



9/12/2018

Python Tips

1. Is vs ==, mutable and immutable
  • == is to compare value, is is compare address
    • == is to compare by calling object.__eq__()
  • list1 = list2, address is assigned, not value. need list1=list2[:]
>>> a = [1,2,3]
>>> id(a)
4463753048  <<<< address is 048
>>> a[0] = 11
>>> id(a)
4463753048
>>> a
[11, 2, 3]
>>> a.append(44)
>>> a
[11, 2, 3, 44]
>>> id(a)   <<<< can change item and append, address is same
4463753048
>>> b = a
>>> id(b)   <<<< list= is point to same address
4463753048
>>> b[0] = 111
>>> a
[111, 2, 3, 44]  <<<< change b = change a
>>> c = a[:]
>>> id(c)
4463919328
>>> c[0] = 1234
>>> a
[111, 2, 3, 44]
>>> b
[111, 2, 3, 44]
>>> c
[1234, 2, 3, 44]
>>>

2. keyword argument

>>> def ff(*args, **kwargs):
...     print args
...     print kwargs
...

>>> ff(1, '22', k1=333, k2='4444')

(1, '22')
{'k2': '4444', 'k1': 333}

>>> d = {'ka':'aaa', 'kb':123}

>>> ff(**d)
()
{'kb': 123, 'ka': 'aaa'}

3. Regexp \符号

https://docs.python.org/3/howto/regex.html

Remove全部的None-Alphanumeric char from string. 应该是

s = re.sub('\W', '', s)

还有记住以下的

\d, \D = [0-9]
\s, \S = [ \t\n\r\v\f]

\w, \W = alphanumeric,[0-9a-bA-Z_]

4. arstCli Script模版

from arstCliLib import *
import sys

dut = sys.argv[1]
openSshOnDut( dut )
setAccessMethod(dut, 'ssh')
cmd = ['show ip int brief | grep " 10\." | grep Vlan']
output = sendCmd(dut, cmd, prompt='enable', raw=True)

print '\n'.join(output)

[solomonyang@syscon] ~ $ python testCli.py
Traceback (most recent call last):
  File "testCli.py", line 4, in <module>
    from arstCliLib import *
ImportError: No module named arstCliLib

PATH=$PATH:$HOME/bin:$HOME/py
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/git/systest-infra/lib/
PYTHONPATH=$PYTHONPATH:$HOME/git/systest-infra/lib/

export PATH
export LD_LIBRARY_PATH
export PYTHONPATH

5. List vs Tuple, based on stackoverflow post

1. Literal/语法
>>> t = (1,2); l = [1,2]; t[1]; l[0]
2
1

2. Size/内存量,区别大概list +12%
>>> t = tuple(range(100000)); l =  list(range(100000)); t.__sizeof__(); l.__sizeof__()
800024
900088

3. Mutable vs Inmutable/可变 vs 不可变
>>> t = (1,2); l = [1,2]
>>> l[0] = 11; print l
[11, 2]
>>> t[0] = 11; print t
TypeError: 'tuple' object does not support item assignment

4. 都可以增加,但是不同,tuple += (3)是返回一个新的obj,而list.add()是改原来的
>>> t = (1,2); l = [1,2]; id(t); id(l); t+=(3,); l+=[3]; id(t); id(l); l.append(3); id(l)
4306859000 <<<<< t
4307014720 <<<<< 1, 都一个地址
4306913952 <<<<< t +=(3,),新地址
4307014720

4307014720

5. 因为不可变,所以tuple (1,2)可以是Dict[key]
>>> d = {}; d[t] = '1,2'
>>> d = {}; d[l] = '1,2'
TypeError: unhashable type: 'list'

6. 用途
比方说,(10,11)是个bookmark,第10页的第11行,一般没有必要改;而list of bookmark = [ (1,10), (10,11), (22, 1)] 

7. Tuple != constant list
http://news.e-scribe.com/397
但是这么了解哪,好像也撮合:-) 好像更多的是字面的了解,tuple = lightweight record,比方说:DB API's fetchmany() 返回的是List of tuple. 每个tuple是一个record,不能改其中一项,改了就没有意义了。

List vs Set

1. Literal/语法/内存量
>>> s = set(range(100000)); s.__sizeof__(); l = list(range(100000)); l.__sizeof__()
4194504

900088

2. Set没有Index, 没有重复,可以数学操作 &, -, ^
>>> s1=set(range(1,20,2)); s2=set(range(10,30)); print 's1->', s1; print 's2->', s2; print '-:', s1 - s2; print '&:', s1&s2; s1^s2
s1-> set([1, 3, 5, 7, 9, 11, 13, 15, 17, 19])
s2-> set([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])
-: set([1, 3, 9, 5, 7])
&: set([19, 17, 11, 13, 15])

set([1, 3, 5, 7, 9, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

5/11/2018

How to use python/yaml

import yaml
import sys

with open(sys.argv[1], 'r') as stream:
   try:
      paramDict = yaml.load(stream)
   except yaml.YAMLError as err:
      print(err)
      sys.ext(0)

print paramDict['Devices']['Switch']['mlagA']['Mgmt']['Host']

============
Devices:
   Switch:
      mlagA:                                 # MLAG Dut1
         Mgmt:                               
            Host: bn303
            AccessMethod:    ssh             # ssh or capi
            SshUsername:     admin           # default admin
            ChassisType:     modular         # fixed or modular
            CapiProtocol:    https

~/py @arst1.sjc> python test.py test.yaml

bn303