2008年11月8日星期六

我印象里面的天健学社

       近来风闻了尹慧金、彭文莉等学生闹事,而这些事情又和我心爱的天健学社有关,我不得不关注了起来。我是2003年进入武大,外省来的,带着点点离乡的忧愁,更带着求学的想法进入美丽的武大。在2003年9月被武测食堂门口天健学社招新的学长们吸引了,因为他们的广告口号是“天行健,君子以自强不息”,他们说这是社团的宗旨。
   恍惚中,觉得这就是心中的大学啊。于是痛快的和同班的一个同学加入了这个社团(后来发现,社团人并不是很多,在本部教一(似乎是这个教室,就是在桂圆宿舍区旁边的,WTO后面那个)社团集会的时候,发现人也就大概30多人,应该有人没有来)。印象里面好像没有交会费,呵呵。第一次迎新碰头会后,社团团长吧(不记得是谁了,好像还是个女的?)就给大家将社团历史啊,宗旨这些八股啦,后面就安排了咱们这些新成员做点什么事情,主要有这些:每个校区由学长负责,组织各个校区的社团成员晨练;组织讲座;学英语,看电影;学太极拳。。。
    那些日子是很开心的,和志同道合的人一起晨练,围着武测的操场跑圈,(可恶的是,学长不仅要求长度,还要求速度,会帮大家计时,希望大家跑得快些,呵呵)(再PS下,后来慢慢的学长不再督促,不再组织了,因为最终要靠大家自觉自愿的去锻炼,我有一次独自锻炼,遇到了从公安县过来考试的一家人——父亲、母亲和女儿,那个女孩长的真实漂亮,我回答她问路都紧张死了,呵呵。不过,他们一家人也真辛苦,早上7点多一点点就过来了。)
    讲座讲什么的,不记得了,我比较笨,容易忘记事情的。。。但是我记得社团有一次请我们去今日电器里面的影棚里面看过电影,我还记得电影是《贝隆夫人》,呵呵,我是农村出来的,很少看这类电影,感觉很好看,也很感动,其中的主题歌也很好听,我想很多看过这电影的人都会喜欢吧?
    后来,社团请了一个民间武术家来教我们打太极拳,这教了一个学期,手把手的,从刚开始的30多人,到最后好像就10多个人坚持下来了。这里面比较有趣的是,这位民间武术家的名字我不记得了,但是我记得当时他说他是我们武大哪个地方的门房的时候,我们很多人都很吃惊,呵呵。真实卧虎藏龙啊!这位师傅教我们的不是那种好看的、健身的杨氏太极拳(这种拳很多人体育课就有教,我本科体育课也上过这个),而是打斗(这词似乎用的不当,至少是能够防身的!)的太极拳,招式和杨氏的也不一样哦。师傅教我们的时候,经常和我们推云手,感觉就想掉进大海里一样,随波逐流,真的很厉害啊。这是我第一次真正见过的真功夫!
    后来嘛,大二大三了,就很少参加社团活动了,社团里面也没有通知过我再去参加。不过我想,很多社团也都是这样吧,渐渐的会把非核心的老成员“淡忘 ”。这是很正常的,新的负责人故意或者无意的忘记了我们这些老家伙?呵呵,没有什么抱怨的意思啦。
    对天健学社,我只有更多的感恩和惭愧,参加天健,是我本科没有白过的一个原因。惭愧的是,天健学社后面那么多付出的学长和师长们,我没有对社团做出什么贡献。我只能在偶然听到别人谈起天健学社的时候,插嘴说:我也参加过天健!天健教人自强不息,我很喜欢。这真的是一个为数不多的好社团!
    我和天健主要就是在2003-2004一年间有紧密的接触,那时候我听说天健是张键柏老师(一个武大资历最老的讲师,今日电器老板、今日学堂的“校长”)无私奉献了很多时间、精力和金钱的。
    从未来网上看到这个《关于个别同学及社会人员冒用天健学社名义开展违纪活动的通告》http://manage.future.org.cn/article/45252.htm, 我才知道我们的天健现在处在一个危急之中。我实在不能做什么,但是我觉得我该把我印象里面的、我亲身经历过的事情说出来,希望大家一起帮帮天健学社,一起帮帮“天行健,君子以自强不息”,这也是在帮助我们每个人自己,帮助我们后来的武大人。
    我想我所说的这些都很公正,没有任何的偏袒,对于“尹慧金、彭文莉”等人的事情也不了解,因为我很久没有天健的消息,也不认识这两人,对她们的“闹事”也是后来风闻。所以我不能做任何评断,况且也不希望这两人的事情使得天健学社收到损害,更不希望天健的宗旨收到侮辱。
    另外,对于张健柏讲师、尹慧金、彭文莉同学等,还希望学校秉公处理,同时对于学生能够考虑更加全面和深远,不要毁了年轻人一辈子,不要轻易将“邪教”的帽子扣在任何人的头上,这也许会把一个不好不坏的人推向坏人这一类?
    

各位有耐心看到这里的同学、师长,
可以看看这些信息,我要申明的是,我不知道我从网络上找到的这些信息是否真实,我也不做评论,请愿意看的人自己去评判。

1、《关于个别同学及社会人员冒用天健学社名义开展违纪活动的通告》 发布者:武汉大学学生社团联合会 李鑫鹏    发布时间:2008-11-05 15:32:51
http://manage.future.org.cn/article/45252.htm
2、一个已经毕业的学长的博客
《自强网记者深入挖掘天健学社静坐事件始末》 (2008-11-06 10:06:20) 
http://blog.sina.com.cn/s/blog_50c23deb0100bbsq.html
3、该学长的博客跟踪
《武汉大学最火的课堂被成功封杀(上)》 (2008-11-07 17:02:53) 
http://blog.sina.com.cn/s/blog_50c23deb0100bd2m.html
《武汉大学最火的课堂被成功封杀(下)》 (2008-11-07 17:27:36) 
http://blog.sina.com.cn/s/blog_50c23deb0100bd2q.html

贴上附件里面几个文件或博客的内容
1、《关于个别同学及社会人员冒用天健学社名义开展违纪活动的通告》 发布者:武汉大学学生社团联合会 李鑫鹏    发布时间:2008-11-05 15:32:51
http://manage.future.org.cn/article/45252.htm

关于个别同学及社会人员冒用天健学社名义开展违纪活动的通告
发布者:武汉大学学生社团联合会 李鑫鹏    发布时间:2008-11-05 15:32:51
【作者:】【编辑:】

全校同学:

我校哲学院2005级学生尹慧金20072008学年度休学一年并于今年9月返校之后,与药学院2005级学生彭文莉自封天健学社正、副社长,并冒用天健学社名义在校内申请长期讲座。在学校发现并制止二人违纪行为的过程中,二人又纠集外校及社会人员,在学校工学部行政楼前静坐,并多次广泛散布歪曲事实真相的传单和网络宣传,在校内外造成恶劣影响。现将有关情况具体通告如下:

一、关于尹慧金、彭文莉二人冒用天健学社负责人名义的事实

尹慧金、彭文莉违反《武汉大学学生社团管理条例》及武汉大学学生社团联合会《学生社团换届管理办法》相关规定,事前未向学生社团联合会提出申请,在没有学生社团联合会纪律与监察部工作人员监督、未召开会员大会进行换届选举和所在院系审批的情况下,自封为天健学社正、副社长(两人自己对于究竟谁是正、谁是副仍存在言辞不一),并直接导致该社团在本学年初无法在学校合法注册登记。此外,在社团联督促指导协会按学校规定尽快完成社团负责人换届选举之际,尹慧金同学弄虚作假,在《武汉大学学生社团干部登记表》上伪造哲学院公章,且态度恶劣。

在学生社团联合会权益部暂时托管该协会,并按照学校相关规定于1023召开该协会会员大会按程序进行换届选举之际,尹、彭二人多次以种种理由阻挠换届会议举行,并对绝大部分协会会员隐瞒其面见校领导递交示威游行申请以及尹弄虚作假伪造哲学院公章等情况。在协会换届选举时,两人又纠结外校学生及社会人员参加换届大会(其中有人当场拿“军官证”以示身份和威胁),两人还以怀疑部分与会人员非协会会员为由要求会后登记所有人姓名及联系方式,在此要求在得到团委老师明确同意后,两人依旧恶意煽动与会人员离场,试图阻挠选举会议正常举行。

在候选人张学荣、曾玲(两人均为天健学社会员)合法当选会长、副会长以后,尹慧金、彭文莉通过电话、短信等方式对新当选会长张学荣同学进行拉拢、诱导(当事人可予证明)。天健学社已于112日在未来网、bbs、百度武汉大学吧、校内网等处发布郑重声明:“尹慧金、彭文莉等并非天健学社社长、副社长,其冒用天健学社名义进行非法活动,对我社造成了严重的不良影响,我社将向有关部门报告,并将在必要时求助于法律程序”。到目前为止,两人仍在今日学堂网站上冒用天健学社名义发布相关信息。

二、关于尹、彭二人纠集部分社会人员开展违纪活动的事实

彭文莉于1017日冒用天健学社名义申请本学期第715周每周六下午200人以上多媒体大教室,时间持续长达八周,申请理由为由张健柏讲授以《道德经》为主题的“中国传统文化系列讲座”。因天健学社当时尚未在学校合法登记注册、彭文莉社团负责人身份无效,且该申请不符合学校关于申请讲座的相关规定等原因,故其申请未获得学生社团联合会批准。此后,尹、彭二人多次到校团委要求解决教室审批事宜未果,于是直接面见校长要求解决其讲座场地审批事宜,并递交游行请愿书要求政管院就所谓“迫害”张健柏一事向全校同学道歉。其中及之后,彭文莉在多种材料中诬陷团委老师讲过关于政管院党委通知团委老师不要批准张健柏讲座的话,同时却事后以署名短信形式向相关老师承认错误。

