DFA 文字过滤替换

Posted on 2012年10月10日 23:55

 

#encoding=utf-8
#DFA based text filter
#author=sunjoy
#version=0.3
class GFW(object):
    def __init__(self):
        self.d = {}
    
    #give a list of "ming gan ci"
    def set(self,keywords):
        p = self.d
        q = {}
        k = ''
        for word in keywords:
            word += chr(11)
            p = self.d
            for char in word:
                char = char.lower()
                if p=='':
                    q[k] = {}
                    p = q[k]
                if not (char in p):
                    p[char] = ''
                    q = p
                    k = char
                p = p[char]
        
        pass
    
    def replace(self,text,mask):
        """
        >>> gfw = GFW()
        >>> gfw.set(["sexy","girl","love","shit"])
        >>> s = gfw.replace("Shit!,Cherry is a sexy girl. She loves python.","*")
        >>> print s
        *!,Cherry is a * *. She *s python.
        """
        p = self.d
        i = 0 
        j = 0
        z = 0
        result = []
        ln = len(text)
        while i+j<ln:
            #print i,j
            t = text[i+j].lower()
            #print hex(ord(t))
            if not (t in p):
                j = 0
                i += 1
                p = self.d
                continue
            p = p[t]
            j+=1
            if chr(11) in p:
                p = self.d
                result.append(text[z:i])
                result.append(mask)
                i = i+j
                z = i
                j = 0
        result.append(text[z:i+j])
        return "".join(result)
        
    def check(self,text):
        """
        >>> gfw = GFW()
        >>> gfw.set(["abd","defz","bcz"])
        >>> print gfw.check("xabdabczabdxaadefz")
        [(1, 3, 'abd'), (5, 3, 'bcz'), (8, 3, 'abd'), (14, 4, 'defz')]
        """
        p = self.d
        i = 0 
        j = 0
        result = []
        ln = len(text)
        while i+j<ln:
            t = text[i+j].lower()
            #print i,j,hex(ord(t))
            if not (t in p):
                j = 0
                i += 1
                p = self.d
                continue
            p = p[t]
            j+=1
            #print p,i,j
            if chr(11) in p:
                p = self.d
                result.append((i,j,text[i:i+j]))
                i = i+j
                j = 0
        return result
        
if __name__=="__main__":
    import doctest,sys
    doctest.testmod(sys.modules[__name__])
    

 

 

smallgfw: 一个基于DFA的敏感词检测和替换模块,用法如doctest所示。

>>> gfw = GFW()
>>> gfw.set(["sexy","girl","love","shit"])#设置敏感词列表
>>> s = gfw.replace("shit!,Cherry is a sexy girl. She loves python.","*")
>>> print s
*!,Cherry is a * *. She *s python. #屏蔽后的效果

>>> gfw = GFW()
>>> gfw.set(["abd","defz","bcz"])
>>> print gfw.check("xabdabczabdxaadefz") #检测敏感词的出现位置
[(1, 3, 'abd'), (5, 3, 'bcz'), (8, 3, 'abd'), (14, 4, 'defz')] #例如,(5, 3, 'bcz')表示下标5之后长度为3的子串

---

check 1 times
re cost: 0.0160000324249
smallgfw cost: 0.0160000324249
===================================
check 2 times
re cost: 0.0309998989105
smallgfw cost: 0.0
===================================
check 3 times
re cost: 0.047000169754
smallgfw cost: 0.0149998664856
===================================
check 4 times
re cost: 0.0629999637604
smallgfw cost: 0.0150001049042
===================================
check 5 times
re cost: 0.0789999961853
smallgfw cost: 0.0309998989105
===================================
check 6 times
re cost: 0.0780000686646
smallgfw cost: 0.0469999313354
===================================
check 7 times
re cost: 0.0940001010895
smallgfw cost: 0.0460000038147
===================================
check 8 times
re cost: 0.109999895096
smallgfw cost: 0.047000169754
===================================
check 9 times
re cost: 0.125
smallgfw cost: 0.0620000362396
===================================
check 10 times
re cost: 0.125
smallgfw cost: 0.077999830246
===================================
check 11 times
re cost: 0.172000169754
smallgfw cost: 0.0629999637604
===================================
check 12 times
re cost: 0.171999931335
smallgfw cost: 0.0780000686646
===================================
check 13 times
re cost: 0.18700003624
smallgfw cost: 0.077999830246
===================================
check 14 times
re cost: 0.18799996376
smallgfw cost: 0.0940001010895
===================================
check 15 times
re cost: 0.203000068665
smallgfw cost: 0.0929999351501
===================================
check 16 times
re cost: 0.219000101089
smallgfw cost: 0.109999895096
===================================
check 17 times
re cost: 0.233999967575
smallgfw cost: 0.108999967575
===================================
check 18 times
re cost: 0.25
smallgfw cost: 0.110000133514
===================================
check 19 times
re cost: 0.264999866486
smallgfw cost: 0.110000133514
===================================
check 20 times
re cost: 0.280999898911
smallgfw cost: 0.141000032425
===================================
replace 1 times
re cost: 0.0
smallgfw cost: 0.0150001049042
===================================
replace 2 times
re cost: 0.0309998989105
smallgfw cost: 0.0
===================================
replace 3 times
re cost: 0.0469999313354
smallgfw cost: 0.0160000324249
===================================
replace 4 times
re cost: 0.0620000362396
smallgfw cost: 0.0160000324249
===================================
replace 5 times
re cost: 0.0780000686646
smallgfw cost: 0.0309998989105
===================================
replace 6 times
re cost: 0.0789999961853
smallgfw cost: 0.0460000038147
===================================
replace 7 times
re cost: 0.0940001010895
smallgfw cost: 0.0469999313354
===================================
replace 8 times
re cost: 0.108999967575
smallgfw cost: 0.0469999313354
===================================
replace 9 times
re cost: 0.125
smallgfw cost: 0.0780000686646
===================================
replace 10 times
re cost: 0.141000032425
smallgfw cost: 0.0629999637604
===================================
replace 11 times
re cost: 0.155999898911
smallgfw cost: 0.0780000686646
===================================
replace 12 times
re cost: 0.156000137329
smallgfw cost: 0.077999830246
===================================
replace 13 times
re cost: 0.18799996376
smallgfw cost: 0.0780000686646
===================================
replace 14 times
re cost: 0.203000068665
smallgfw cost: 0.0939998626709
===================================
replace 15 times
re cost: 0.203000068665
smallgfw cost: 0.0940001010895
===================================
replace 16 times
re cost: 0.233999967575
smallgfw cost: 0.0939998626709
===================================
replace 17 times
re cost: 0.234000205994
smallgfw cost: 0.109999895096
===================================
replace 18 times
re cost: 0.25
smallgfw cost: 0.125
===================================
replace 19 times
re cost: 0.25
smallgfw cost: 0.125
===================================
replace 20 times
re cost: 0.296000003815
smallgfw cost: 0.125
===================================

 