两人在校内网、百度武大贴吧等网络论坛中极力歪曲和捏造事实,煽动不明真相同学对学校及有关人员进行抗议和攻击。1027日上午,二人纠结十余人到工学部行政楼前静坐示威,展示抗议宣传板,同时向路人散发针对团委老师的极尽歪曲事实真相的宣传单页。后经公安部门和学校保卫部门介入查实,十余人中大部分为外校学生及社会人员。此后,111日、4日晚上,又以“尹慧金、彭文莉及全体天健学社成员”名义在校内多种场合散发歪曲事实真相的传单并在一区教四楼个别教室进行演讲。

三、关于天健学社业务指导老师的事实说明

尹、彭二人对外宣称张健柏为天健学社业务指导教师,并鼓动不明真相学生采取游行、静坐等极端手段抗议所谓压制事件。经查证《武汉大学学生社团登记证》并直接询问当事人,证实:天健学社自20029月成立以来,其业务指导教师一直为原人文学院、现历史学院李少军教授、博导,从未卸任(其本人亲笔书写材料可予证实)。张健柏根本不是天健学社业务指导教师。

 

 

               学生社团联合会

               二00八年十一月五日


2、一个已经毕业的学长的博客
《自强网记者深入挖掘天健学社静坐事件始末》 (2008-11-06 10:06:20) 
http://blog.sina.com.cn/s/blog_50c23deb0100bbsq.html

自强网记者深入挖掘天健学社静坐事件始末 (2008-11-06 10:06:20)
这篇新闻是不能发的,虽然它没有夹杂半点记者的主观评论。在这里仅供想知道详情的同学参考。我们的记者不能说挖掘到的东西都是真实的,但是绝对都是从当事人口中得知的一线消息。出于对记者的保护,在这里名字不能给出。


    2008年10月27日上午10点,十几名身份不明的学生集聚学校团委门口,高举“我们要学习,要王志军老师给天健学社一个交代”的宣传板及百余名学生的联合签名。静坐一直持续到当天下午三点左右,其间学生与团委双方发生争执和冲突,宣传板被砸、签名被撕。由此,一场学生静坐掀起了武汉大学的一场轩然大波。


“老子”惹谁了?

    这件事还要从天健学社说起。《老子与道德经》是天健学社本学期邀请武汉大学政治与公共管理学院老师张健柏主讲的系列讲座。

    作为天健学社的正副会长(彭、尹二人自称),武汉大学哲学院学生尹慧金及药学院学生彭文莉本打算向团委申请7-15周连续每周定期举办张健柏的主题讲座,但却没有料到在申请过程中遇到了重重困难。

    根据武汉大学相关条例,讲座的审查与批准必须经过武汉大学学生社团联合会(后文简称社联)。天健学社所要批的讲座应该由社联下属纪律监察部或团委老师兼社联指导老师王志军负责审批。然而,令人不解的是,讲座的第一期和第二期都照常举行了,却在第三次审批的过程中出现了问题。

    针对为什么第三次讲座申请被驳回,王志军和尹、彭二人显然对此有着截然不同的观点。王志军说,同一个老师连续八周举办讲座,相当于在全校开了一门选修课,作为社联的指导老师,王只具备审批讲座的权利,不具备审批选修课的条件。另一方面,社联在对该学社进行审查的过程中发现两名主要负责人(尹慧金和彭文莉)“社长”和“副社长”的名号是“自封”的,没有经过正常的换届选举程序,作为“非法”的负责人无法代表整个社团申请批准讲座。另外,在接下来的调查过程中,进一步发现尹慧金向团委递交的其所在学院换届材料上公章是伪造的,更加坚定了王不批讲座的态度。

    而尹慧金和彭文莉则不这样认为。据彭文莉回忆说,当时王志军在谈到为什么不批讲座的时候说过,是政治与公共管理学院(主讲人张健柏所在学院,后文简称政管学院)不让张办讲座。考虑到问题可能在于政管学院,2008年10月16日,尹、彭决定写一份材料向校长反映问题,同时也将这份材料送到了团委。但是王志军看到材料后矢口否认曾说过有关政治与公共管理学院的事情,并且要求彭文莉在材料中有关政管院部分的叙述下签名,表明王本人并未说过相关的话,而是由彭文莉提供。在彭署名后,王志军进一步提出希望彭文莉以书面形式正式致歉认错。彭刚开始拒绝认错,但由于后来听说尹慧金已经见到校长且校长对她们表达了支持的态度(王与尹、彭二人对校长的话有不同理解,在是否支持的问题上存在分歧),觉得既然目的已经达到就没必要与老师进行对峙,于是彭随后向王发送短信,承认王没有说过有关政管院这样的话。而王志军则坚称彭向其发送的短信是自己并未说出那句话的重要证据,并在网上发表日志称彭先在传单中诬陷他讲过政管院不批张讲座的话,但却在私下以短信形式向自己承认错误是“无耻的行为”。

    第二天上午,由于从昨天的交涉中觉得取得了校长的支持,彭文莉满怀信心地再次走进团委办公室,希望这次讲座能够顺利通过审批,但是王仍严正要求彭写下书面致歉信。彭这次最终写下了致歉信却没有提到政管院,王于是火了,他对彭说:“我不想骂你,骂你这样的人不值,我不认识你,我不想见你,你以后不要来我办公室!”(据彭日志)在交涉过程中,根据记者采访所知,双方可能在态度上都存在一定问题,最后讲座仍然没有批。


换届还是换血?


    如果只是到了这一步,可能也不会造成今天这样的结果。2008年10月,天健学社换届。社联以天健学社原“正副社长”尹、彭二人换届程序违规为由,要求天健学社重新公开选举换届,社联指导老师王志军及部分社联成员列席会议。

    为什么说尹、彭二人天健“社长”身份为假呢?就尹而言,在2008年5、6月份全校换届的过程中,哲学院可能出于07年度尹曾提出退学的申请,转而休学跟随张健柏“修行”,没有同意在换届材料上盖章,而尹随后私自将哲学院原盖在另一张表格上的公章复印挪用到了换届材料上,这也是为何王一直咬定尹的负责人身份为假的主要原因。

    另外一方面,虽然彭取得了所在药学院公章,但尹、彭二人并未经过全体天健社员公开选举,擅自“自封”为正副社长,并向团委递交了换届材料。

    10月23日中午12:30,天健学社换届选举正式开始。直至12:25分,尹、彭二人才匆匆赶到。这次换届选举的目的是从六名有资格参与换届选举的候选人中差额选出两名同学,分别担任天健学社新一届的正副社长。其中,四号参选人张学荣(同时身兼社联素质教育讲堂项目部负责人)以绝对票数最终当选为社长。

    然而,据目击者称,当天现场选举过程中,天健学社部分成员与社联负责人王志军产生了激烈冲突,在尹、彭二人声明放弃本次参选天健学社社长的权利后(据称是由于她们怀疑在场88名投票人中多数并非真正天健社员,而王志军随后否定了这一说法),十几名原天健社员愤然离席,并呼吁在场“真正天健成员”尽快离场,随后王志军及部分当事人离场,会议继续进行。最终,社联纪监部宣布本次选举符合参选所需人数,选举有效,张学荣当选新任社长。

    会后,尹、彭等天健成员在网络上发表文章,称这次换届为一场“选举闹剧”。他们说,当时王叫来了一批非天健成员的学生参加投票,并安排一帮“保安”严控现场(部分为社联内部成员),最终通过不公正的方式选出了一个忠实于他的社联成员作社长,而这位社长上任的目的是要如今的天健学社名存实亡,名义上是“换届”,实质上是“换血”。在审批未果后,这件事愈加激化了双方的矛盾,最终引发了后续的静坐事件。


从“学生社团”到“秘密组织”

    在讲座被拒批、换届风波后,天健学社中有人提出通过游行的方式“和平请愿”,意在讨回说法,同时恢复讲座。而在该申请被校方驳回后,2008年10月27日上午10点,未经过任何审批的静坐事件就这样发生了。静坐和向路人散发传单等行为引起了团委的注意,双方在争吵的过程中发生冲突,宣传板被砸烂。必须说明的是,经双方证实,静坐的十几人中的确有校外人员,但是对这些人究竟是何身份却有着不一致的说法,王志军说是“社会人员”,而彭文莉及张健柏则称其是喜欢老子与道德经的一些“校外学生”。

    据彭文莉讲到,冲突过程中,一个校外的人被拖进办公楼,同时团委打电话通知各院系辅导员赶过来,要把静坐的学生拉走。然后他们被告知团委书记答应要调查他们所反映的情况,却在进入办公室后听到自己由于触犯法律要送去公安局的说法。最后,这批静坐人员当场留下姓名,核实了身份后才被放出。

    事情到此,远未结束。第二天院系团委老师和辅导员找到这些参与者,并进行规劝。就规劝内容也存在不同版本。彭说被告知自己目无校纪校规,无理取闹,无事生非,要交代不存在的事情,比如要跟什么宗教组织有联系,有什么人在背后指使等。还所如果不交代就要受到严重处分,甚至有可能不发毕业证。不仅如此,还说触犯了国家法律,要承担相关责任,需要写检讨书及保证书,行为也将受到监控。

    而据王志军说,老师找到他们就是进行善意的规劝。尹所说的用奖学金、助学金等“利诱”根本是无稽之谈,是考虑到她家庭比较贫困,与这件事没有关系。

    静坐事件引起了诸多猜测,“邪教”、“秘密组织”、“洗脑”等传言甚嚣尘上。有人甚至猜测尹、彭二人是受到张健柏的唆使,为了给张争取上课资格而聚众闹事。再加上尹曾休学一年跟随张健柏学习,张与其学生以“师傅”及“弟子”相称,共同修习内家拳法等等众人看来不平常的现象,更加重了大家对“秘密组织”的猜测,众人谈天健色变。尹、彭等天健社员也在教四等教学楼散发传单,以此澄清自己与“邪教”一说并无联系。

    目前,天健学社新的领导班子已经上任,人文讲坛第一期也如期举行。但本次静坐的余波尚未平静。截至记者发稿日,王表示现在自己正处于搜集人身攻击及个人诽谤的方面具体证据的阶段,等校方最终处理结果出台后,很可能通过法律手段维护个人权益。而张健柏与彭文莉也于11月4日下午采访过程中向记者透露已于当日向省委反映有关情况,希望得到公正解决。
 

张健柏谈天健学社与静坐事件【自强访谈,接上文事件报道】

   经过一系列的采访,整个事件中,最令人关注的是张健柏。张健柏,今日学堂、今日电器的创始人,武汉大学政治与公共管理学院老师。他所主讲的“情商训练”选修课场场爆满,原天健学社“老子与道德经”系列讲座的主讲人。

那么关于10月27号静坐事件,张健柏是否真的就如有些人说的一系列事件背后唆使者,假冒的天健社长情的假冒的天健学社指导老师,到底他的教师资格是怎么回事……为了解答这些疑问,记者通过彭文莉终于在11月4号下午采访到了张健柏。当时彭文莉和她的父亲也在现场。访谈根据记者当时笔记和回忆写成,可能未必全部相同,但是大意如下。



1、为什么由尚重生老师挂名的“情商训练”是由您来讲的呢?

    当时武汉地区高校联合开这门课,我们学校的尚重生、王三山、石超明等老师就申请并开了这门课。但是申请下来之后,三个老师都比较忙没有时间讲,但是申请下来了又不能不讲,尚老师就找到了我。为了武大名誉,就担任了这门课的老师。一节课十二块钱,对我来讲是没有什么好处的。
   (之前采访尚重生老师,两人说法一致,的确是他们没有时间讲,而张健柏当时正好被停课,时间比较多,尚重生说他觉得这个人还是有些真东西可以交给学生的,所以就把这门课交给了张健柏。而教务部的教务干事是知道这件事的,所以在教务部网站上“情商训练”尚重生名字的后面会有一个备注“张健柏”)



2、听说您在讲这门课之前就已经被停课了,是什么原因么?那您是否能够上“情商训练”呢?

    因为我在政治与公共管理学院教的是政治与公共管理学院的马哲,就学院的学术考评制度来说,必须每年发表关于马哲的论文和研究成果,别的方面的不算。但是我自己觉得那些论文没什么价值,纯属浪费时间。也有人告诉我说可以让研究生写,只要发了就行了呗,但是怎么说呢,要讲学术良心吧,就没有这样做,所以当时我连续两年的学术考评是不合格的,于是就停了我的课。
    另一方面,停了我的马哲课是学院(政治与公共管理学院)内部的事情,也就是说等于说不聘用我。但是教师资格是无法取消的,如果取消的话是违法的,所以我还是武大的老师,可以上这门课。教务部对我讲这门课是承认的,即便是后来不让我讲,给出的理由也是我不是“情商训练”的挂名老师。



3、关于您和天健学社的关系有两种说法,一从来就是天健的指导老师,二从来就不是指导老师,到底是哪一种呢?

    按照学校的相关规定,天健的指导老师是另外一名历史学院的老师,但是这个老师不怎么管,他们(尹惠金、彭文莉等)可能是偷懒(笑)有什么事就来找我,我也尽量帮他们。我是实际做事的人,只是在学校材料上指导老师不是我的名字。愿意认是他们的事。



4、有人说,尹惠金和彭文莉不是天健的社长、副社长,是自封的,您怎么看?关于尹惠金挪用院里公章的事,您有什么看法?

    是不是社长,这个我不了解,他们内部的事我管不了。但是我知道他们(尹、彭)几年前就加入了天健的,而且做的不错。关于公章这个事情,我已经跟尹惠金说了怎么能做这样的事呢,这是绝对不对的。尹惠金说只是为了(办张的讲座)方便些,没有考虑这么多。



5、 您是否知道静坐这件事,是什么看法?
 
    静坐这件事是错的,不该这么做。但是静坐也是分性质的,它的初衷、愿望是好的,表达方式是错的。这个组织是非常小的,没有多大影响,学校没必要无限升级。



6、那按照您说的既然目的是好的,为什么团委会这样做,不批讲座呢?

    可能是是他们(尹、彭等)态度问题,得罪了团委。双方存在矛盾,团委老师就找各种理由不批讲座。如果(团委)要证明自己对,就得证明他们错。要证明自己非常对,就得证明他们非常错。
 
    那听团委的老师讲连续八周的讲座而且是同一个老师就相当与开了公选课,而王志军是没有这个权力的?

    是的,但是他说不可以连批八周,但是可以一次次去批呀,双方处理的不好不够灵活。他们是不给批讲座找不到其它理由了,就来查说八周的讲座不符合制度,社团负责人“不合法”了。



7、 怎样看待“邪教”这样的说法呢?

   “欲加之罪,何患无辞”,如果把他们整了,他(王志军)就对了,就有功了。至于别人为什么会猜测是邪教呢,是因为武大还没有这样的一个老师让学生听课可以听好几年的。我一年可以做两三百本书,所以每次课都不一样,社会上也有很多企业家和公务员都来听我的课。的确要承认别人优秀不是一件容易的事,这一点我可以理解。



8、之前我也曾经采访过尚重生老师,他说可能造成现在的结果是您张老师对自己的学说过于执着,您的逻辑和现实的逻辑不太一样,你是怎样认为的呢?

    他这样说也有一定道理,但是我没有过分执着呀,我只是展示自己的个性,你可以喜欢也可以不喜欢。每个人的都不一样,我追求的是真理、理想。

那会不会您在无意或有意中将这种逻辑推广给您的学生了呢?

    大学生都大部分是成人了,有自己的判断力。就我接触的天健的成员来讲,她们是不同的。你觉得尹惠金和彭文莉相同吗?我所开办的今日学堂也是这样,我用的是自己的教育理论,但是全国如果都这样搞的话那就是灾难。不是复制是学,不是要他们跟我学,我是trainer,是训练者。他们有什么漏洞、哪有毛病就会批评他。

可能您不是这样想,但他们都一直听你的讲座,受到什么影响?

    他们有不是只听我讲课,别的老师也听呀,要不你去问彭文莉。

如果说您是个trainer,那您觉得可以将他们训练成什么样的人呢?

   我不是训练,只是教给他们成为什么样的人。希望做一个真诚、有智慧、有责任感的人。

 (其间,张健柏在提到彭文莉的问题是“太执着、死脑子”时,沉默已久的彭文莉的父亲讲到,孩子社会知识方面缺乏,学校应该事实求是,不应该把反动组织跟学习放在一起。张健柏接着讲到,是的,不能为了自己的小利,毁灭别人的前途。)




9、 那您对结果怎么看,对未来有什么预期?

    因为双方处理的都不是很好。尹、彭等他们天健成员希望能换个(团委)老师,也希望讲座能够办起来。我觉得王志军应该道歉,向学生认错,同时批给讲座。学生也要做检讨。


3、该学长的博客跟踪
《武汉大学最火的课堂被成功封杀(上)》 (2008-11-07 17:02:53) 
http://blog.sina.com.cn/s/blog_50c23deb0100bd2m.html

武汉大学最火的课堂被成功封杀(上) (2008-11-07 17:02:53)

武汉大学最火的课堂被成功封杀

 

作为武汉大学的学生,虽然已经毕业,但母校发生的事情仍然时时牵动着我的心。突然听说近来学校发生了一件极为恶劣丑陋的事—— 张健柏老师的课被学校封杀。真是既痛心又无奈。痛心的是,真正有思想有见地的老师又少了一个。这无疑意味着我们失去了跟大师学习的宝贵机会。对学生而言,有什么比这种损失更为惨重的呢!无奈的是,从易中天老师到赵林老师,再到现在的张健柏老师,甚至听闻尚重生老师明年也要停课。好像武大漠视人才,排挤受学生拥戴老师的做法已成风气,变得稀松平常了。加之近来网上高校排名,武汉大学已跌出前二十。真的令人担忧,武汉大学将何去何从。我们这些昔日曾以母校为荣的学子,将有何脸面再骄傲的宣称自己是“武大郎”。

关于张健柏老师

大学之大,为有大师才之为大。我想,这一点无论何时都无法改变。作为武大学子,提及那些大师,不得不先说到“四大名嘴”。仿佛他们已经成为武大的另一种代名词了。

李工真老师的课堂,永远充满着嬉笑怒骂,悲欢离合。语言犀利,视角独到。我们在其间听着,看着,也笑了,也哭了,也惊叹了,也反思了。就像看了一场精彩纷呈文物并重的传统京剧。不由的让人连声较好。就一个词“过瘾”。然而,听过了,也就过了。顶多是回味一番,期盼下一场

赵林老师浓郁的学术风格令人由衷的钦佩折服。有人说老师的外形有些像冯巩,我想与其儒雅的气质和博学的内涵不大搭调。听其讲学,感到就是学术的精湛与美妙。真正的做学问的人,我们从内心是肃然起敬的。然而,总有种感觉,可远观而不可身及。学术是学术,自己是自己。无法受用