psyco优化后

check 1 times
re cost: 0.0149998664856
smallgfw cost: 0.0
===================================
check 2 times
re cost: 0.0320000648499
smallgfw cost: 0.0
===================================
check 3 times
re cost: 0.0460000038147
smallgfw cost: 0.0
===================================
check 4 times
re cost: 0.0629999637604
smallgfw cost: 0.0
===================================
check 5 times
re cost: 0.0780000686646
smallgfw cost: 0.0160000324249
===================================
check 6 times
re cost: 0.077999830246
smallgfw cost: 0.0150001049042
===================================
check 7 times
re cost: 0.0940001010895
smallgfw cost: 0.0159997940063
===================================
check 8 times
re cost: 0.109000205994
smallgfw cost: 0.0159997940063
===================================
check 9 times
re cost: 0.125
smallgfw cost: 0.0150001049042
===================================
check 10 times
re cost: 0.125
smallgfw cost: 0.0320000648499
===================================
check 11 times
re cost: 0.139999866486
smallgfw cost: 0.0320000648499
===================================
check 12 times
re cost: 0.155999898911
smallgfw cost: 0.0310001373291
===================================
check 13 times
re cost: 0.171999931335
smallgfw cost: 0.0160000324249
===================================
check 14 times
re cost: 0.203000068665
smallgfw cost: 0.0149998664856
===================================
check 15 times
re cost: 0.219000101089
smallgfw cost: 0.0160000324249
===================================
check 16 times
re cost: 0.233999967575
smallgfw cost: 0.0160000324249
===================================
check 17 times
re cost: 0.233999967575
smallgfw cost: 0.0309998989105
===================================
check 18 times
re cost: 0.25
smallgfw cost: 0.0320000648499
===================================
check 19 times
re cost: 0.265000104904
smallgfw cost: 0.0309998989105
===================================
check 20 times
re cost: 0.28200006485
smallgfw cost: 0.0309998989105
===================================
replace 1 times
re cost: 0.0160000324249
smallgfw cost: 0.0150001049042
===================================
replace 2 times
re cost: 0.0159997940063
smallgfw cost: 0.0150001049042
===================================
replace 3 times
re cost: 0.0320000648499
smallgfw cost: 0.0149998664856
===================================
replace 4 times
re cost: 0.047000169754
smallgfw cost: 0.0
===================================
replace 5 times
re cost: 0.077999830246
smallgfw cost: 0.0
===================================
replace 6 times
re cost: 0.0940001010895
smallgfw cost: 0.0160000324249
===================================
replace 7 times
re cost: 0.0929999351501
smallgfw cost: 0.0160000324249
===================================
replace 8 times
re cost: 0.108999967575
smallgfw cost: 0.0
===================================
replace 9 times
re cost: 0.125
smallgfw cost: 0.0160000324249
===================================
replace 10 times
re cost: 0.141000032425
smallgfw cost: 0.0149998664856
===================================
replace 11 times
re cost: 0.15700006485
smallgfw cost: 0.0150001049042
===================================
replace 12 times
re cost: 0.171999931335
smallgfw cost: 0.0160000324249
===================================
replace 13 times
re cost: 0.18700003624
smallgfw cost: 0.0309998989105
===================================
replace 14 times
re cost: 0.18799996376
smallgfw cost: 0.0310001373291
===================================
replace 15 times
re cost: 0.218999862671
smallgfw cost: 0.0160000324249
===================================
replace 16 times
re cost: 0.21799993515
smallgfw cost: 0.0320000648499
===================================
replace 17 times
re cost: 0.233999967575
smallgfw cost: 0.0310001373291
===================================
replace 18 times
re cost: 0.25
smallgfw cost: 0.0309998989105
===================================
replace 19 times
re cost: 0.296999931335
smallgfw cost: 0.0320000648499
===================================
replace 20 times
re cost: 0.280999898911
smallgfw cost: 0.0310001373291
===================================

 

http://code.google.com/p/smallgfw/

使用DFA实现文字过滤

Posted on 2012年10月10日 23:38

DFA和文字过滤 


文字过滤是一般大型网站必不可少的一个功能,而且很多文字类网站更是需要。那么如何设计一个高效的文字过滤系统就是非常重要的了。 

文字过滤需求简要描述:判断集合A中哪些子集属于集合B,拿javaeye来说,如果用户发表一篇文章(集合A),我们需要判断这篇文章里是否存在一些关键字是属于集合B,B一般来说就是违禁词列表。 

看到这里,没有接触过的同学可能会想到contains,正则之类的方法,但是很遗憾,这些方法都是行不通的。唯一比较好的算法是DFA。 

一,DFA简介: 
学过编译原理的同学们一定知道,在词法分析阶段将源代码中的文本变成语法的集合就是通过确定有限自动机实现的。但是DFA并不只是词法分析里用到,DFA的用途非常的广泛,并不局限在计算机领域。 

DFA的基本功能是可以通过event和当前的state得到下一个state,即event+state=nextstate, 
我们来看一张到处都能找到的状态图: 


--------------------------------------- 

 
------------------------------------- 





大写字母是状态,小写字母是动作:我们可以看到S+a=U,U+a=Q,S+b=V等等。一般情况下我们可以用矩阵来表示整个状态转移过程: 
--------------- 
状态\字符  a       b 
S        U       V 
U        Q       V 
V        U       Q 
Q        Q       Q 

但是表示状态图可以有很多数据结构,上面的矩阵只是一个便于理解的简单例子。而接下来在本文提到的文字过滤系统中会使用另外的数据结构来实现自动机模型 

二,文字过滤 
在文字过滤系统中,为了能够应付较高的并发,有一个目标比较重要,就是尽量的减少计算,而在DFA中,基本没有什么计算,有的只是状态的转移。而要把违禁文字列表构造成一个状态机,用矩阵来实现是比较麻烦的,下面介绍一种比较简单的实现方式,就是树结构。 