李敬一老师是诗人与艺术的完美结合。开朗洒脱,热情四溢。只有听了他的讲座,才会明白什么叫“诗词的意境,解译的魅力”。挺没劲的一首诗,搁到李老师嘴里一评析,怎么就这么感人。在他的课堂上,可以抛却周身的疾苦与失意。驾着文字的彩翼信天驰骋。感觉棒极了。然而,余音绕梁终有绝日不可能一直在陶醉中沉迷,终究从幻境里走到现实中来

尚重生老师总是一针见血,无情的撕破事实的真相。“玩什么虚的,得看真家伙!”就是这样直白,朴素,残酷的语言。把一幕又一幕的阴冷,黯淡,卑劣,龌龊批得体无完肤,剥的血光粼粼。在他的课堂上,只有窒息的沉寂和心酸的苦笑。忽然发现,这个社会原来比想象的还让人心寒,太可怕了。然而,郁闷痛恨过后,只能无奈的承认,无从做起,无能为力。

名嘴让人敬仰。可武大中真的“隐士”更加令人拜服。

张健柏老师就是这样的“隐士”。称其为“隐士”,只因他不为名誉所动,不愿把时间精力用在发表一些没有价值的论文,或者跟领导同事搞好关系以便晋升等方面,而是专注于学术研究和教导学生。从教近二十年,尽管学术造诣极高,也非常受学生欢迎,却依然只是讲师。恐怕已经是“武大资格最老的讲师”了。他的风格与别家不同。道家的,儒家的,法于自然的,偏于现实的,好像都有点像,又仿佛都不是。对于其人,借《论语》的话,望之也威,听其言也厉,即之也温来描述最为恰当。用“五岳归来不看山,黄山归来不看岳”加以形容,可能是对其他大师的不尊重,姑且借来暂代此意吧。如果是头一次进入他的课堂,一开始,有点喧闹“没什么特别吧,看起来挺年轻的,有经验吗?”。三分钟之后,出奇的静。所有人都张大了瞳孔和嘴巴,“这个人究竟是干嘛的。怎么说的话和别人的都不一样。好像还蛮有道理的。”那么接下来,便要在痛苦的起跑线上挣扎着启程了。重新认识自我,重新反思生命,重新面对人生,重新选择方向。这一切,就在这位清清瘦瘦,朴朴实实,温温雅雅的“武大资格最老的讲师”的开启下,发动起来了。他的课就是让人开始思考的,而且思考之后我们会惊喜的甚至欢呼雀跃的发现,竟然可以沿着思考的方向去做。有什么能比这更令人激动的呢?

我是从大一开始就听张老师的课,到现在已经有四五年的时间,每个周末去听一次他的课,好像成为一种“充电”的需要。可谓受益匪浅,而且越学越觉得张老师的东西博大精深。对于帮助我们研究学术,指导自己的工作和生活十分受用。身边和我一样的同学还有许多。有的在外地工作,还特意保留了以前在课堂上讲课的录音资料,经常聆听反复体悟。如果不是张老师讲授的东西非常有价值,怎么可能会有这么多人整个大学期间甚至毕业了还特意留下来继续跟其学习?

 

关于人生哲学讲堂和老子与道家智慧讲堂

 

人生哲学十二讲是武汉大学的一门公共选修课。(现在都觉得自己很幸运,能在毕业之前听到这门课。对我来说,所学到的内容会一生受益。)虽然开课才仅仅一年时间,但其火爆的程度令人难以想象,从第一节到最后一节,无论门口,过道甚至讲台都挤得水泄不通。主讲人便是张健柏老师(令我困惑不解的是,学校网站上公布的主讲却另有其人。如此受学生欢迎的老师,学校居然一个名分都不愿意给,还要委屈于别人的名义之下。就连我这个作学生的也看不惯,忍不住想要为老师鸣不平了)。

不知大家是否知道,去年哈佛商学院最受欢迎的选修课是幸福课,听课人数超过了王牌课《经济学导论》。教这门课的是一位名不见经传的年轻讲师,名叫泰勒·本-沙哈尔。在一周两次的幸福课上,本-沙哈尔没有大讲特讲怎么成功,而是深入浅出地教他的学生,如何更快乐、更充实、更幸福。其实,张老师的这门人生哲学课与之非常类似。可以说是武汉大学的“幸福课”。张老师从不同角度阐释了人生的价值和生命的意义。涉及到身心健康,家庭幸福,事业成功等方面。包括人生目标的设定,心灵与财务自由,家庭与婚姻之男女专场,教育专题,修身与内家武术等十二个专题。张老师现身说法,情理并重。可以说整个课程就是一次心灵的净化与灵魂的洗涤。

很多同学在课程结束时都觉得,人生问题这十二讲场场精彩,让人回味无穷,一生受益。每次上课都是一个痛苦的过程。因为每次听课都不得不进行艰难的自省,将自己从旧我中一层层地剥离出来,从无知与浅薄中挣扎爬出。迫使自己换一个角度,换一种心态去认识真实的自己,看待宝贵的生命。张老师让更多的大学生学会怎样思考,怎样探寻,怎样求证。而不是糊里糊涂的陷入自我,家庭,学校,社会为我们编织的谎言当中。而这些话题恰恰是在传统教育的课堂上不曾听到过的。他的教导给大学的生活注入了更多的活力,使我们开了眼界,感到耳目一新。特别是脑子里的垃圾被清空后,也变得开朗成熟有活力了。终于能放下很多无谓的包袱清醒更充实地投入生活了。


《武汉大学最火的课堂被成功封杀(下)》 (2008-11-07 17:27:36) 
http://blog.sina.com.cn/s/blog_50c23deb0100bd2q.html

武汉大学最火的课堂被成功封杀(下) (2008-11-07 17:27:36)

课堂场场爆满

 

张老师博学广识,对中国传统文化的研究和证悟有极高的见地。儒释道皆有点染,尤其是对中国道家文化更为专精。张老师本身非常繁忙,但在广大同学的强烈要求之下,为了满足大家的求学热情和让更多的同学了解到真正有价值的传统文化,他还是利用周末休息的时间在校外自己家中免费为大家讲解老子《道德经》。

一年多来这个校外公益讲堂更是火爆异常,本来只能容纳七八十人的地方,总是有上百人报名参加。不但有武汉大学的同学,而且华工,财大,民大等高校的学生也纷纷慕名而来。就连很多已经工作的社会人士也特意前来听课学习。张老师对《老子》的见解可谓精当独到,把那些看似玄而又玄的道理分析得质朴简洁。他结合自己的生活和经历,从调心修身,经营管理,治国安邦等不同角度加以阐释,使大家对《老子》的理解更为明了透彻。更让我们受益的是,张老师本身也是内家武术高手,他还结合太极拳的拳理,修炼和实战等方面来加以讲解,使大家对中国传统文化的内涵有了直接的体验和深刻的领悟。

由于报名听课的人数越来越多,场地又确实有限,虽于心不忍,但不得不把更多的人拒之门外。为了让更多武大学子能够听上张老师的老子课堂,本学期武汉大学天健学社以社团活动的形式,请张老师把《老子与道家智慧》系列讲座搬到校内。开办的两次非常成功,听众爆满,课堂师生互动其乐融融。如果这个课堂能持续开展的话,对于武大乃至整个武汉的大学生来说都是受益无穷的。

但是天意无常,人心难料,讲座才办了两次就被扼杀了。更让人难以想象的是,就连张老师正常的人生哲学公选课也被封杀。这是武大的耻辱,更是学生的不幸。

 

关于静坐请愿

 

“学生求学无门被逼静坐,团委百般刁难压制打人”,这篇关于武大学生静坐请愿真相的文章已经在网上炒的沸沸扬扬。事实究竟怎样暂且不论。我想说的是,我所了解的尹慧金是一个积极善良,阳光健康的女孩子。她有着强烈的求学热情,和异常坚定的治学态度。所谓人以群分,天健学社正是像尹慧金这样的一群求真进步的青年学子的学习团队。如果说天健学社是“邪教组织”,尹慧金是“邪教魔头”,这简直是无耻荒谬。

然而为什么如此荒唐的事情居然会发生,而且连张健柏老师也被无辜的牵扯进来做了牺牲品。这不得不让人会怀疑团委那些所谓的老师们的“险恶用心”。事情发生了,按常理应该调查真相,合理解决。即便是学生采用静坐的方式不当,团委老师以及辅导员的工作不正是对他们进行引导教育和帮助吗?作为尚未走出校门的学生,他们还很年轻,甚至单纯幼稚,心中只有渴望知识的热情,追求进步的冲动。这一点我自己也深有体会。如果团委老师能以宽宏大量的胸襟,理解他们求学急切的心情,同情他们被逼无奈的处境。从学生的角度加以循序善诱,使他们能正确认识自己错在那里,从而今后注意到方式方法,避免再次碰壁。这不正好发挥出团委作为思想教育工作者的巨大作用吗?

然而不幸的是,他们却无辜又无助的沦为“邪教份子”,也许一辈子洗都洗不清。各位团委老师,你们怎能如此很毒。用他们的大好前途来当作你们玩弄权利的靶子,当作你们弥补过失的替罪羊。这种行径,让我想起了书中曾经读到过的,在文革中整右派的手段。怎么在共创和谐的今天,这种如此卑劣的行为竟会发生在百年武大。

学生如此惨淡,连老师也跟着受害。难道就因为他们请的主讲人是张老师吗?连事实都尚未调查清楚或者根本就没打算调查,便强行封杀老师的课。这简直就是滥用职权,打压老师。更何况还有如此多的同学眼巴巴的期盼着这个课程的后续内容,就这么突然间没有了。甚至连个合理的说法也不给。他们会不会有失落,会不会有不甘,会不会有愤怒。而这些难道团委的老师就真的根本不在乎吗?学校是为学生服务的。而现在学生喜欢的课被停掉了,学生拥护的老师被压制了。这叫服务吗?这分明就是致学生的心愿于不顾。

 

张老师被迫“下课”了,损失最大的就是那些好学的学生。假如我们从张健柏老师那里学到的智慧可以用金钱来衡量的话,又该是多少呢?据我了解张老师创办的今日学堂,学费是每个孩子每年三万元,而且限制招生,每年只招一二十名,总有不少家长不得其门而入。除去假期周末,平均下来每天是一百多元。可是这么高的学费,张老师并不亲自教学。他只负责培养老师(也就是他的弟子),学堂的具体教学工作由弟子们来承担。如果听张老师的课要收费的话,比照学堂小孩的学费,我们每天就要付一百多元。考虑到张老师的水平至少在弟子的十倍以上,我们应付的学费大概是每天两千元,这正好是商学院EMBA学员的付费标准,张老师也上过他们的课。单从经济上说,我们武大学生大多数是付不起的,即便还是“儿童级”的学费。然而张老师为我们所做的这一切都是免费的。不但如此,他还从繁忙之中抽出休息的时间,自己提供学习场地为广大学生传授更多的东西。他作为一个老师,真正是在身体力行“传道授业解惑”的古代师道。

可是,这样一位为学生所崇敬的老师,就这样黯然消失于武汉大学——这所世界上最美丽的大学当中。听起来多么可笑而又无奈。大学非有大楼,更非有美景之谓大,而是有了大师才之谓大。空有大楼美景的地方只能算是供人游赏的公园而已。然而学校此举我真的无言以对。真的难以想象武汉大学变成樱花游园的样子。无论何时我们这些做学生的都会铭记师恩,都会期盼母校辉煌。

Patterns in Python

site from http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html

Patterns in Python

Author: Duncan Booth
Contact: duncan@rcp.co.uk 

Abstract

What design patterns are applicable to Python? Some patterns are an intrinsic part of Python, other patterns require some careful coding to get the best from them. What new patterns appear in Python?

1   What is a pattern?

The definitive reference book Design Patterns [GoF] describes a set of patterns for object-oriented software design. This book is often referred to as the 'Gang of Four' book (or even GoF) after the four authors (Gamma, Helm, Johnson and Vlissides).

A design pattern describes a problem that occurs over and again and the core of a solution to that problem in such a way that it may be used in many different ways. That last point is important, when we talk about design patterns in software, we aren't talking about things that can be neatly tied up into a class or library implementation and just used, we are talking about techniques that are applied in different ways. Recognising when the same technique is being used in a different context allows us to apply our experiences across a much wider domain.

The GoF introduced a pattern vocabulary to the software community. Each pattern as they describe it has:

  1. pattern name which is a handle used to describe a design problem. Using a name lets us have a common vocabulary with other software developers.
  2. The problem describes when to apply a pattern.
  3. The solution describes the elements that make up the design, their relationships, responsibilities and collaborations.
  4. The consequences are the results and trade-offs of applying the pattern. Recognising the consequences of applying a pattern in one situation lets us better evaluate how appropriate the pattern may be in another.

Design Patterns gives outline implementions of patterns in C++ (and a supplementary book translated many of them into Smalltalk). However, it is apparent that while some patterns are largely independant of the language in which they are implemented, others either become inappropriate in another language, or virtually disappear.

This paper looks at a few of the common patterns, identifies what if anything is their equivalent in Python, and also considers whether Python has its own patterns different than the C++ patterns.

Others have looked at how Design Patterns relate to Python, most notably Vespe Savikko [VS], and Alex Martelli [AM], but as Python evolves, the ways you can implement these patterns are changing.

1.1   A word of warning

I was reading an article by Ron Jeffries [RJ] recently where he wrote:

Small Boy with a Patterns Book

After spending a bunch of time thinking about these ideas, over a few days now, I finally recognized in myself what I call "Small Boy with a Patterns Book". You can always tell when someone on your team is reading the Gang of Four book (Gamma, et al., Design Patterns). Every day or so, this person comes in with a great idea for a place in the system that is just crying out for the use of Composite, or whatever chapter he read last night.

There's an old saying: To a small boy with a hammer, everything looks like a nail. As programmers, we call into the same trap all too often. We learn about some new technology or solution, and we immediately begin seeing places to apply it.

Patterns are useful, they can also be addictive. Try not to overuse them.

2   Creational Patterns

The GoF identified several creational patterns. These patterns abstract the process of instantiating objects.

2.1   Factory

The most fundamental of patterns identified by the GoF are probably the Factory and Abstract Factory. The Factory pattern in a language such as C++ wraps the usual object creation syntax new someclass() in a function or method which can control the creation. The advantage of this is that the code using the class no longer needs to know all of the details of creation. It may not even know the exact type of object it has created. In other words it reduces the dependencies between modules.

A more advanced form of factory (Abstract Factory) provides the extra indirection to let the type of object created vary.

The factory pattern is fundamental in Python: where other languages use special syntax to indicate creation of an object, Python uses function call syntax as the (almost) only way to create any object: some of the builtin types such as int, str, list, and dict, have their own special syntax, but they all support factory construction as well.

Moreover, Python uses abstract factories for everything. The dynamic nature of the system means that any factory may be overridden.

For example, the following code:

 import random
  def listOfRandom(n):
         return [random.random() for i in range(n)] 

At first sight it looks as though this function will return a list of 10 pseudo-random numbers. However you can reassign random at the module level, and make it return anything you wish. Although at first this may sound like a crazy thing to do, in fact it is one of the reasons why Python is such a great language for writing unit tests. It is hard to write an automated test for a function with a pseudo-random result, but if you can temporarily replace the random number generator with a known, repeatable, sequence, you can have repeatable tests. Python makes this easy.

It is hard to say whether this really counts as a pattern in Python at all. At one level it is basic to the language, and does not involve actual code. On the other hand, the pattern is so well known that it is important to acknowledge that it corresponds to the Factory pattern.

Python 2.2 introduced a new way to control object creation. New-style objects (where object is the base class) allow a method __new__ to control the actual creation of the object. This may be seen as another form of the factory pattern, and one where there is actual Python code to implement it. We see more of this in the next section.

2.2   Singleton (and the Borg)

Intent

Ensure a class has only one instance and provide a global point of access to it.

One of the first patterns many programmers learn to identify as a pattern is the 'Singleton'. This is a pity, as in many ways it is rather more of an anti-pattern.

A singleton is an object which can only be instantiated once in a process. Not of course an object which you only happen to instantiate once, but rather an object which will resist all attempts to create multiple instances.

The singleton pattern is often used for a class controlling an application's access to a database, a network link to a server, a conection to the computer's registry and so on. This is a poor use of singleton. The application may only require a single database, but it isn't a requirement that there can only be one database connection. Maybe one day it will evolve into an application with two databases, so why write code to prevent that?

A more significant drawback of singleton is that it breaks testing. Unit tests often work by creating mock objects that look similar to real objects but have dummy implementations. If your code has built brick walls protecting that 'database' instance, then it becomes harder, or even impossible to temporarily stub it out (although very little is completely impossible in Python). Test driven development very quickly leads you to abandon large singletons.

Nevertheless, should you require it, it is easy to implement the singleton pattern in Python:

 >>> class Singleton(object):   
      _instance = None      
      def __new__(cls, *args, **kwargs):        
         if not cls._instance:         
            cls._instance = super(Singleton, cls).__new__(
                                    cls, *args, **kwargs) 
         return cls._instance   
>>> class C(Singleton):   
      pass  
 >>> class D(Singleton):    
     pass   
>>> c = C() 
>>> d = C() 
>>> id(c), id(d) 
(10049912, 10049912) 
>>> e = D() 
>>> f = D() 
>>> id(e) 
10113672 
>>> id(f) 
10113672 
>>> g = C() 
>>> id(g) 
10049912 
>>>  

This example creates a new mixin class Singleton. Each new subclass creates one instance and thereafter returns that instance. Further subclassing of C or D could be confusing, but by checking the type returned we can avoid the obvious errors.

It has been noted elsewhere [AM] that the requirement driving people to use the Singleton is not a requirement for a single instance at all. Rather it is a need for a shared state. This led Python Programmers to invent one of the few genuine Python Patterns with a name: The Borg.

The Borg pattern allows multiple class instances, but shares state between instances so the end user cannot tell them apart. Here is the Borg example from the Python Cookbook

 class Borg:
     __shared_state = {}
     def __init__(self):
         self.__dict__ = self.__shared_state
     # and whatever else you want in your class -- that's all! 

Problems with the Borg as a pattern start when you begin to write 'new style' classes. The __dict__ attribute is not always assignable, but worse any attributes defined within __slots__ will simply not be shared. The Borg is cool, but it isn't your friend.

There is another implementation of Singleton which is even simpler than the one given above. In fact, I'm sure every Python programmer has used this method, although many of them may have failed to recognise the Singleton pattern within it.

Consider this file (singleton.py):

"""This module implements the singleton pattern""" 

Simple, isn't it. You can access the singleton object using the import statement. You can set and access attributes on the object. Obviously in real life you might want a few methods, or some initial values, so just put them in the module.