所有的违禁词其本质来说是有ascii码组成的,而待过滤文本其本质也是ascii码的集合,比如说: 
输入是A=[101,102,105,97,98,112,110] 
违禁词列表: 
[102,105] 
[98,112] 
那么我们的任务就是把上面两个违禁词构造成一个DFA,这样输入的A就可以通过在这个DFA上的转移来实现违禁词查找的功能。 

树结构实现这个DFA的基于的基本方法是数组的index和数组value之间的关系(在双数组trie中同样是基于这一基本方法) 
那么102其实可以看作一个数组索引,而105是102这个索引指向的下一个数组中的一个索引,105后面没有值了,那就代表这个违禁词结束了。 

通过这样一种方式,就可以构造出一颗DFA的树结构表示。 

接着遍历输入文本中的每一个byte,然后在DFA中作状态转移就可以判断出一个违禁词是否出现在输入文本中。 

 

#encoding:UTF-8
import sys
from time import time
'''
@author: ahuaxuan 
@date: 2009-02-20
'''

wordTree = [None for x in range(256)]
wordTree.append(0)
nodeTree = [wordTree, 0]
def readInputText():
    txt = ''
    for line in open('text.txt', 'rb'):
        txt = txt + line
    return txt

def createWordTree():
    awords = []
    for b in open('words.txt', 'rb'):
        awords.append(b.strip())
    
    for word in awords:
        temp = wordTree
        for a in range(0,len(word)):
            index = ord(word[a])
            if a < (len(word) - 1):
                if temp[index] == None:
                    node = [[None for x in range(256)],0]
                    temp[index] = node
                elif temp[index] == 1:
                    node = [[None for x in range(256)],1]
                    temp[index] = node
                
                temp = temp[index][0]
            else:
                temp[index] = 1
    

def searchWord(str):
    temp = nodeTree
    words = []
    word = []
    a = 0
    while a < len(str):
        index = ord(str[a])
        temp = temp[0][index]
        if temp == None:
            temp = nodeTree
            a = a - len(word)
            word = []
        elif temp == 1 or temp[1] == 1:
            word.append(index)
            words.append(word)
            a = a - len(word) + 1 
            word = []
            temp = nodeTree
        else:
            word.append(index)
        a = a + 1
    
    return words

if __name__ == '__main__':
    #reload(sys)  
    #sys.setdefaultencoding('GBK')  
    input2 = readInputText()
    createWordTree();
    beign=time()
    list2 = searchWord(input2)
    print "cost time : ",time()-beign
    strLst = []
    print 'I have find some words as ', len(list2)
    map = {}
    for w in list2:
        word = "".join([chr(x) for x in w])
        if not map.__contains__(word):
            map[word] = 1
        else:
            map[word] = map[word] + 1
    
    for key, value in map.items():
        print key, value

 

输入文本就是本文(不包含下面的示例结果文本) 
运行结果示例: 


  1. python 5  
  2. 违禁词 12  
  3. DFA 12  
  4. ahuaxuan 3  

       当然用python实现以上算法只是为了便于理解,事实上python的速度实在是太慢了,同样的违禁词列表,同样的输入文本,python写的比用java写的差了40倍左右。理论上来讲在这个功能上,用python调用c写的功能比较合适。 


而这种方式比较大的缺点是内存使用虑较大,因为有很多数组上的元素是None,引用的空间会消耗大量的内存,这个和违禁词的长度和个数成正比。比较好的方式还是用双数组实现DFA,这个方式使用内存空间较小,而基本原理还是一样,通过两个数组的index和value之间的数学关系来实现状态机的转移。 

附件中附带违禁词和输入文本的测试,大家可以运行一下看看效果。

 

文章出处:http://ahuaxuan.iteye.com/blog/336577?page=4#comments

优先队列

Posted on 2012年9月26日 19:00
#!/usr/bin/env python3
import queue
import threading

class Job():
    def __init__(self, priority, description):
        self.priority = priority
        self.description = description
        print("New job:", description)

    def __lt__(self, other):
        return self.priority < other.priority

q = queue.PriorityQueue()
q.put(Job(3, "Mid-level job"))
q.put(Job(10, "Low-level job"))
q.put(Job(1, "Important job"))

def process_job(q):
    while True:
        next_job = q.get()
        print("Processing job:", next_job.description)
        q.task_done()

workers = [threading.Thread(target=process_job, args=(q,)),
           threading.Thread(target=process_job, args=(q,)),
          ]

for w in workers:
    w.setDaemon(True)
    w.start()

q.join()

difflib

Posted on 2012年9月24日 16:12

difflib是python提供的比较序列(string list)差异的模块。

实现了三个类:
1>SequenceMatcher 任意类型序列的比较 (可以比较字符串)
2>Differ 对字符串进行比较
3>HtmlDiff 将比较结果输出为html格式.


Library Example - re

Posted on 2012年9月17日 19:54

一、查找文本中的模式

#!/usr/bin/env python3
import re

pattern = "this"
text = "Does this text match the pattern?"

match = re.search(pattern, text)

s = match.start()
e = match.end()

print('Found "{0:s}"\nin "{1:s}"\nfrom {2:d} to {3:d} ("{4:s}")'.format(
     match.re.pattern, match.string, s, e, text[s:e]))

 

二、编译表达式

#!/usr/bin/env python3
import re

# Precompile the patterns
regexes = [ re.compile(p) 
            for p in ["this", "that"]
          ]

text = "Does this text match the pattern?"

print("Text: %r\n".format(text))

for regex in regexes:
    print("Seeking \"%s\" -> ".format(regex.pattern), end='')

    if regex.search(text):
        print("Match")
    else:
        print("No Match")

三、多重匹配

findall()函数返回输入中与模式匹配而不重叠的所有子串

#!/usr/bin/env python3
import re

text = "abbaaabbbaaaaa"
pattern = "ab"

for match in re.findall(pattern, text):
    print("Found \"{0}\"".format(match))

Found "ab"
Found "ab"

finditer()返回一个迭代器,它将生成Match实例

#!/usr/bin/env python3
import re

text = "abbaaabbbbaaaa"
pattern = "ab"

for match in re.finditer(pattern, text):
    s = match.start()
    e = match.end()
    print("Found \"{0}\" at {1:d}:{2:d}".format(text[s:e], s, e))

Found "ab" at 0:2
Found "ab" at 5:7
 

四、模式语法

#!/usr/bin/env python3
import re

def test_patterns(text, patterns=[]):
    """Given source text and a list of patterns, look for
    matches for each pattern within the text and print
    then to stdout
    """
    # Look for each pattern in the text and print the results
    for pattern, desc in patterns:
        print("Pattern {0!r} ({1})\n".format(pattern, desc))
        print("  {0!r}".format(text))
        for match in re.finditer(pattern, text):
            s = match.start()
            e = match.end()
            substr = text[s:e]
            n_backslashes = text[:s].count('\\')
            prefix = '.' * (s + n_backslashes)
            print("  {0}{1!r}".format(prefix, substr))
        print()
    return

if __name__ == "__main__":
    test_patterns('abbaaabbbbaaaaa',
                  [('ab', "'a' followd by 'b'"),])

    test_patterns('abbaabba',
        [('ab*',      'a followed by zero or more b'),
         ('ab+',      'a followed by one or more b'),
         ('ab?',      'a followed by zero or one b'),
         ('ab(3)',    'a followed by three b'),
         ('ab(2, 3)', 'a folloed by two to three b')])

Pattern 'ab' ('a' followd by 'b')

  'abbaaabbbbaaaaa'
  'ab'
  .....'ab'

Pattern 'ab*' (a followed by zero or more b)

  'abbaabba'
  'abb'
  ...'a'
  ....'abb'
  .......'a'

Pattern 'ab+' (a followed by one or more b)

  'abbaabba'
  'abb'
  ....'abb'

Pattern 'ab?' (a followed by zero or one b)

  'abbaabba'
  'ab'
  ...'a'
  ....'ab'
  .......'a'

Pattern 'ab(3)' (a followed by three b)

  'abbaabba'

Pattern 'ab(2, 3)' (a folloed by two to three b)

  'abbaabba'
 

注:如果需要非贪婪模模式,请在模式元字符后面加问好(?)

 

字符集

字符集(character set)是一组字符,包含可以与模式中相应位置匹配的所有字符,例如[ab]可以匹配a或b

test_patterns(
        'abbaabbba',
        [
            ("[ab]",    "either a or b"),
            ("a[ab]+",  "a followed by 1 or more a or b"),
            ("a[ab]+?", "a followed by 1 or more a or b, not greedy"),
        ]
    )

Pattern '[ab]' (either a or b)

  'abbaabbba'
  'a'
  .'b'
  ..'b'
  ...'a'
  ....'a'
  .....'b'
  ......'b'
  .......'b'
  ........'a'

Pattern 'a[ab]+' (a followed by 1 or more a or b)

  'abbaabbba'
  'abbaabbba'

Pattern 'a[ab]+?' (a followed by 1 or more a or b, not greedy)

  'abbaabbba'
  'ab'
  ...'aa'

with 上下文管理器

Posted on 2012年8月31日 01:04
#!/usr/bin/env python3

class ListTransaction:
    
    def __init__(self, theList):
        self.theList = theList

    def __enter__(self):
        self.workingcopy = list(self.theList)
        return self.workingcopy

    def __exit__(self, type, value, tb):
        if type is None:
            self.theList[:] = self.workingcopy
        return False

 

#!/usr/bin/env python3

from contextlib import contextmanager

@contextmanager
def ListTransaction(thelist):
    workingcopy = list(thelist)
    yield workingcopy
    # only do not raise error 
    thelist[:] = workingcopy

python的文件锁

Posted on 2012年6月24日 19:27



"""
文件锁测试
"""

import fcntl
import time

fp = open('hello.txt','w')
fcntl.flock(fp, fcntl.LOCK_EX)
print '文件锁开始执行'
time.sleep(100)
fcntl.flock(fp, fcntl.LOCK_UN)
fp.close()

jinjia2 中文文档

Posted on 2012年5月29日 00:44

补充:

1. 在模板中设置自定义变量:

    {% set variable_name = value %}

   比如设置{% set username = 'Jack' %}

  那么在设置之后就可以使用{{ username }}得到输出Jack

 

 

 

section 1 API

1 jinja2的Hello world:

import jinja2 as jj

template = jj.Template(‘Hello {{where}}’)

template.render(where = ‘World’)

基础:

2.1 jinja2中有一个核心对象: template Environment(模板环境), 这个类的实例被用于存储配置信息, 全局对象, 从文件系统或其他位置加载模板, 甚至如果你使用Template的构造器创建一个String类型的模板的时候, 也会自动的创建一个Environment对象.

2.2 Environment一般在一个应用中只创建一个, 当系统中有不同的配置需求的时候, 就需要创建多个Environment对象相互支持.

创建一个Environment对象: env = Environment(loader = FileSystemLoader(‘templates’))…意思是创建一个template Environment对象, 使用的加载器loader是FileSystemLoader类型, 可以加载的模板是当前工作目录下的templates目录下的模板文件.

加载一个模板: template = env.get_template(‘mytemplate.txt’), 使用env的模板环境加载名为mytemplate.txt的模板文件.

渲染一个模板: template.render(name = ‘Jack’), 渲染模板template, 传入了模板参数name值为Jack

高级api