Python modules are Singleton instances: another case of Python taking a design pattern and making it a fundamental part of the language.

3   Structural Patterns

3.1   Flyweight

Intent

Use sharing to support large numbers of fine-grained objects effeciently.

This is related to the singleton pattern. Whereas with singleton we wanted exactly one instance of an object, in some cases we need very many instances but not all of the objects need to be distinct.

For example, consider an application that handles stock market prices. Perhaps we have several portfolios, each of which contains a large number of underlying stock instruments. Each instrument holds some data (current and recent prices, daily high and low, etc.), but this data is common to the instrument wherever it is used. Each portfolio might record the amount of each instrument held, the date purchased, and the price at which it was purchased.

We have a choice here. We could store the portfolio specific data inside each instrument, but then instrument instances cannot be shared between portfolios. If we store them as part of the portfolio then we can have shared instrument classes:

# Model a financial instrument 
# The instrument class represents a financial instrument, 
# with updates arriving from some network source. 
# # N.B. As an example, this code is not threadsafe. 
# Real code might have to handle asynchronous updates to data. 
import weakref
  class Instrument(object):
     _InstrumentPool = weakref.WeakValueDictionary()
      def __new__(cls, name):
         '''Instrument(name)

         Create a new instrument object, or return an existing one'''
         obj = Instrument._InstrumentPool.get(name, None)
          if not obj:
             print "new",name
             obj = object.__new__(cls)
             Instrument._InstrumentPool[name] = obj
          return obj

      def __init__(self, name):
         '''Complete object construction'''
         self.name = name
         print "New instrument @%04x, %s" % (id(self), name)
          # ... connect instrument to datasource ...
  
  import unittest
  class InstrumentTests(unittest.TestCase):
     def testInstrument(self):
         ibm1 = Instrument("IBM")
         ms = Instrument("MS")
         ibm2 = Instrument("IBM")
         self.assertEquals(id(ibm1), id(ibm2))
         self.assertNotEquals(id(ibm1), id(ms))
         self.assertEquals(2, len(Instrument._InstrumentPool),
             "Total instruments allocated")
          # This bit assumes CPython memory allocation:
         del(ibm1)
         del(ibm2)
         self.assertEquals(1, len(Instrument._InstrumentPool),
             "Total instruments allocated")

  if __name__=='__main__':
     unittest.main() 

This code shows a simple way to create objects which share their state if they are created with compatible parameters. The two IBM objects are in fact only one object, but the MS object is separate.

If we run this code with the 'print' statements then we can see that although we only create two objects, the __init__ constructor is called all three times. This could be useful, for example, if we want the Instrument class to generate events to some Portfolio class further up the line.

D:\accu>instrument.py
 new IBM New instrument @7bd240, IBM new MS New instrument @7a80b8, MS New instrument @7bd240, IBM .
 ---------------------------------------------------------------------- 
Ran 1 tests in 0.020s  OK 

The weakref dictionary ensures that when nothing is actively using a particular instrument the storage for it may be automatically released. The actual behaviour of this may vary somewhat, for example the Java implementation of Python wouldn't actually release unused instruments until a garbage collection cycle.

4   Behavioural Patterns

4.1   Observer

Intent

Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Observer is one of the patterns I find myself using over and again, but until recently I never felt completely happy with my Python implementations of it.

You have two classes, the subject and an observer which registers itself with the subject and receives notification callbacks when data changes in the subject. I find the GoF form of this pattern somewhat limiting, because they describe a system where a subject class has a general 'notify' method used for everything (although they do suggest a mechanism for generating more selective events using aspects).

The implementation described here uses a more general, and I believe cleaner form of event generation which is based (loosely) on the event structure from Microsoft's .Net framework. It is best described starting with the intended use.

The actual example is taken from the GoF book, although of course the implementation is not. ClockTimer is a subject for storing and maintaining the time of day. It notifies its Observers every second.ClockTimer provides the interface for retrieving individual time units such as the hour, minute and second:

class ClockTimer:
         def GetHour(self):
                 return self._hour
         def GetMinute(self):
                 return self._minute
         def GetSecond(self):
                 return self._second
          TickEvent = Event()
         def OnTick(self):
                 ClockTimer.TickEvent.call(self, self.GetHour(),
                         self.GetMinute(), self.GetSecond())
          def Tick(self):
                 # update internal time-keeping state
                 # ...
                 self.OnTick() 

The Tick method gets called by an internal timer at regular intervals. It updates the internal state and calls the OnTick method to notify observers of the change.

The OnTick method fires the event with whatever parameters seem appropriate. Firing the event indirectly in this way allows subclasses to override the event handling.

Although we have a single Event in this class, the implementation allows for any number of different events to be defined.

Now, we can define a class DigitalClock that displays the time:

 class DigitalClock(Widget):
         def __init__(self, clockTimer):
                 self.__subject = clockTimer
                 clockTimer.TickEvent += self.Update
          def close(self):
                 self.__subject.TickEvent -= self.Update
          def Update(self, subject, hour, min, sec):
                 self.displayedTime = (hour, min, sec)
                 self.Draw()
          def Draw(self):
                 # draw the digital clock 

N.B. We need an explicit close method to be called on this object because there is a circular dependency (ClockTimer contains a reference to the UpdateMethod of the DigitalClock instance, and the DigitalClock instance stores a reference to the clockTimer). This means that a __del__ method would never be called. In cases where this could be a problem, one solution would be to define a WeakMethod class that simulates a bound method but only holds a weak reference to the instance.

The plumbing that allows this to work is as follows:

class Delegate:
     '''Handles a list of methods and functions
     Usage:
         d = Delegate()
         d += function    # Add function to end of delegate list
         d(*args, **kw)   # Call all functions, returns a list of results
         d -= function    # Removes last matching function from list
         d -= object      # Removes all methods of object from list
     '''
     def __init__(self):
         self.__delegates = []
      def __iadd__(self, callback):
         self.__delegates.append(callback)
         return self
      def __isub__(self, callback):
         # If callback is a class instance,
         # remove all callbacks for that instance
         self.__delegates = [ cb
             for cb in self.__delegates
                 if getattr(cb, 'im_self', None) != callback]
          # If callback is callable, remove the last
         # matching callback
         if callable(callback):
             for i in range(len(self.__delegates)-1, -1, -1):
                 if self.__delegates[i] == callback:
                     del self.__delegates[i]
                     return self
         return self
      def __call__(self, *args, **kw):
         return [ callback(*args, **kw)
             for callback in self.__delegates] 

The delegate class maintains a list of callbacks (so we can have several observers for a single subject). The only operations supported on a delegate are to add a function, remove a function or call all of the functions in the delegate. The callback functions are stored in order (so first added is also first called), and removed in last in/first out order.

We could create the Delegate instances in __init__, but there is a potential drawback to this. If we created a class that could fire many events, but events mostly went unused, we should have a lot of delegates created for no reason. The Event class below creates delegates only when they are needed, and the indirect call used in the subject class supports this:

class Event(property):
     '''Class event notifier
     Usage:
         class C:
             TheEvent = Event()
             def OnTheEvent(self):
                 self.TheEvent(self, context)
          instance = C()
         instance.TheEvent += callback
         instance.OnTheEvent()
         instance.TheEvent -= callback
     '''
     def __init__(self):
         self.attrName = attrName = "__Event_" + str(id(self))
         def getEvent(subject):
             if not hasattr(subject, attrName):
                  setattr(subject, attrName, Delegate())
             return getattr(subject, attrName)
         super(Event, self).__init__(getEvent)

      def call(self, subject, *args, **kw):
         if hasattr(subject, self.attrName):
             getattr(subject, self.attrName)(subject, *args, **kw) 

Within the ClockTimer class a reference to instance.TickEvent will create the Delegate. The Delegate could be called using self.TickEvent(args), but this would always create it. By calling it instead using ClockTimer.TickEvent.call(args) we avoid doing this unneccessarily.

4.2   Iterators and Generators

Intent

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

The iterator pattern is one which Python has embraced fully, albeit in a slightly simpler form than the one proposed by the GoF. GoF iterators have methods:

 First()
 Next()
 IsDone()
 CurrentItem() 

Python's iterator interface requires the following methods to be defined:

 __iter__()
      Returns self next()
          Returns the next value or throws StopIteration 

In addition, any object which supports iteration, but is not itself an iterator supports the iterable interface, i.e. it has a method __iter__() which creates a new iterator object of the appropriate type. It may also have additional methods for creating different types of iterator, but this is not required by the language.

The main difference in Python is that Python's iterators cannot be reset. If you want to iterate over a sequence more than once in Python, then you simply have to create multiple iterators.

Here is a simple example using Python's iterators to iterate over a binary tree structure. This involves walking the tree, and because each value is returned in order we must remember which nodes have been processed, and which we have yet to see. We could write the code recursively if we didn't need to keep suspending the iterator to return a result, but handling a stack manually in Python is actually pretty straightforward:

class Node(object):
     class NodeIterator:
         def __init__(self, node):
             self.stack = [node]
          def __iter__(self):
             return self
          def next(self):
             if not self.stack:
                 raise StopIteration
              node = self.stack.pop(-1)
             while isinstance(node, Node):
                 self.stack.append(node.right)
                 node = node.left
             return node
      def __init__(self, left, right):
         self.left = left
         self.right = right
      def __iter__(self):
         return Node.NodeIterator(self)

  import unittest
 class NodeTests(unittest.TestCase):
     def testNode(self):
         tree = Node(
                   Node('a', 'b'),
                   Node(
                       Node('c', 'd'),
                       'e'))
          self.assertEquals(['a', 'b', 'c', 'd', 'e'], list(iter(tree)))

  if __name__=='__main__':
     unittest.main() 

The main problem with this code is that it isn't immediately clear why it works. Why, if I want to return the left side of each branch before the right do I have to deal with the right node first? Why do I never (apparently) return the right hand node of anything?

Iterators often involve thinking backwards in this way. First we maintain our state so we can resume the iterator later on, then we wory about what to return on this iteration.

Also, of course, the unit test obscures the normal use of this code. Where I simply convert the iteration into a flat list to check that all the leaves came back in the correct order, normally we would have some code more like:

for leaf in tree:
         ... do something with the leaf ... 

Generators

Since Python 2.2 there has been special syntax in the language to make it easier to write iterators. Generators turn the process of iterating over an object on its head. The iterator object exists solely to maintain the state of the iteration, this is usually some sort of loop index, but in some cases the data structures can be much more complex. For example the same binary tree structure using a generator becomes:

from __future__ import generators
  class Node(object):
     def __init__(self, left, right):
         self.left = left
         self.right = right
      def __iter__(self):
         if (isinstance(self.left, Node)):
             for n in self.left:
                 yield n
         else:
             yield self.left
          if (isinstance(self.right, Node)):
             for n in self.right:
                 yield n
         else:
             yield self.right

  import unittest
 class NodeTests(unittest.TestCase):
     def testNode(self):
         tree = Node(
                   Node('a', 'b'),
                   Node(
                       Node('c', 'd'),
                       'e'))
          self.assertEquals(['a', 'b', 'c', 'd', 'e'], list(iter(tree)))

  if __name__=='__main__':
     unittest.main() 

The code isn't actually any shorter, but walking the tree has now become rather more obvious. If the left side is another node then we yield each leaf in turn, otherwise we just yield the leaf. Then we repeat on the right side either yielding each leaf in turn or yielding the leaf if that is all we have. Without the generator we were forced to abandon the 'obvious' recursive implementation, but the generator lets us suspend execution as each result is generated.

Other benefits of the generator are that it hides the need for another object type, and (rather suprisingly) it turns out that using a generator is actually much faster than simply calling a Python function repeatedly.

itertools

Iterators and generators may be combined to form pipelines, and the upcoming Python 2.3 includes a new builtin module with a variety of useful iterators. Because these iterators generate each result only as it is returned they provide a way to work with potentially infinite lists:

count([n])
Return consecutive integers starting with n
ifilter(predicate, iterable)
Return all elements x of iterable for which predicate(x) is true.
imap(function, *iterables)
Like map(), but returns an iterator rather than a list.
izip(*iterables)
Like zip(), except it returns an iterator.
repeat(obj)
Returns an iterator that yields obj an unlimited number of times.
times(n, [object])
Returns object a total of n times.

and many more.

It is too early to see how the Python community takes to this new support for iterators. So far there seem to be those (like myself) who see almost every problem as an opportunity for generators, and those who are steering well clear.

4.3   Command Dispatch Pattern

The GoF describe a Command pattern where a request is encapsulated as an object. Back in 1997, Guido van Rossum [GvR] identified a pattern that performs a similar function, but which is unique to dynamic languages such as Python, Perl &c. He gave it the name Command Dispatch.

Sadly, although use of this pattern is common through many Python programs, the name, and perhaps also the identification of this as a pattern, have largely been forgotten.

Suppose you have a class that needs to execute a number of different commands sent from some outside source. e.g. 'get()' and 'put()'. There are various ways to handle this such as:

if command == 'get':
     get()
 elif command == 'put':
     put()
 else:
     error() 

or:

dispatch_table = {
     'get': get,
     'put': put, }
  # Command dispatch:
if dispatch_table.has_key(command):
     func = dispatch_table[command]
     func()
else:
     error() 

but the one used by Python programmers everywhere is:

class Dispatcher:
      def do_get(self): ...
      def do_put(self): ...
      def error(self): ...
      def dispatch(self, command):
         mname = 'do_' + command
         if hasattr(self, mname):
             method = getattr(self, mname)
             method()
         else:
             self.error() 

As Guido put it: I find this approach super elegant and have used it many times.

You can find this pattern used throughout Python's libraries, including BaseHTTPServer, cmd, pydoc, repr, sgmllib, SimpleXMLRPCServer, urllib, distutils and so on.

5   Little patterns in Python

There are many other common idioms in Python which (depending on your viewpoint) are certainly patterns, although they are perhaps too small to count as Design Patterns. However, even if they don't count as fully fledged Design Patterns, the small patterns listed here are representative of how writing software in Python influences the way you think.

DSU

Decorate, Sort, Undecorate. The way in Python to do any but the simplest sorting. Instead of providing a comparison function for your objects, simply replace a list of objects with a list that sorts into the desired order using the builtin functions.

For example, to produce a list of files in the current directory sorted by their 'last modified' time:

 >>> files = glob.glob('*')
 >>> decorated = [ (os.stat(file).st_mtime, file) for file in files ] 
>>> decorated.sort()
>>> files = [ file for (time, file) in decorated ] 
>>> print files ['py.ico', 'pyc.ico', 'pycon.ico', 'default.tag',
      ... (long list of files here)
 ... 'Doc', 'Tools', 'INSTALL.LOG', 'win32', 'win32com', 'Lib'] 
>>>  

List comprehensions

Introduced in Python 2.0, list comprehensions let you build new lists by writing a description instead of a series of commands. This lets you think about what you are writing in a different way, which is one of the important features of design patterns, although the list comprehension on its own is too small to be a major pattern.

Bound methods

Coming to Python from other languages where functions and methods are not first class methods requires a definite mental gearshift. A common Python technique is to pass around bound methods or use them for micro-optimisations. e.g.

result = []
save = result.append
while somecondition:
     save(calculateValue()) 

Lists, tuples, and dictionaries

Everything in Python is an object, but not everything has to be a user-defined object. Thinking in terms of the builtin types is important to Python programmers. Partly this is because the builtin types can run faster or be less memory hungry, but there is another bonus in that code is often easier to understand when it uses more primitive but familiar types rather than customised classes everywhere.

Module as a script

Write every module as a script in Python (and the inverse, write every script as a module). By encapsulating the main code of a script in a block headed by if __name__=='__main__', any classes or functions in the script can be reused in other programs. Likewise adding the same block to a module allows tests use of the module outside the context of the program.

6   Conclusion

Design Patterns are very useful tools. They give you a language for thinking about the design and allow you to recognise familiar problems in new contexts. Recognising a pattern lets you immediately relate that pattern back to previous experiences both good and bad.

Some patterns are almost universal across programming languages but other patterns are specific to the features or even the syntax of a particular language. To become fluent in a programming language means not just understanding the syntax but also adopting a common pattern of thought with the other developers.

Even within a language possible implementations of patterns change as the language evolves. The examples given in this paper use new style classes, weak references, and properties. All features added to Python comparatively recently.

7   References

[GoF] Design Patterns, Elements of Reusable Object-Oriented Software; Erich Gamma, Richard Helm, Ralph Johnson, Jon Vlissides; 1995.
[AM] (12) Five Easy Pieces: Simple Python Non-Patterns; Alex Martelli, AB Strakt. http://www.aleax.it/Python/5ep.html
[VS] Design Patterns in Python; Vespe Savikko, Tampere University of Technology. http://www.python.org/workshops/1997-10/proceedings/savikko.html
[GvR] Command Dispatch Pattern; Guido van Rossum; Python Pattern-SIG mailing list, May 1997
[RJ] Adventures in C#: Some Things We Ought to Do; Ron Jeffries; Jan 2003 http://www.xprogramming.com/xpmag/acsMusings.htm

2008年11月7日星期五

初入职场“七宗罪”之――没事偷着乐