3.1 class Environment(block_start_string = ‘{%’, block_end_string = ‘%}’, variable_start_string = ‘{{’, variable_end_string = ‘}}’, comment_start_string = ‘{#’, comment_end_string = ‘#}’, line_statement_prefix = None, trim_blocks = False, extensions = (), optimized = True, undefined = <class ‘jinja2.runtime.Undefined’>, finalize = None, autoescape = False, loader = None, cache_size = 50, auto_reload = True):  下面单独列出的属性解释不都是构造器中的参数

3.1.1 block_start_string = ‘{%’, block_end_string = ‘%}’, variable_start_string = ‘{{’, variable_end_string = ‘}}’, comment_start_string = ‘{#’, comment_end_string = ‘#}’用来定义块, 变量, 注释的开始和结束标记.

3.1.2 line_statement_prefix: 单行语句前缀

3.1.3 trim_blocks: 布尔值, 块后面的第一行将会被移除(块, 非变量标签), 默认是False

3.1.4 extensions: Jinja的扩展对象列表, 可以是导入路径的字符串或扩展类

3.1.5 optimized: 布尔值, 表明优化是否允许.

3.1.6 undefined: jinja2.runtime.Undefined或其子类的实例, 用来描绘模板中的值为undefined的变量

3.1.7 finalize: 一个可调用对象, 用来最终确定一个变量, 默认使用apply, 需要HTML转码时可以设置为escape

3.1.8 autoescape: 设置为true就打开了XML/HTML的自动escape功能

3.1.9 cache_size: 缓存大小, 默认50, 意思是如果有超过50个模板被加载器加载, 就会清理刚刚使用过的模板.  如果设置为0, 表示所有的模板都会被重编译, 也就是不使用缓存, 如果设置为-1, 表示缓存不会被清理.

3.1.10 auto_reload: 如果模板的文件发生了变化, 加载器会重新编译该模板进行加载.

3.1.11 shared: 使用Template的构造器创建一个模板的时候, 会自动的创建一个Environment对象, 这个Environment对象就是一个共享的Environment对象, 很多模板都共享着同一个匿名Environment对象, 对于共享Environment对象而言, shared属性为True, 其他情况都是False

3.1.12 sandboxed: SandboxedEnvironment的实例对象此属性为True

3.1.13 filters: 一个字典描述的filters过滤器集合, 如果非模板被加载的时候, 可以安全的添加filters或移除较早的.

3.1.14 tests: 一个字典描述的测试函数集合, 如果非模板被加载, 可以安全的修改这个字典.

3.1.15 globals: 一个字典描述的全局变量集合, 这些变量可以在所有的模板中使用, 并且不能被模板重写(如果optimizer设置为允许). 如果非模板被加载, 它可以安全的修改这个字典.

3.1.16 from_string(source, globals = None, template_class = None): 从一个字符串加载一个模板, 将source指定的字符串转换成一个模板对象.   该方法是一个实例方法

3.1.17 join_path(template, parent): 不知道用途. 联接一个模板和父模板.  通过默认的查找查找关联的根, 这个方法返回没有修改过的template参数, 但是, 如果paths可以随父模板改变, 这个函数就可以用来得到模板的真实名称.(模板父名称+模板名称???), 子类可以重写这个方法实现自己的模板路径联接

3.1.18 get_template(name, parent = None, globals = None): 加载一个模板, 如果parent参数不是None, 会调用join_path()方法得到模板的真实名称在加载之前.  如果加载器配置了这个方法就会加载name指定的模板.  globals参数用来提供编译时的全局模板参数, 未来可能会允许优化的渲染templates的部分在编译时……….编译不允许有TemplateNotFound异常

3.1.19 overlay(block_start_string = missing, block_end_string = missing, variable_start_string = missing, variable_end_string = missing, comment_start_string = missing, comment_end_string = missing, line_statement_prefix = missing, trim_blocks = missing, extensions = missing, optimized = missing, undefined = missing, finalize = missing, autoescape = missing, loader = missing, cache_size = missing, auto_reload = missing):  获取一个新的Environment, 该对象继承获得所有当前Environment对象的配置属性, 调用此方法传递的参数会覆盖原有的配置属性.

3.2 class Template(): 核心的模板对象, 用来提供使用构造器创建模板对象, 构造器参数和Environment的相同, 但是不能提供loader, 使用构造器创建的模板对象有一个临时的Environment对象, 这个对象和所有其他使用构造器创建的Template共享.   下面介绍Template中的主要成员:

3.2.1 globals: 模板中使用的全局变量???

3.2.2 name: 返回加载模板时指定的名称(如果是FileSystemLoader加载的, 会返回文件名.)

3.2.3 render(*args, **kwargs): 接受关键字参数或字典作为参数.  返回渲染模板的结果字符串

3.2.4 stream(*args, **kwargs): 接受参数同上, 返回一个TemplateStream对象, TemplateStream做类似生成器的工作.

3.2.5 generate(*agrs, **kwargs): 对于很大的模板, 使用generate接口并不会一次渲染整个模板, 而是返回一个生成器, 每次next的时候, 使用yield方式生成一个模板片段.

3.2.6 module: 是一个TemplateModule对象, 该对象对用于运行时导出模板变量.例如:

t = Template(“{% macro foo() %}42{% endmacro %}”)

t.module.foo()就会返回42

3.2.7 make_module(vars = None, shared = False): 不传递参数相当于module属性.  传递参数功能未知.

3.3 class TemplateStream(gen): 一个模板流, 和python的生成器工作原理基本相同, 但是, 这里可以通过更多项的缓存, 以减少迭代次数., 默认是不支持缓存的, 可以通过enable_buffering()开启缓存

3.3.1 disable_buffering(): 展示输出缓存

3.3.2 enable_buffering(size = 5): 开启缓存, 缓存的项数默认是5, 缓存发生的时机在yielding之前

4 Undefined Types: Environment的构造器中提供了设置接口, 如果在模板中查找不到一个名称或不能访问一个属性的时候, 就会创建一个Undefined对象并返回.

4.1 class Undefined(hint = None, obj = None, name = None): 默认的Undefined类型, 这个undefined类型只能被打印, 遍历, 布尔判断, 其他的任何访问都会引发UndefinedError.

4.2 class DebugUndefined(hint = None, obj = None, name = None): 用来打印返回debug信息的Undefined类型

4.3 class StrictUndefined(hint = None, obj = None, name = None):

上下文环境:

5.1 class Context(environment, parent, name, blocks): 用来保存模板的上下文环境变量. 不支持直接创建实例, 因为它是在模板的不同评估阶段自动创建的.  Context对象是不可变的, 不可以在parent中修改, 只允许在创建template代码的时候在vars上修改. 模板的filters和全局函数被标记为contextfunction(), 当前活动的context会作为第一个参数被传递给这些全局函数, 并且是只读的.

上下文环境支持只读的字典操作: get, __getitem__, __contains__, 然而__getitem__失败之后不会发生KeyError, 而是返回一个Undefined对象.

属性解释:

5.3.1 parent: 一个只读的字典, 其中存放全局变量, 这些变量可能来自另外的Context实例, Enviroment.globals或者Template.globals. 他们都是不可修改的.

5.3.2 vars: 模板的本地变量. 是字典类型,  包含了来自parent的environment和 context functions作为本地的可以从模板修改和导出的变量. 模板将会修改这个字典在评估template的时候, 但是filters和context functions是只读的.

5.3.3 environment: 加载这个模板的environment对象

5.3.4 exported_vars: 这个集合包含所有template导出的名称, 名称的值在vars字典中.  可以通过get_exported()方法获得一个新的导出变量字典.

5.3.5 name: 拥有这个context的模板的加载名

5.3.6 blocks: 一个当前已经映射的block字典. keys是所有block的名字, 值是所有block的注册值. 最后一项是当前活动的block

5.3.7 super(name, current): 渲染一个父级的block

5.3.8 get(key, default = None): 获取模板context中的一项, 如果key不存在, 返回default

5.3.9 get_exported(): 返回一个exporeted variables字典

5.3.10 get_all(): 返回一个完整的context拷贝(包含所有的全局变量)

加载器

所有的加载器继承自BaseLoader, 可以通过继承BaseLoader并重写get_source方法创建自己的加载器.

6.2 class BaseLoader(): 所有加载器的基类….Environment 提供的get_template方法会调用加载器的get_source()加载模板.

6.2.1 get_source(environment, template): 获取模板的源, 文件名和reload帮助器.  接受environment和模板名, 返回一个元组(source, filename, uptodate), 如果加载不到, 可以触发TemplateNotFound异常.    返回的source是模板的unicode或ASCII字符串形式.  文件名必须是真正在文件系统中存在的文件全路径, 如果不是从文件系统加载可以返回None, 最后一个返回uptodate是一个函数, 如果自动reloading允许, 就会在模板的源发生改变的时候自动调用这个方法. 这个函数不接受任何参数, 因此需要在函数中保留一些原来的状态, 可以使用闭包来保存状态.  如果这个uptadate方法返回的是False, 模块就会被重新加载一次.

6.2.2 load(environment, name, globals = None): 甲子啊一个模板, 这个方法从缓存中查找一个模板或调用get_source()加载.  子类可以重写这个方法来改变加载方式.

其他的jinja2内建加载器:

6.3.1 class FileSystemLoader(searchpath, encoding = ‘utf-8’): 从文件系统加载

6.3.2 class PackageLoader(package_name, package_path = ‘templates’, encoding = ‘utf-8’): 从包中加载

6.3.3 DictLoader(mapping): 从指定字典中加载

6.3.4 FunctionLoader(load_func): 调用指定的函数加载, 该函数返回一个元组tuple(source, filename, uptodatefunc), 其中uptodatefunc同BaseLoader.get_source()返回中的uptodatefunc, 用来在重加载时判断是否需要重加载.  返回False会进行重加载

6.3.5 PrefixLoader(mapping, delimiter = ‘/’): 前缀加载器, mapping是一个字典, {‘loader1’: loader1, ‘loader2’: loader2}, 则加载’loader1/template.html会调用loader1加载器, delimiter是一个间隔字符串, delimiter之前的就会被作为mapping的key获取具体的加载器.

6.3.6 ChoiceLoader(loaders): 接受一个加载器列表, 在加载模板的时候, 如果使用其中一个加载器加载失败就会选用下一个加载器继续加载.

公共工具: 用来自定义filter和函数

7.1 environmentfilter(f): 装饰器, 标记为environment依赖的filter, filter会作为filter的第一个参数被传递.

7.2 contextfilter(f): 装饰器, 标记为context依赖filter, 当前context会作为第一个参数被传递给filter.

7.3 environmentfunction(f): 该装饰器被用于标记一个可调用对象作为enviroment的可调用对象,

7.4 contextfunction(f): 该装饰器被用于标记一个可调用对象作为context的可调用对象,

7.5 escape(s): 转换(&, <, >, “)字符成为HTML的安全序列.  返回的是一个Markup对象, 由于Markup是标记为安全的不需要escape的, 所以, 一个串是不可能被二次escape的.  如果需要自动转码, 可以将environment的finalize属性设置为escape

7.6 clear_caches(): 清理缓存的接口.

7.7 class Markup()  标记一个string包含的html/xml是安全的, 不需要escape….

异常:

8.1 TemplateError(): 所有模板异常的基类

8.2 UndefinedError(): 模板尝试操作一个Undefined类型的时候触发异常

8.3 TemplateNotFound(name): 模板查找不到的异常, 参数是模板的名称

8.4 TemplateSyntaxError(message, lineno, filename): 模板内部有语法错误的时候触发, message是异常消息, lineno是异常发生的行号, filename是发生异常的模板的文件名.

8.5 TemplateAssertionError(message, lineno, filename): 不懂

自定义过滤器: 在模板中使用{{ obj | myfilter(args)}}对应的就会调用过滤器:

def myfilter(obj, args):

       pass

自定义过滤器的注册: environment.filters[‘filter_name’] = filter, 内建的filters可以通过调用environment.filters获取.

注册为environment过滤器使用装饰器environmentfilter

注册为context过滤器使用装饰器contextfilter

自定义测试: 在模板中使用{% if obj is test_name %}的方式进行测试.

10.1 test返回的必须是True或False.

10.2 test的注册: environment.tests[‘test_name’] = test

同样可以使用environment.tests获取所有内建的tests

注册为environment过滤器使用装饰器environmentfunction??

注册为context过滤器使用装饰器contextfunction???

全局名称空间: Environment.globals, 或Template.globals

section 2 Template Designer

概要:

一个模板就是一个简单的文本文件, 它可以生成任何基于文本的格式(HTML, XML, CSV, LaTeX 等等), 没有明确的扩展名, .html, .xml 或者其他任何都可以.

模板包含变量(或表达式), 当模板被评估(解析)的时候这些变量会被替换成值.

模板有一些标签, 用来控制模板解释时的逻辑.

模板的语法多是使用Django和python创造的.

1.5 {% %}用来执行语句, {{ }}用来返回一个变量的值.

变量:

可以使用.号来获取对象的属性

支持切片操作

如果访问的对象在模板中没有被找到, 就返回一个预定义的Undefined对象.

过滤器:

变量的修改可以使用过滤器.

过滤器的语法是使用管道操作符|, 过滤器可以多重嵌套使用, 前面的过滤器的返回值将会作为下一个过滤器的第一个输入参数.   这里的管道和linux的管道概念上是类似的, 将前面的表达式的返回值交给后面的表达式(或函数)处理

测试: 和filter类似, is前面的值将会被作为test的第一个参数传入, 如果还有其他的参数, test名称后面加空格跟随其他参数, 或者使用方法调用符”()”进行参数的传入.

注释: {#  #}中间包含注释语句.

模板继承: 通过在一个框架模板中定义一些公用的输出, 在通过定义子块block达到代码共享, 这样, 其他的模板继承框架模板, 就不用再写重复的公用代码.   其中的block在父模板中可以有实现, 在子类中通过重写达到多态效果.

定义block: {% block block_name %} {% endblock %}

子模板中继承父模板: {% extends ‘base.html’ %}, 这一句告诉模板引擎, 这个模板继承另一个模板, 当解析这个模板的时候, 首先会本地化它的父模板. extends标签如果有则必须是模板中的第一个标签.

在同一个模板中, 不允许有重名的block

在模板中, 可以通过self获取自身的引用来调用指定名字的block内容, 例如{{self.block_name }}

在block中, 如果重写了父模板的block, 又期望显示父模板的内容(当只是对父模板做了一些填充性的扩展需求发生时), 可以使用{{super()}}来显示父模板中该block的内容

7 HTML Escaping

当从模板生成一个HTML的时候, 会由于变量包含一些HTML标签带来危险. 对于这个问题有两种解决方法: 手动转码每个变量或者通过默认指定自动转码所有的变量

7.2 Jinja2对两种解决方法都支持, 具体使用哪个根据应用程序的配置, 默认的配置是非自动转码.

默认使用手动转码的原因:

自动转码会对所有的变量都进行转码, 对于很多的变量实际上是不包含HTML元素的, 也就不会产生安全影响, 这样转码就会对性能带来影响.

变量的安全信息是非常脆弱的, 可能会因为转码和解码导致数据丢失.

使用手动转码的工作方式:

对于可能包含>, <, &, “等字符的不可靠变量进行转码

转码使用管道调用filter: {{user.username | e}}

使用自动转码的工作方式: 会对所有未设置为安全的变量进行转码

8 For:  {% for user in users %} {% endfor %}: 下面列出for循环块内部可用的变量

8.1 loop.index: 当前迭代索引, 1开始

8.2 loop.index0: 当前迭代索引, 0开始

8.3 loop.revindex: 当前迭代到结束还有多少个元素, 包含当前元素

8.4 loop.revindex: 当前迭代到结束还有多少个元素, 不包含当前元素.

8.5 loop.first: 当前迭代元素是否是第一个元素

8.6 loop.last: 当前迭代元素是否是最后一个元素

8.7 loop.length: 迭代对象一共有多少个元素

8.8 loop.cycle: 返回一个包装的Cycle对象. 该对象描述迭代的当前状态.

9 If: {% if bool_expression %}

10 Macros: {% macro macro_name(args, kwargs) %} 内部可以使用传入的参数, 就像普通的方法的方法体 {% endmacro %}

10.1 Macros的调用: {{macro_name(*args, **kwargs)}}  返回的是定义的macro的标签体内的输出.

内置属性:  可以在{% macro %}和{% endmacro %}之间使用的属性

10.2.1 varargs: 如果调用时传递的位置参数多于定义的位置参数, 多出的会以一个元组的形式保存在这个变量中

10.2.2 kwargs: 如果调用时传递的关键字参数多于定义的关键字参数, 多出的会以一个字典的形式保存在这个变量中

10.2.3 caller: 调用这个macro对象的call对象, 该对象是一个可调用对象, 可以使用{{caller()}}的方式获取call中的自己输出.

外部可调用属性:  可以在macro定义外部通过macro_name.field_name调用的属性

10.3.1 name: 获取macro定义的名称

10.3.2 arguments: 获取定义中的所有参数名称, 返回一个元组

10.3.3 defaults: 获取所有定义中的有默认值的参数的默认值.

10.3.4 catch_kwargs: 如果为True表示macro的定义可以接受扩展关键字参数, 也就是可以接受在定义中没有指定的参数

10.3.5 catch_varargs: 如果为True表示macro的定义可以接受扩展位置参数, 也就是可以接受在定义中没有指定的参数

10.3.6 caller: 布尔类型, 表明在macro定义中是否调用了caller()对象

11 Call: {% call macro_name(*args, **kwargs)%}内部可以定义自己的输出{% endcall %},

用来对macro定义的函数的扩展.

在调用的时候, 还可以使用参数传递:

在macro定义中调用时, 使用{{call(*args, **kwargs)}}的方式进行调用, 就会把参数传递给{% call %}

在{% call %}中需要接受参数时使用{% call(*args, **kwargs) macro_name(*args, **kwargs) %}

12 Assignments: 为模板指定别名的语法: {% navigation = [(‘index.html’, ‘index’), (‘about.html’, ‘about’)] %}

13 Block: 定义模板中的块

14 Include: 将预定义的模板引入到当前模板中, 语法是{% include ‘template_name’%}, 这个标签没有结束符, 默认会传递当前context到被引入的模板

15 Import: {% import ‘template_name’ as new_name %} 将一个模板引入作为新的变量, 就跟模块的引入相似, 引入后可以使用.点号操作符获取其中定义的macro等元素, 也可以使用from-import语法{% from ‘template_name’ import element_name as new_name %}将模板中的元素引入并赋予一个新的名称.  默认不会传递当前的context到被引入的模板

16 Import Context Behavior:

16.1 {% import ‘template_name’ with context %}, 引入template并传递当前context, 同样, from-import的引入方法也使用with context语法

16.2 {% include ‘template_name’ without context %}, 包含一个template, 但是不传递当前context

17 Expressions:

17.1 “string”引号中间的就是字符串

17.2 42 / 42.23: 直接用数值表示float, int

17.3 [1, 2, 3, 4]: 列表

17.4 (1, 2, 3, 4): 元组

17.5 {‘one’: 1, ‘two’: 2} 字典

17.6 true/false

18 +, -, *, /, **, //, %等数学运算符都支持.

逻辑运算符and, or, not也同样支持

其他操作

20.1 in 判断元素是否在集合中

20.2 | 管道操作符, 默认使用Apply调用一个方法

20.3 ~  字符串连接

20.4 ( )  调用可调用对象

20.5 . 和 [ ]获取属性

三元操作: value1 if expression else value2支持

内建filter: (对于内建filter的别名, 可以在jinja2的filters.py文件中查找)

22.1 abs(number)  返回一个值的绝对值

22.2 batch(value, lincount, fill_with = None): 接受的value是一个序列对象, linecount表明个数, 最后生成一个列表, 列表个数为linecount, 如果提供的value长度小于linecount, 不足的使用fill_with填充

22.3 capitalize(string): 接受一个字符串, 将其转换为首字母大写, 其他字母小写的形式返回

22.4 center(value, width = 80): 接受一个字符串, 将其至于80的长度中居中, 不足的字符使用空格填充

22.5 default(value, default_value = u””, boolean = False): 返回value指定的变量的值, 如果value是Undefined那么返回default_value指定的值, boolean意义未知

22.6 dictsort(value, case_sensitive = False, by = ‘key’): value为要遍历的字典, case_sensitive指示是否立即加载, 设置为False表示延时加载, by表示以什么排序, 可以通过设置by = ‘value’来以值排序.

22.7 escape(string): 返回一个转码的安全HTML

22.8 filesizeformat(value): 接受一个数值, 返回人易读的文件大小表示.

22.9 first(sequence): 返回序列的第一个元素

22.10 float(value, default = 0.0): 将接受到的value转换成float类型, 如果转换失败返回指定的default值

22.11 forceescape(value): 强制进行HTML转码, 也就是说不检查要转码的字符串是否是标记为安全的,这样可能会发生二次转码

22.12 format(value, *attribute): 类似于字符串格式化’%d     %s’这样的功能value是格式定义, attribute不定参数接受占位符代表的值.

22.13 groupby(value, attribute): 按照指定的共有属性将集合进行分组, 返回元组组成的列表, 元组中第一个元素是用来分组的属性的值, 第二个元素是分组得到的所有原集合元素的列表.

22.14 indent(string, width = 4, indentfirst = False): 将接受到的string, 每行缩进width指定的字符数, indentfirst用来指定首行是否缩进.

22.15 int(value, default = 0): 将接受到的value转换成int型, 如果转换失败, 返回default指定的值

22.16 join(value, d = u””): 接受一个序列类型的对象, 向序列中进行插空d指定的字符串返回一个字符串

22.17 last(seq): 返回指定序列的最后一个元素

22.18 length(obj): 返回序列或者字典的项数

22.19 list(value): 将接受到的value转换成一个list

22.20 lower(string): 将接受到的字符串转换成小写形式.

22.21 pprint(value, verbose = False): 漂亮的打印一个变量的值, 多用于调试, verbose表示是否显示冗长的信息

22.22 random(seq): 接受一个序列对象, 随机返回其中的一个元素

22.23 replace(string, old, new, count = None): 接受一个字符串, 将其中的old表示的子串替换成new指定的子串, 从左到右替换count次, 如果count不指定, 则替换一次

22.24 reverse(value): 接受一个可迭代对象, 返回逆序的迭代器

22.25 round(value, precision = 0, method = ‘common’): 舍去运算, 接受一个值, precision表示精度(小数点后保留几位), method可以取值common | ceil | floor, 分别表示四舍五入 | 进位 | 舍去

22.26 safe(value): 标记传入的value值是安全的, 使用escape转码时不会发生二次转码

22.27 slice(value, slices, fill_width = None): 切片, 接受一个可迭代对象, 返回slices指定的前n个元素, 不足n个使用fill_width指定的对象进行填充

22.28 sort(value, reverse = False): 接受一个序列对象, 进行排序, reverse指定是否逆序

22.29 string(obj): 接受一个对象, 转换成一个string字符串

22.30 striptags(values): 接受一个字符串, 剥离SGML/XML标签, 并且将多个空白字符转换成单空格

22.31 sum(sequence, start = 0): 接受一个序列对象, 返回序列对象的元素和start的总和, 如果指定的序列对象是空的, 就返回start指定的值

22.32 title(string): 将接受到的字符串转换成标题模式, 即每个单词的首字母大写

22.33 trim(value): 去掉字符串开始和末尾多余的空白字符

22.34 truncate(string, length = 255, killwords = False, end = “…”): 切断接受到的字符串, 截取前length个字符, 如果字符串比length长, 切断后追加end指定的字符串, 如果killwords = True可以返回, 如果killwords = False不会有任何输出, 不明白.

22.35 upper(string) 把接受到的字符串转成大写

22.36 urlize(value, trim_url_limit = None, nofollow = False): 接受一个url, 转换成一个<a>标签表示的link, 这个link的href为传入的url, innerText是url截取前trim_url_limit个字符, nofollow设置为true时, 会为这个link加入一个属性 rel=’nofollow’

22.37 wordcount(string): 计算string中的单词数

22.38 wordwrap(string, width = 79, break_long_words = True): 返回经过包装的width指定宽度的字符, 也就是说每读取width个字符就会换行. , break_long_words表明在获取到width个字符之后, 如果一个单词还没有结束, 是否截断单词, False将不会截断

22.39 xmlattr(d, autospace = True): 通过接受一个字典, 创建一个SGML/XML属性列表, 例如:

<ul {{ {‘class’ = ‘my_list’, ‘missing’: none, ‘id’: ‘list’} | xmlattr }} />

可以得到输出

<ul class=’my_list’ id=’list’ />

字典中指定的值为none的, 将不会被解析成标签属性.

内建测试:

23.1 callable(object): 测试一个对象是否是可调用对象

23.2 defined(value): 测试传入的对象是否已经定义了

23.3 divisibleby(value, num)测试传入的数值是否可以被num整除

23.4 escaped(value): 检查传入的对象是否被转码了

23.5 even(value): 如果传入的对象是even的返回True,  不懂even是什么样的对象

23.6 iterable(value): 检查对象是否是可迭代的

23.7 lower(value): 检查传入的字符串是否都是小写

23.8 none(value): 检查对象是否是空对象None

23.9 number(value): 检查对象是否是一个数字

23.10 odd(value): 检查传入的数字是否是奇数

23.11 sameas(value, other): 检查传入的对象和other指定的对象是否在内存中的同一块地址(同一个对象)

23.12 sequence(value): 检查对象是否是序列, 序列同样是可迭代对象

23.13 string(value): 检查对象是否是string

23.14 undefined(value): 检查一个对象是否未定义

23.15 upper(value): 检查一个字符串是否全部大写

全局函数:

24.1 range([start, ]stop[, step]):

{% for i in range(10) %}

       {{ i }}

{% endfor %}

24.2 lipsum(n = 5, html = True, min = 20, max = 100): 不知道用途

24.3 dict(**items)  根据传入的关键字参数构造一个字典对象.

Socket Basics

Posted on 2012年5月23日 15:23

server

from socket import *

myHost = ''
myPort = 50007

sockobj = socket(AF_INET, SOCK_STREAM)
sockobj.bind((myHost, myPort))
sockobj.listen(5)

while True:
    connection, address = sockobj.accept()
    print('Server connected by', address)
    while True:
        data = connection.recv(1024)
        if not data: break
        connection.send(b'Echo=>' + data)
    connection.close()

client

import sys
from socket import *

serverHost = 'localhost'
serverPort = 50007

message = [b'Hello network world']

if len(sys.argv) > 1:
    serverHost = sys.argv[1]
    if len(sys.argv) > 2:
        message = (x.encode() for x in sys.argv[2:])

sockobj = socket(AF_INET, SOCK_STREAM)
sockobj.connect((serverHost, serverPort))

for line in message:
    sockobj.send(line)
    data = sockobj.recv(1024)
    print('Client received:', data)

sockobj.close()

QGtkStyle was unable to detect the current GTK+ theme.

Posted on 2012年5月22日 20:35

qt-config 没有就下载

 

GUI风格 选择 Cleanlooks