本文摘抄自http://info.china.alibaba.com/news/detail/v5003013-d1003297353.html
送与自己自勉


  "没事偷着乐"是《贫嘴张大民的幸福生活》中,生活在社会底层的主人公历经艰辛之后的一句无奈的感叹。但在有些人心中,它"升华"成了一种生活态度――厌 恶劳动,害怕艰苦,贪图享乐。但事实上,大多数情况下,这种生活态度的表现并非如此明显,它通常以各种很微妙的方式表现出来。

    两个大学生,一条起跑线

    曾经有两个应届大学毕业生D君和Q君,同时被公司招聘进来。两个人的学历相当,能力差别也不明显。原本的计划是要将二人培养成为优秀的编辑,以接替即将离职的老编辑。但是,干起活来两人不同的工作态度就完全表现出来了。

    新 手初上岗,就先让他们对将来的工作有所熟悉。对于大学生来说,修改、校对文章这些工作应该是很简单的,很快两人就做完了。忙完了一期杂志最紧张的排版出版 阶段,接下来的一个星期,办公室的空气显得有几分轻松。不过,老编辑都各有各的栏目,做完了上一期杂志,就有条不紊地开始准备下一期了。这两位新编辑此时 在干什么呢?

    没事偷着乐

    记得小时候,在家没事自顾玩,不帮忙收拾家务。老妈就骂我:"成了癞蛤蟆,不捅不跳!"没想到,大学毕业生中,也还有练就这种蛤蟆神功的高手。

   Q 君无事可干,开始上网看新闻。看新闻看腻味了,又开始和QQ上的好友疯狂聊天。聊得无趣了,就开始在QQ上搜索"谁在线上",专门找闲人聊天。公司有明文 规定,禁止上班时间玩游戏。于是他就苦等到中午下班休息时间跟其他同事玩上一把。下午上班,他也玩累了。于是就趴在桌子上打起了瞌睡。当然,堂堂大学生, 哪能这样天天呼呼大睡?过了几天,他带来一本书,下午无事就坐在办公室看起书来。原以为他在看英语或者计算机专业书,谁知编辑部副主任悄悄告诉我,他"无 意中"看到了那本书的名字。原来是本玄幻小说!

    唉……我几乎都要为他感到有几分悲哀了。让年轻人一连几天按时到公司来无所事事,也真难为他了。

    没事找事做

   D 君在做什么呢?虽然比Q君晚了一点,但是D君也很快完成了分配给他的工作任务。而后,他翻看了一下以前的杂志,跑到一位老编辑的桌边:"刘老师,给点活儿 干吧。"老刘编辑惊讶地看了他一眼,说:"哦,你等会儿吧。"谁知D君等了一会儿,又跑到另外一个老编辑身边:"张老师,给安排点事儿干吧。"

    他厚着脸皮跑到一个个老编辑那里讨活儿干。终于有些老编辑又给他一些简单的稿件,他拿着稿子就像得到了宝贝似的,三步并作两步赶回自己的座位,埋头开干了。做好了,又跑回老编辑那里:"刘老师,您看这样行吗?""张老师,您给指点指点?"

    于是老编辑们多多少少都对他的工作错误加以指点。后来发觉他干得不错,就慢慢把一些复杂的稿子交给他了。D君的业务能力水平由此开始直线攀升。

    而此时,Q君还在聊天、睡觉,看玄幻小说。

    截然不同的表现

    有 一天大家来到公司干了不到半小时,突然停电了!这时干什么好?不少老编辑都毫无准备,一方面着急工作进度,一方面却又无可奈何。于是纷纷打听何时来电,得 知"正在抢修"之后,也只好回到自己的座位翻看一下杂志。有的老编辑聚在一起吹牛,编辑部主任没有干涉――因为大家平时自由沟通交流的机会确实也不多。大 家都没有离开办公室,供电一恢复,就可以立即继续工作。

    过了半小时,来电了。大家赶快回到自己的位置开始工作。这时候,D君和Q 君却不见踪影了。我去找资料的时候,发现D君坐在会议室里面。原来他觉得办公室里面有几个老编辑在聊天,太吵,正好手头有几份打印出来的稿子,就躲到会议 室去改。我告诉他已经来电了,他立即收拾东西回了办公室。等我回到办公室,Q君依然不在。又过去了大约一小时,Q君回来了――他和读者服务部的MM一起上 楼顶放风筝去了!

    两种结局,一个道理

    一个月下来,新一期杂志的几大栏目都有了D君负责编校的文章。而Q君仍然只负责完成了几篇简单文章的编校。所有这些,编辑部的头儿看在眼里记在心里。于是,两个月过去,D君提前转正,独立负责一个小栏目;Q君却没有通过试用期考核,被解聘了。

    公司不是学校。虽然有工作任务的分配,但是没人会像学校的老师那样,从早读到晚自习,全面安排好你的课程表。通常情况下,只有工作任务和质量考核。如果你能 轻松完成分配给你的工作任务,你自认为能力强,价值高,却被埋没在一些简单工作里面,怎么体现出来?我想唯一的办法,就是主动去寻找,去做一些能体现你自 身价值的事情。

    "没事偷着乐"这种生活态度,在社会中有很多信徒。有人没监督就要偷懒,有人没检查就要出错,有人没加薪就坚决不多干一份活儿。他们还有一个共同点,就是羡慕成功人士的名誉、地位和物质生活,却总是忽视他们背后的艰辛。你是不是其中的一员呢?

2008年11月4日星期二

在Solaris 10下用SMF配置Subversion

Solaris 10下配置subversion有如下几个关键点:
  1. 获取subversion
  2. 配置subversion
  3. 设置subversion为系统服务
在获取subversion的时候,直接从subversion的官方网站难以获得二进制版本,最后用的是pkg-get从blastwave.org上获取的。参见www.blastwave.org/howto.html吧,要记得更新pkg库

花了不少时间从blastwave上down下二进制的subversion以及subversion的dependece二进制

subversion中的程序默认下载在/opt/csw/bin下面了

第二步配置subversion还是很简单的,从网络上能找到很多

第三步配置subversion成系统服务,以自动启动的方式运行。这里网络上很多都是用init.d/rc*.d这样的方法来弄,不过呢,这些已经是不建议的方式了。
solaris 10里面建议用SMF来完成管理,确实很方便。
具体的SMF就不讲了,Google下或者去sun的Bigadmin里面能看到很多。

(因为现在是根据回忆来写,有些路径或者文件名可能会打错。。。。)
我这里配置subversion是参考了/var/svc/manifest/network/utmp.xml这个文件,因为我的subversion也是一个network服务,类似utmp需要依靠多用户run-level
所以写了个subversion.xml如下
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='export'>
  <service name='network/subversion' type='service' version='0'>
    <create_default_instance enabled='true'/>
    <single_instance/>
    <dependent name='svnserve_multi-user' restart_on='none' grouping='optional_all'>
      <service_fmri value='svc:/milestone/multi-user'/>
    </dependent>
    <!-- 以脚本启动-->
    <exec_method name='start' type='method' exec='/lib/svc/method/svc-subversion' timeout_seconds='60'>
      <method_context/>
    </exec_method>
<!-- 以kill方式将服务进程干掉,这是有subversion的管理方式决定的,干掉svnserve进程-->
    <exec_method name='stop' type='method' exec=':kill' timeout_seconds='60'>
      <method_context/>
    </exec_method>
    <stability value='Unstable'/>
    <template>
      <common_name>
        <loctext xml:lang='C'>Subversion monitoring</loctext>
      </common_name>
    </template>
  </service>
</service_bundle>


然后写了个启动的shell脚本: subversion
#! /usr/bin/bash

# Start the subversion server
/opt/csw/bin/svnserve -d -r /export/home/svn/svn/repos/

用svccfg import subversion.xml导入到管理库里面,将subversion这个脚本添加执行权限,并拷贝成/lib/svc/method/svc-subversion

然后svcs |grep subversion看看运行状态,如果是online就OK了

可以通过 svcadm disable subversion
svcadmin enable subversion
svcadmin restart subversion
来管理这个服务

更多的看man svccfg 和 svcadm

通过 svcs -xv subversion可以诊断故障

有问题看看/var/svc/log/network-subversion的日志

2008年10月13日星期一

在Windows环境下编译SendIP的问题总结

以下是SendIP的介绍,我主要是想用这个东西来发伪造的数据包,可惜在俺的D版的Windows XP SP2上还是不通。
SendIP is a tool to send completely arbitrary packets out over the network.
In conjunction with PackPrint (see
http://www.earth.li/projectpurple/progs/packprint.html), this makes an
extremely powerful debugging tool for networks.

SendIP目前支持如下协议:
Here is a list of protocols that SendIP currently understands:
* IPv4 (but see below section 7)
* TCP
* BGP
* ICMP
* UDP
* RIP
* NTP
* IPv6 (except on solaris)
* ICMPv6
* TCP
* UDP
* RIPng
* NTP?

Other protocols will be added in future versions, as and when I have time
to add them.

Of course, it is still possible to send packets using other protocols, but
you have to construct the packet data and headers entirely by hand.


因为这东西只提供了Linux和Solaris下的版本,我猜可能国外的人私人都用不起Windows……
我就在Cygwin下想将其编译看看。
结果遇到如下问题:
  1. 在编译的时候,遇到了gethostbyname2这个函数未定义……
  2. gcc的-fPic等选项不支持
第一个问题么,我知道gethostbyname是在netdb.h这个头文件中声明的,gethostbyname2不清楚。google 关键字cygwin+gethostbyname2发现,gethostbyname2也是在netdb上声明,但是从http://win6.jp/Cygwin/index.html这上面知道,现在最新版本的cygwin并没有支持IPV6,需要从这个网址上下载补丁。
下载后按照里面的README很快的就解决了第一个问题

第二个问题也简单,直接将Makefile里面相关的编译选项去掉就可以了




最后编译好了,就开始运行了……

$ ./sendip -p ipv4 -p tcp -d r99 x.x.x.x
sendto: Interrupted system call

faint!!!!
$ ls
CHANGES contrib gnugetopt1.o ipv6.so sendip.1 tcp.so
LICENSE csum.c help2man ntp.c sendip.c types.h
Makefile csum.o icmp.c ntp.h sendip.exe udp.c
README cygwin1.dll icmp.h ntp.so sendip.o udp.h
TODO dummy.c icmp.so rip.c sendip.spec udp.so
VERSION dummy.h ipv4.c rip.h sendip.spec.in
bgp.c gnugetopt.c ipv4.h rip.so sendip2.exe
bgp.so gnugetopt.h ipv4.so ripng.c sendip_module.h
compact.c gnugetopt.o ipv6.c ripng.h tcp.c
compact.o gnugetopt1.c ipv6.h ripng.so tcp.h


$ fgrep "Interrupted system call" *
Binary file cygwin1.dll matches

看来这个错误是在Cygwin下封装了。

最后想起了,MS在winXP SP2版本后就对发送raw packet进行了限制
C:\Documents and Settings\Administrator>net helpmsg 10004

一个封锁操作被对 WSACancelBlockingCall 的调用中断。
发送伪造的数据包将被WSACancelBlockingCall中断。


解决方法应该是用驱动直接发包。。。。。。


可以参考winpcap + libnet +自己的code来实现吧

郁闷,还以为有现成的工具呢,自己写的话,就是组装包比较麻烦。

可以参考参考tcpReplay-Win32或者JPcap,封装的都还挺好。