2009年2月17日
John Borthwick 在 Google Next Victim Of Creative Destruction? 一文中闡述了AOL 的死亡以及產(chǎn)業(yè)的不斷循環(huán), yahoo, ebay 等已經(jīng)成為技術(shù)革新的受害者.
隨著搜索的垂直分割, 搜索市場也被細(xì)化
1. 視頻搜索的突起, youtube 從2007.10 到 2008.10 的搜索增長了114%, 占了google 搜索的26%.
2. 實時消息的發(fā)展, 以twitter 為代表, 市場對突發(fā)事件的要求的強烈, 使得twitter 迅速發(fā)展, twitter 的搜索(http://search.twitter.com/)與傳統(tǒng)引擎依賴內(nèi)容相關(guān)以及鏈接關(guān)系相比, 更注重時間的相關(guān)性.
Gerry campbell 的文章 Search is broken – really broken. 的一個圖說明了這種趨勢

2008年12月19日
Python 的logging 模塊的Socket 和 Logging4cplus 的 socket 的格式是不一樣的, 現(xiàn)實中需要將日志發(fā)送到logging4cplus 的服務(wù)器, 不得已, 寫了個 Python logging 模塊到 logging4cplus的Adapter
1 #!/usr/bin/env python
2 #-*- coding: gbk -*-
3 from struct import pack, unpack
4
5 class BufferPack(object):
6 def __init__(self):
7 self.buffer = ''
8
9 def addChar(self, s, unsigned=False):
10 self.buffer += pack(unsigned and '>b' or '>c', s )
11
12 def addShort(self, s, unsigned=False):
13 self.buffer += pack(unsigned and '>H' or '>h', s )
14
15 def addInt(self, s, unsigned=False):
16 self.buffer += pack(unsigned and '>I' or '>i', s )
17
18 def addLong(self, s, unsigned=False):
19 self.buffer += pack(unsigned and '>L' or '>l', s )
20
21 def addString(self, s):
22 self.addInt( len(s) )
23 self.buffer += s
24
25 def addBuffer(self, s):
26 self.buffer += s.buffer
27
28 class BufferUnpack(object):
29
30 char_bits = len( pack('>b', 0) )
31 short_bits = len( pack('>H', 0) )
32 int_bits = len( pack('>I', 0) )
33 long_bits = len( pack('>L', 0) )
34
35 def __init__(self, buffer):
36 self.buffer = buffer
37 self.pos = 0
38
39 def _read_item(self, unpackstr, len):
40 v = unpack(unpackstr, self.buffer[self.pos:self.pos+len] )
41 self.pos += len
42 return v
43
44 def readChar(self, unsigned=False):
45 return self._read_item(unsigned and '<b' or '<c', self.char_bits)
46
47 def readShort(self, unsigned=False):
48 return self._read_item(unsigned and '<H' or '<h', self.short_bits )
49
50 def readInt(self, unsigned=False):
51 return self._read_item(unsigned and '<I' or '<i', self.int_bits )
52
53 def readLong(self, unsigned=False):
54 return self._read_item(unsigned and '<L' or '<l', self.long_bits )
55
56 def readString(self):
57 len = self.readInt()
58 v = self.buffer[self.pos:self.pos+len]
59 self.pos += len
60 return v
61
62 def PackMessage( record ):
63 bp = BufferPack()
64 bp.addChar(2, True)
65 bp.addChar(1, True)
66
67 bp.addString("{log.servername}")
68 bp.addString(record.name)
69 bp.addInt(record.levelno*1000)
70 bp.addString("")
71 bp.addString(record.msg)
72 bp.addString(str(record.threadName))
73 bp.addString(str(record.process))
74 bp.addInt( record.created )
75 bp.addInt( record.msecs )
76 bp.addString(record.filename)
77 bp.addInt( 1 )
78
79 pkg = BufferPack()
80 pkg.addInt(len(bp.buffer), True)
81 pkg.addBuffer( bp )
82
83 return pkg.buffer
84
85 if __name__=="__main__":
86 import logging, logging.handlers
87
88 logger = logging.getLogger()
89 logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc)
90
91 hdlr = logging.handlers.SocketHandler('{logserver.ip}', 8888)
92 formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
93 hdlr.setFormatter(formatter)
94 logger.addHandler(hdlr)
95 logger.setLevel(logging.NOTSET)
96
97 logger.info("hello")
使用的時候.
1. 在logging 創(chuàng)建SocketHandler 的時候, 需要修改logging.handlers.SocketHandler.makePickle 為方法 PackMessage
logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc)
2. 需要修改代碼中的兩部分內(nèi)容 {log.servername} 和 {logserver.ip}
2008年12月4日
BHO就是Browser Helper Object(瀏覽器輔助對象)
BHO關(guān)聯(lián)原理 (BHO關(guān)聯(lián)的是SHDOCVW,也就是說不只關(guān)聯(lián)IE,下面全部用IE來說明)
1.IE的窗口打開時,先尋找HKLM下的SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\ 里的CLSID,這些CLSID,都對應(yīng)著相應(yīng)的BHO插件,然后根據(jù)這個CLSID到HKCR下的CLSIDs里找到此插件的信息,包括文件位置等。
2.IE根據(jù)找到的CLSID信息創(chuàng)建 BHO 對象,并且查找 IObjectWithSite 接口. (這個接口非常簡單,只有SetSite和GetSite兩個方法)
3.IE把IWebBrowser2(瀏覽器插件)傳到 BHO 的 SetSite 方法,用戶在此方法中可掛載自己的事件處理方法。
4.窗口關(guān)閉時,IE把 null 傳到 BHO 的 SetSite 方法,此方法用來去掉掛載的事件處理方法。
編寫B(tài)HO流程
1.創(chuàng)建IObjectWithSite顯式接口,創(chuàng)建 COM 類型,實現(xiàn)繼承IObjectWithSite接口
2.實現(xiàn)此接口并在SetSite方法里加上所要掛載的事件
3.處理事件
4.注冊此BHO到注冊表中HKLM下的Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects;(HKCR下的CLSIDs是根據(jù)上面的路徑自動注冊的)
5、.net 下須設(shè)置此BHO項目的 配置屬性_>生成 中為Interop注冊為True,這樣才能將.net 類庫文件注冊到COM
刪除BHO
打開注冊表項到:HKLM下的Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects 可以看到下面有一些CLSID值,這些值對應(yīng)相關(guān)的插件,點擊可以在默認(rèn)值后看到相關(guān)插件的名稱!可以復(fù)制相關(guān)CLSID到注冊表中搜索相關(guān)CLSID,找到后打開InprocServer32可以看到相關(guān)文件的路徑,至于DLL文件等可以用UEDIT32.exe工具打開查看具體信息,當(dāng)然也可以用修改程序類的eXeScope.exe研究一下!
請根據(jù)具體情況刪除相關(guān)鍵值和相關(guān)文件!
REF:
BHO 的編寫
VCKBase 關(guān)于IE 編程文檔中心
C++中使用BHO來屏蔽特定網(wǎng)站
瀏覽器集成教學(xué) 自定義瀏覽器
2008年10月29日
zz http://littletutorials.com/2008/07/07/success-as-technical-lead/
分為3個部分
Set yourself up for success
Build your relationship with the team
Build your relationship with the management and business people
Set yourself up for success
1. Define early on what success means for you, the team and the business
You have to have a clear idea of what you want. You also have to understand what team members and the management want. You also have to be aware that what people really want, what they say the want and sometimes even what they think they want are very different things. Try to be very honest at least with yourself. Success has different definitions for different people. If there is a big disconnect between these definitions you have a problem before you start.
2. Believe in the project: idea, architecture, time, team
You cannot have any kind of success if you are convinced you lead a team of morons to implement a stupid idea using the wrong architecture in a ridiculously short time. You have to really believe in the project to have a chance to success. This does not mean lie to yourself. It means do whatever you can to understand your concerns and work on them with the management. As for the architecture, it is best if you have a heavy word or if you are the architect.
3. Understand the domain, the business requirements and the technical challenges
You should be an expert in the technologies used for implementation. You also have to become very knowledgeable in the problem domain and the business case. This will help you understand the business decisions dropped on your head from upstairs and also will help you stand a chance at negotiating them.
4. Know your team: strengths, weaknesses, ambitions and personalities
Software is created by people. Your job as a “tech lead” is to support them in doing that, both from a technical point of view and at a human level. You want to lead a team of motivated and enthusiastic people. But each person gets motivated by different things.
5. Have a plan as a result of a planning activity
“Plans are useless but planning is essential” - (Dwight D Eisenhower, US President, general 1890-1969). Planning will make you think about the problems you face in detail. Also keep in mind that “a plan is just a list of things that ain’t gonna happen” - (Benicio Del Torro in “The Way of the Gun”).
6. Be part in the design of everything
This does not mean do the whole design. You want to empower team members. But your job is to understand and influence each significant subsystem in order to maintain architectural integrity.
7. Get your hands dirty and code
Yes you should take parts of the code and implement them. Even the least glamorous parts. This will help you not getting stuck alone between management and the team. It will also help you gain respect in the team.
8. Act as a communication proxy for your team
In long complex projects with big teams communication is one of the most complicated aspects. The more people you have involved in solving a problem the bigger the communication matrix becomes. Since people need information to be able to make the right decisions this will lead to an exponential increase in the time consumed for communication. Agile methodologies alleviate this problem. But in the end it is up to you to propagate important information to the right people.
9. Make sure everybody understands the big picture: their work has implications
This will help you greatly because will allow team members to design and implement in a way that you don’t have to fight. It is also hard work from your part.
10. Fight for architecture and design consistency
Doing the right thing from the design and architecture point of view is not more costly. It is actually cheaper in every project longer than a couple of months. Every early investment in architecture pays for itself later during integration and maintenance. Even if you have to admit an occasional hack or prototype in the code base you should contain it in very specific modules.
11. Know the status of everybody’s work and detect slippage
This allows for corrective actions and for early communication with the management. You don’t want to be caught by surprise. Remember that during 90% of the allocated time for a task the code is 90% complete.
12. Record technical debt if you need shortcuts but try to maintain architectural integrity; report the debt
This one is very important for products that will have multiple releases. Technical debt should be analyzed at the beginning of each iteration.
13. Use the process that makes sense in your particular case
Tough one. Sometimes (most of the times?) the process is not up to you. In the enterprise usually the process is pre-decided. But always keep in mind that the process in itself means nothing. It is the people who give meaning to the process. Good people can make the worst process work while the wrong team cannot make any process work. Waterfall can be implemented in a very agile way and the agile methodologies can be applied with “rigor mortis” agility (see The Agile 800 Pounds Gorilla).
14. Avoid dogmas - question why everything is done the way is done; make sure everybody else knows the reasons
Sometimes I hear from programmers: we are agile and combine XP and Scrum and we also do TDD (Test Driven Development - I still hope for a TDD that means Thought Driven Development). The questions that pop up in my mind are: Do you need all those? Do you “really” do them by the book?
Anyway the point here is don’t do anything just because it is the way it has always been done. Understand why. Then explain the reasons to all team members. Rinse and repeat.
15. Avoid design by committee; listen to everybody but make your own decisions
No good design is born from referendum. There are lots of people making wild exotic suggestions when their a$$ is not on the line. There are also excessively prudent ideas born from fear. Even with good ideas you have to filter them and make them yours before you can include them in the design. A good architecture and a good design is usually born in one mind, an open mind that looks around. The obvious example is Linux.
Build your relationship with the team 16. Gain the team’s respect with the quality of your work and by doing what you are preaching17. Be fair
18. Admit your mistakes
19. Publicly recognize both team’s and individual members’ merits
20. Don’t blame anybody publicly for anything
21. Build morale and confidence by offering early victories to the team and to its individual members
22. Match people and tasks based on skills and their personal preference if possible; explain your decisions
23. Work the estimates with the team don’t come up with them
24. Mentor people
25. Listen to and learn from people
26. Explain your technical decisions
Build your relationship with the management and business people
27. Be sure you have authority along with responsibility
28. Be sure you get requirements and not architecture/design masked as requirements
29. Explain technical decisions in business terms
30. Try to be accurate in your estimates; avoid being too optimistic and don’t push it with hidden padding; explain the need for padding
31. Set reasonable expectations
32. Understand the relationships and dependencies with other teams or projects
33. Accurately report the status with alarms, explanations and solutions; report any technical debt
34. Resist pressure for change in requirements, and more important for shortcuts…
35. Be aware of politics
36. React to surprises with calm and with documented answers
zz http://www.whenpenguinsattack.com/2006/07/19/php-template-engine-roundup/
該文總結(jié)了 php 的一些模板. 我使用過的有smarty, template lib, 還有后來用的 Savant. 感覺smarty 太復(fù)雜了, template lib 需要學(xué)習(xí)一些標(biāo)簽, 并且不是很強大, 綜合考慮還是Savant 最好, 既可以使用模板機制, 另外頁面模板直接使用php 函數(shù)來輸出. 功能也還可以.
Smarty
Smarty is a template engine that compiles the templates into PHP scripts, then executes those scripts. Very fast, very flexible.
Savant
A powerful but lightweight PEAR-compliant template system. It is non-compiling, and uses PHP itself as its template language.
Heyes Template Class
A very easy to use, yet powerful and quick template engine that enables you to separate your page layout and design from your code.
FastTemplate
A simple variable interpolation template class that parses your templates for variables and spits out HTML with their values
ShellPage
A simple and easy to use class that lets you make whole websites based on template files for layouts. Change the template and your whole site changes.
STP Simple Template Parser
A simple, light weight and easy to use template parser class. It can assemble a page from several templates, output result pages to the browser or write them to the filesystem.
OO Template Class
An object oriented template class you can use in your own programs.
SimpleTemplate
A template engine to create and structure websites and applications. It can translate and compile the templates.
bTemplate
A small and fast template class that allows you to separate your PHP logic from your HTML presentation code.
ETS - easy template system
A template system that allows you to reshuffle templates with exactly the same data.
EasyTemplatePHP
A simple, yet powerful templating system for your site.
vlibTemplate
A fast, full featured template system that includes a caching and debugging class.
AvanTemplate
A template engine that is multi-byte safe and consumes little computing resource. It supports variable replacement and content blocks that can be set to hidden or shown.
Grafx Software’s Fast Template
A modification of the popular Fast Template system, this includes a cache function, debug console, and silent removal of unassigned dynamic blocks.
TemplatePower
A fast, simple and powerful template class. Features nested dynamic block support, block/file include support and show/hide unassigned variables.
TagTemplate
This library function was designed for use with template files and allows you to retrieve info from HTML files.
htmltmpl: templating engine
A templating engine for Python and PHP. Targeted to web application developers, who want to separate program code and design of their projects.
PHP Class for Parsing Dreamweaver templates
A simple class to parse a Dreamweaver template for use in custom mods for a Gallery 2 and a WordPress blog.
MiniTemplator (Template Engine)
A compact template engine for HTML files. It features a simple syntax for template variables and blocks. Blocks can be nested.
Layout Solution
Simplifies website development and maintenance. It holds commonly used variables and page elements so you don’t need to duplicate common layouts over and over.
Cached Fast Template
This inclusion into FastTemplate allows for caching of the template files, and can even cache with different specifications on separate blocks of content.
TinyButStrong
A template engine that supports MySQL, Odbc, Sql-Server and ADODB. It includes seven methods and two properties.
Brian Lozier’s php based template engine
Only 2k in size, very fast and object-orientated.
WACT
a template engine that separates code from design.
PHPTAL
a XML/XHTML template library for PHP.
ref:
http://www.sitepoint.com/forums/showthread.php?t=123769 對其他的php 模板進(jìn)行了討論
2008年10月6日
看條款38 的時候不是很理解, 于是寫了個測試代碼
#include<iostream>
using namespace std;
class A{
public:
virtual void show(int a=145)
{
cout<<"A: a="<<a<<endl;
}
};
class B: public A
{
public:
void show(int b)
{
cout<<"B: b="<<b<<endl;
}
};
class C: public B
{
public:
void show(int c=999)
{
cout<<"C: c="<<c<<endl;
}
};
class D: public C
{
public:
void show()
{
cout<<"D:\n";
}
};
void main()
{
A *pp;
A a;
B b;
C c;
D d;
a.show();
pp = &a; pp->show();
// b.show(); // error C2660: 'B::show' : function does not take 0 arguments
pp = &b; pp->show();
c.show();
pp = &c; pp->show();
d.show();
pp = &d; pp->show();
C *pc= &d;
pc->show();
system("pause");
}
輸出結(jié)果是
A: a=145
A: a=145
B: b=145
C: c=999
C: c=145
D:
C: c=145
C: c=999
回顧條款
虛函數(shù)是動態(tài)綁定而缺省參數(shù)值是靜態(tài)綁定的. 為什么C++堅持這種有違常規(guī)的做法呢?答案和運行效率有關(guān)。如果缺省參數(shù)值被動態(tài)綁定,編譯器就必須想辦法為虛函數(shù)在運行時確定合適的缺省值,這將比現(xiàn)在采用的在編譯階段確定缺省值的機制更慢更復(fù)雜。做出這種選擇是想求得速度上的提高和實現(xiàn)上的簡便,所以大家現(xiàn)在才能感受得到程序運行的高效;
所以
a. 靜態(tài)綁定 .vs. 動態(tài)綁定
A *pp
= new B;
這里 pp 靜態(tài)綁定是 A* , 而動態(tài)綁定卻是 B*
B *pb = new B;
這里 pb 靜態(tài)綁定和動態(tài)綁定是一樣的都是 B*
b. 缺省值是靜態(tài)綁定的, 而非動態(tài)綁定
所以
d.show() 輸出 D: 因為show 被 D override
pp
= &d; pp->show();
pp 被動態(tài)綁定到D *, 但是show 的缺省值卻是A* 的 145, 所以輸出的是 C: c=145, 而不是999 ( 函數(shù) show 被C 給override 了)
而 C *pc = &d; pc->show() , pc 靜態(tài)綁定為C*, 而動態(tài)綁定為 D* , 所以輸出的是 C: c=999 , 999 是 C* 靜態(tài)綁定的缺省值
c. 所以調(diào)用b.show 的時候出現(xiàn)了如下的錯誤
// b.show(); // error C2660: 'B::show' : function does not take 0 arguments
因為 B* 沒有靜態(tài)綁定的函數(shù)
結(jié)論就是
決不要重新定義繼承而來的缺省參數(shù)值
ref:
從這里學(xué)了不少:)
http://bbs.chinaunix.net/viewthread.php?tid=439188
2008年10月3日
為了給黑莓導(dǎo)入iPhone 的通信錄(contacts) , 只能利用黑莓的桌面管理器, 通過ipd 來維護(hù).
但是發(fā)現(xiàn) ABC Amber BlackBerry Converter 只能轉(zhuǎn)換而無法修改, IPDManager 只能維護(hù)鈴聲和音樂啥的:( 只能自己寫了個小程序
ipd 的格式可以在 http://na.blackberry.com/eng/developers/resources/journals/jan_2006/ipd_file_format.jsp 這里找到, 后面是代碼, 只是生成datablock 列表, 還需要額外拷貝. 操作時最好只同步通信錄.
下面是代碼
#!/usr/local/bin/python2.5
#-*- coding: gbk -*-
from struct import *
class BBFile:
def __init__(self):
pass
def _contactblock(self, name, phone, uid):
s = ''
# name
name = name.encode("utf-16be")
s += pack('<HB', len(name)+1, 0xa0)
s += pack('<B', 0x01) + name
# ff * 8
s += pack('<HB', 8, 0x54)
s += '\xff'*8
# uid
s += pack('<HBI', 4, 0x55, uid)
# phone
phone = phone.encode("gbk")
s += pack('<HB', len(phone)+1, 0x08)
s += phone + '\x00'
return s
def save(self, filename, us, dbID=0, dbVer=0):
hf = open(filename, "w+b")
rs, uid = 1, 363797835 # 初始值
for u in us:
s = self._contactblock(u[0], u[1], uid)
h = pack('<HIBHI', dbID, len(s)+7, dbVer, rs, uid)
hf.write(h + s)
uid += 8 #
rs += 1 #
hf.close()
if __name__=='__main__':
bb = BBFile()
us = [ (u'寶寶1', u'13888888888'),(u'寶寶2', u'13888888888'),(u'寶寶3', u'13888888888'), ]
bb.save("bb.ipd", us, 0, 0)
1. 保存成文件就可以直接運行了:)
2. 如果要真的生成可以導(dǎo)入bb 的文件的話, 要使用高級-> 只同步通訊錄, 然后將這個文件生成的內(nèi)容放在導(dǎo)出文件的頭的后面, 還是有點麻煩.... 有空做個全自動的 呵呵
因為只是測試, 所以很多硬編碼了:)
2008年9月25日
= HTTP 基礎(chǔ)
一個完整的 HTTP 請求可以分成4步:
1. 創(chuàng)建TCP socket, 連接到Web 服務(wù)器
2. 發(fā)送Http 請求頭
3. 接受Web 響應(yīng)數(shù)據(jù)
4. 關(guān)閉socket 連接
整個流程可以通過telnet hostname 80 來模擬
一個完整的請求例子如下
* About to connect() to www.baidu.com port 80 (#0)
* Trying 202.108.22.5... connected
* Connected to www.baidu.com (202.108.22.5) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.16.4 (i586-pc-mingw32msvc) libcurl/7.16.4 OpenSSL/0.9.7e zlib/1.2.2
> Host: www.baidu.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 25 Sep 2008 05:14:30 GMT
< Server: BWS/1.0
< Content-Length: 3342
< Content-Type: text/html
< Cache-Control: private
< Expires: Thu, 25 Sep 2008 05:14:30 GMT
< Set-Cookie: BAIDUID=3A8165EF68FFEE5F605D33ADEF300BA1:FG=1; expires=Thu, 25-Sep-38 05:14:30 GMT; path=/; domain=.baidu.com
< P3P: CP=" OTI DSP COR IVA OUR IND COM "
<
<html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><title>......
另外值得說明的是, HTTP 請求是無狀態(tài)的,表明在處理一個請求時,Web服務(wù)器并不記住來自同一客戶端的請求。
= Http 請求頭
包含4個部分: 請求行、請求頭、空行和請求數(shù)據(jù)
1. 請求行
由三個標(biāo)記組成:請求方法、請求URI和HTTP版本,它們用空格分隔, 如:GET /index.html HTTP/1.1
HTTP 規(guī)范定義了8種請求方法:
GET 檢索URI中標(biāo)識資源的一個簡單請求
HEAD 與GET方法相同,服務(wù)器只返回狀態(tài)行和頭標(biāo),并不返回請求文檔
POST 服務(wù)器接受被寫入客戶端輸出流中的數(shù)據(jù)的請求
PUT 服務(wù)器保存請求數(shù)據(jù)作為指定URI新內(nèi)容的請求
DELETE 服務(wù)器刪除URI中命名的資源的請求
OPTIONS 關(guān)于服務(wù)器支持的請求方法信息的請求
TRACE Web服務(wù)器反饋Http請求和其頭標(biāo)的請求
CONNECT 已文檔化但當(dāng)前未實現(xiàn)的一個方法,預(yù)留做隧道處理
2. 請求頭 [ 可無 ]
由關(guān)鍵字及值對組成,每行一對,關(guān)鍵字和值用冒號(:)分隔。如
> User-Agent: curl/7.16.4 (i586-pc-mingw32msvc) libcurl/7.16.4 OpenSSL/0.9.7e zlib/1.2.2
> Host: www.baidu.com
> Accept: */*
具體請求頭如后所列
3. 空行
最后一個請求頭之后是一個空行,發(fā)送回車符和退行,通知服務(wù)器以下不再有頭標(biāo)。
4. 請求數(shù)據(jù) [ 可無 ]
使用POST傳送數(shù)據(jù),最常使用的是Content-Type和Content-Length頭標(biāo)
= Web 響應(yīng)
由四個部分組成: 狀態(tài)行、響應(yīng)頭、空行、響應(yīng)數(shù)據(jù), 如:
< HTTP/1.1 200 OK
< Date: Thu, 25 Sep 2008 05:14:30 GMT
< Server: BWS/1.0
< Content-Length: 3342
< Content-Type: text/html
< Cache-Control: private
< Expires: Thu, 25 Sep 2008 05:14:30 GMT
< Set-Cookie: BAIDUID=3A8165EF68FFEE5F605D33ADEF300BA1:FG=1; expires=Thu, 25-Sep-38 05:14:30 GMT; path=/; domain=.baidu.com
< P3P: CP=" OTI DSP COR IVA OUR IND COM "
<
<html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><title>......
1.狀態(tài)行
由三個標(biāo)記組成:HTTP版本、響應(yīng)代碼和響應(yīng)描述
HTTP版本:: 向客戶端指明其可理解的最高版本。
響應(yīng)代碼:: 3位的數(shù)字代碼,指出請求的成功或失敗,如果失敗則指出原因。
響應(yīng)描述:: 為響應(yīng)代碼的可讀性解釋。
如
< HTTP/1.1 200 OK
HTTP響應(yīng)碼劃分如下(祥見后):
1xx:信息,請求收到,繼續(xù)處理
2xx:成功,行為被成功地接受、理解和采納
3xx:重定向,為了完成請求,必須進(jìn)一步執(zhí)行的動作
4xx:客戶端錯誤
2.響應(yīng)頭
跟請求頭一樣,它們指出服務(wù)器的功能,標(biāo)識出響應(yīng)數(shù)據(jù)的細(xì)節(jié)。
3.空行
最后一個響應(yīng)頭標(biāo)之后是一個空行,發(fā)送回車符和退行,表明服務(wù)器以下不再有頭標(biāo)。
4.響應(yīng)數(shù)據(jù)
HTML文檔和圖像等,就是HTML本身。
= HTTP頭
用以描述客戶端或者服務(wù)器的屬性、被傳輸?shù)馁Y源等, 分為
1.通用頭標(biāo):即可用于請求,也可用于響應(yīng),是作為一個整體而不是特定資源與事務(wù)相關(guān)聯(lián)。
2.請求頭標(biāo):允許客戶端傳遞關(guān)于自身的信息和希望的響應(yīng)形式。
3.響應(yīng)頭標(biāo):服務(wù)器和于傳遞自身信息的響應(yīng)。
4.實體頭標(biāo):定義被傳送資源的信息。即可用于請求,也可用于響應(yīng)。
下表描述在HTTP/1.1中用到的頭標(biāo)
Accept 定義客戶端可以處理的媒體類型,按優(yōu)先級排序;
在一個以逗號為分隔的列表中,可以定義多種類型和使用通配符。例如:Accept: image/jpeg,image/png,*/*
Accept-Charset 定義客戶端可以處理的字符集,按優(yōu)先級排序;
在一個以逗號為分隔的列表中,可以定義多種類型和使用通配符。例如:Accept-Charset: iso-8859-1,*,utf-8
Accept-Encoding 定義客戶端可以理解的編碼機制。例如:Accept-Encoding:gzip,compress
Accept-Language 定義客戶端樂于接受的自然語言列表。例如:Accept-Language: en,de
Accept-Ranges 一個響應(yīng)頭標(biāo),它允許服務(wù)器指明:將在給定的偏移和長度處,為資源組成部分的接受請求。
該頭標(biāo)的值被理解為請求范圍的度量單位。例如Accept-Ranges: bytes或Accept-Ranges: none
Age 允許服務(wù)器規(guī)定自服務(wù)器生成該響應(yīng)以來所經(jīng)過的時間長度,以秒為單位。
該頭標(biāo)主要用于緩存響應(yīng)。例如:Age: 30
Allow 一個響應(yīng)頭標(biāo),它定義一個由位于請求URI中的次源所支持的HTTP方法列表。例如:Allow: GET,PUT
AUTHORIZATION 一個響應(yīng)頭標(biāo),用于定義訪問一種資源所必需的授權(quán)(域和被編碼的用戶ID與口令)。
例如:Authorization: Basic YXV0aG9yOnBoaWw=
Cache-Control 一個用于定義緩存指令的通用頭標(biāo)。例如:Cache-Control: max-age=30
Connection 一個用于表明是否保存socket連接為開放的通用頭標(biāo)。例如:Connection: close或Connection: keep-alive
Content-Base 一種定義基本URI的實體頭標(biāo),為了在實體范圍內(nèi)解析相對URLs。
如果沒有定義Content-Base頭標(biāo)解析相對URLs,使用Content-Location URI(存在且絕對)或使用URI請求。
例如:Content-Base: Http://www.myweb.com
Content-Encoding 一種介質(zhì)類型修飾符,標(biāo)明一個實體是如何編碼的。例如:Content-Encoding: zip
Content-Language 用于指定在輸入流中數(shù)據(jù)的自然語言類型。例如:Content-Language: en
Content-Length 指定包含于請求或響應(yīng)中數(shù)據(jù)的字節(jié)長度。例如:Content-Length:382
Content-Location 指定包含于請求或響應(yīng)中的資源定位(URI)。
如果是一絕。對URL它也作為被解析實體的相對URL的出發(fā)點。
例如:Content-Location: http://www.myweb.com/news
Content-MD5 實體的一種MD5摘要,用作校驗和。
發(fā)送方和接受方都計算MD5摘要,接受方將其計算的值與此頭標(biāo)中傳遞的值進(jìn)行比較。
例如:Content-MD5: <base64 of 128 MD5 digest>
Content-Range 隨部分實體一同發(fā)送;標(biāo)明被插入字節(jié)的低位與高位字節(jié)偏移,也標(biāo)明此實體的總長度。
例如:Content-Range: 1001-2000/5000
Contern-Type 標(biāo)明發(fā)送或者接收的實體的MIME類型。例如:Content-Type: text/html
Date 發(fā)送HTTP消息的日期。例如:Date: Mon,10PR 18:42:51 GMT
ETag 一種實體頭標(biāo),它向被發(fā)送的資源分派一個唯一的標(biāo)識符。
對于可以使用多種URL請求的資源,ETag可以用于確定實際被發(fā)送的資源是否為同一資源。
例如:ETag: "208f-419e-30f8dc99"
Expires 指定實體的有效期。例如:Expires: Mon,05 Dec 2008 12:00:00 GMT
Form 一種請求頭標(biāo),給定控制用戶代理的人工用戶的電子郵件地址。例如:From: webmaster@myweb.com
Host 被請求資源的主機名。對于使用HTTP/1.1的請求而言,此域是強制性的。例如:Host: www.myweb.com
If-Modified-Since 如果包含了GET請求,導(dǎo)致該請求條件性地依賴于資源上次修改日期。
如果出現(xiàn)了此頭標(biāo),并且自指定日期以來,此資源已被修改,應(yīng)該反回一個304響應(yīng)代碼。
例如:If-Modified-Since: Mon,10PR 18:42:51 GMT
If-Match 如果包含于一個請求,指定一個或者多個實體標(biāo)記。只發(fā)送其ETag與列表中標(biāo)記區(qū)配的資源。
例如:If-Match: "208f-419e-308dc99"
If-None-Match 如果包含一個請求,指定一個或者多個實體標(biāo)記。資源的ETag不與列表中的任何一個條件匹配,操作才執(zhí)行。
例如:If-None-Match: "208f-419e-308dc99"
If-Range 指定資源的一個實體標(biāo)記,客戶端已經(jīng)擁有此資源的一個拷貝。必須與Range頭標(biāo)一同使用。
如果此實體自上次被客戶端檢索以來,還不曾修改過,那么服務(wù)器只發(fā)送指定的范圍,否則它將發(fā)送整個資源。
例如:Range: byte=0-499<CRLF>If-Range:"208f-419e-30f8dc99"
If-Unmodified-Since 只有自指定的日期以來,被請求的實體還不曾被修改過,才會返回此實體。
例如:If-Unmodified-Since:Mon,10PR 18:42:51 GMT
Last-Modified 指定被請求資源上次被修改的日期和時間。例如:Last-Modified: Mon,10PR 18:42:51 GMT
Location 對于一個已經(jīng)移動的資源,用于重定向請求者至另一個位置。
與狀態(tài)編碼302(暫時移動)或者301(永久性移動)配合使用。
例如:Location: http://www2.myweb.com/index.jsp
Max-Forwards 一個用于TRACE方法的請求頭標(biāo),以指定代理或網(wǎng)關(guān)的最大數(shù)目,該請求通過網(wǎng)關(guān)才得以路由。
在通過請求傳遞之前,代理或網(wǎng)關(guān)應(yīng)該減少此數(shù)目。例如:Max-Forwards: 3
Pragma 一個通用頭標(biāo),它發(fā)送實現(xiàn)相關(guān)的信息。例如:Pragma: no-cache
Proxy-Authenticate 類似于WWW-Authenticate,便是有意請求只來自請求鏈(代理)的下一個服務(wù)器的認(rèn)證。
例如:Proxy-Authenticate: Basic realm-admin
Proxy-Proxy-Authorization 類似于授權(quán),但并非有意傳遞任何比在即時服務(wù)器鏈中更進(jìn)一步的內(nèi)容。
例如:Proxy-Proxy-Authorization: Basic YXV0aG9yOnBoaWw=
Public 列表顯示服務(wù)器所支持的方法集。例如:Public: OPTIONS,MGET,MHEAD,GET,HEAD
Range 指定一種度量單位和一個部分被請求資源的偏移范圍。例如:Range: bytes=206-5513
Refener 一種請求頭標(biāo)域,標(biāo)明產(chǎn)生請求的初始資源。對于HTML表單,它包含此表單的Web頁面的地址。
例如:Refener: http://www.myweb.com/news/search.html
Retry-After 一種響應(yīng)頭標(biāo)域,由服務(wù)器與狀態(tài)編碼503(無法提供服務(wù))配合發(fā)送,以標(biāo)明再次請求之前應(yīng)該等待多長時間。
此時間即可以是一種日期,也可以是一種秒單位。例如:Retry-After: 18
Server 一種標(biāo)明Web服務(wù)器軟件及其版本號的頭標(biāo)。例如:Server: Apache/2.0.46(Win32)
Transfer-Encoding 一種通用頭標(biāo),標(biāo)明對應(yīng)被接受方反向的消息體實施變換的類型。例如:Transfer-Encoding: chunked
Upgrade 允許服務(wù)器指定一種新的協(xié)議或者新的協(xié)議版本,與響應(yīng)編碼101(切換協(xié)議)配合使用。
例如:Upgrade: HTTP/2.0
User-Agent 定義用于產(chǎn)生請求的軟件類型(典型的如Web瀏覽器)。
例如:User-Agent: Mozilla/4.0(compatible; MSIE 5.5; Windows NT; DigExt)
Vary 一個響應(yīng)頭標(biāo),用于表示使用服務(wù)器驅(qū)動的協(xié)商從可用的響應(yīng)表示中選擇響應(yīng)實體。例如:Vary: *
Via 一個包含所有中間主機和協(xié)議的通用頭標(biāo),用于滿足請求。例如:Via: 1.0 fred.com, 1.1 wilma.com
Warning 用于提供關(guān)于響應(yīng)狀態(tài)補充信息的響應(yīng)頭標(biāo)。例如:Warning: 99 www.myweb.com Piano needs tuning
www-Authenticate 一個提示用戶代理提供用戶名和口令的響應(yīng)頭標(biāo),與狀態(tài)編碼401(未授權(quán))配合使用。響應(yīng)一個授權(quán)頭標(biāo)。
例如:www-Authenticate: Basic realm=zxm.mgmt
= HTTP碼應(yīng)碼
響應(yīng)碼由三位十進(jìn)制數(shù)字組成,它們出現(xiàn)在由HTTP服務(wù)器發(fā)送的響應(yīng)的第一行, 分五種類型,由它們的第一位數(shù)字表示:
- 1xx:信息,請求收到,繼續(xù)處理
- 2xx:成功,行為被成功地接受、理解和采納
- 3xx:重定向,為了完成請求,必須進(jìn)一步執(zhí)行的動作
- 4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實現(xiàn)
- 5xx:服務(wù)器錯誤,服務(wù)器不能實現(xiàn)一種明顯無效的請求
下表顯示每個響應(yīng)碼及其含義:
100 繼續(xù)
101 分組交換協(xié)
200 OK
201 被創(chuàng)建
202 被采納
203 非授權(quán)信息
204 無內(nèi)容
205 重置內(nèi)容
206 部分內(nèi)容
300 多選項
301 永久地傳送
302 找到
303 參見其他
304 未改動
305 使用代理
307 暫時重定向
400 錯誤請求
401 未授權(quán)
402 要求付費
403 禁止
404 未找到
405 不允許的方法
406 不被采納
407 要求代理授權(quán)
408 請求超時
409 沖突
410 過期的
411 要求的長度
412 前提不成立
413 請求實例太大
414 請求URI太大
415 不支持的媒體類型
416 無法滿足的請求范圍
417 失敗的預(yù)期
500 內(nèi)部服務(wù)器錯誤
501 未被使用
502 網(wǎng)關(guān)錯誤
503 不可用的服務(wù)
504 網(wǎng)關(guān)超時
505 HTTP版本未被支持
= 實例
== POST 數(shù)據(jù)
== 上傳一個文件
假設(shè)接受文件的網(wǎng)頁程序位于 a
bb
ccc
客戶端鏈接 192.168.29.65 后, 應(yīng)該發(fā)送如下http 請求:
POST /upload_file/UploadFile HTTP/1.1
Accept: text/plain, */*
Accept-Language: zh-cn
Host: 192.168.29.65
Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)
Content-Length: 333
Connection: Keep-Alive
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="userfile1"; filename="E:s"
Content-Type: application/octet-stream
a
bb
ccc
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="text1"
foo
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="password1"
bar
-----------------------------7d33a816d302b6--
(上面有一個回車)
此內(nèi)容必須一字不差,包括最后的回車。
注意:Content-Length: 333 這里的333是紅色內(nèi)容的總長度(包括最后的回車)
注意這一行:
Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
根據(jù) rfc1867, multipart/form-data是必須的.
---------------------------7d33a816d302b6 是分隔符,分隔多個文件、表單項。其中33a816d302b6 是即時生成的一個數(shù)字,用以確保整個分隔符不會在文件或表單項的內(nèi)容中出現(xiàn)。Form每個部分用分隔符分割,分隔符之前必須加上"--"著兩個字符(即--{boundary})才能被http協(xié)議認(rèn)為是Form的分隔符,表示結(jié)束的話用在正確的分隔符后面添加"--"表示結(jié)束。
前面的 ---------------------------7d 是 IE 特有的標(biāo)志,Mozila 為---------------------------71.
每個分隔的數(shù)據(jù)的都可以用Content-Type來表示下面數(shù)據(jù)的類型,可以參考rfc1341 (http://www.ietf.org/rfc/rfc1341.txt) 例如:
Contect-Type:application/octet-stream 表示下面的數(shù)據(jù)是二進(jìn)制數(shù)據(jù)
Contect-Type:text/plain 表示下面的數(shù)據(jù)是ASSCII碼數(shù)據(jù)
Contect-Type:text/richtext 表示下面的數(shù)據(jù)是RTF格式
2008年8月14日
想要在c++ 中嵌入script 代碼, 除了自己寫腳本引擎外, lua, python 都可以在c++ 中使用, 另外 MonoBind, AngelScript library 都是一些c++ script library, 可以嵌入到c++ 中使用 .
今天在c++ 中試著嵌入 python 代碼 (示例代碼在 Python-2.5.2\Demo\embed\ 下)
#include <Python.h>
int main(int argc, char *argv[])
{
// Py_NoSiteFlag = 1;
// Py_SetPythonHome("D:\\usr\\Python"); // PYTHONHOME
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}
在運行時可能會產(chǎn)生類似 'import site' failed; use -v for traceback 的錯誤, 原因是python 在import module 的時候的路徑問題. 有3種方法可以解決(以前通過設(shè)置環(huán)境變量 PYTHONPATH 好像在2.5 已經(jīng)無效了).
0. 取消注釋 Py_NoSiteFlag = 1;
這個只是取消import site , 當(dāng)然如果在代碼中要import 啥的話, 還是會出現(xiàn)錯誤的.
a. 設(shè)置環(huán)境變量 PYTHONHOME = D:\usr\Python
b. 在調(diào)用 Py_Initialize 之前調(diào)用函數(shù)
Py_SetPythonHome("D:\\usr\\Python"); // 參數(shù)是python 的安裝目錄
2. 其他一些有用的資源
Python/C API Reference Manual (API 參考) , Extending and Embedding the Python Interpreter (擴展及嵌入Python解釋器, 主要說明了如何擴展Python, 給Python 寫擴展, 其中 5. Embedding Python in Another Application 一章講述了在C++中嵌入/調(diào)用Python 代碼 )
使用C/C++擴展Python 對文 Extending and Embedding the Python Interpreter 作了精簡, 很不錯的一篇文章, 但是跳過了一些基礎(chǔ) .
Building Hybrid Systems with Boost.Python 介紹了使用boost.python 方便python 插件開發(fā), python綁定c++程序 是其中文版本.
Embedding Python in Multi-Threaded C/C++ Applications 講了c++在多線程環(huán)境如何使用Python , 文 C++多線程中調(diào)用python api函數(shù) 提供了一個多線程的封裝.
SCXX - A Simple Python/C++ API
http://davidf.sjsoft.com/mirrors/mcmillan-inc/scxx.html
C++擴展和嵌入Python應(yīng)用 (介紹了一些Python/C API 函數(shù), 以及ext 例子, 一般般)
http://hi.baidu.com/yunsweet/blog/item/20b08aeebaa2b1282cf534c7.html
3. Python 多線程的使用
zz http://blog.csdn.net/liguangyi/archive/2007/06/20/1659697.aspx
今天看了近一天關(guān)于多線程的應(yīng)用中,如何安全調(diào)用python方面的資料,開始的時候看的簡直頭大如斗,被python語言的全局鎖(Global Interpreter Lock)、線程狀態(tài)(Thread State )等都有點繞暈了,后來經(jīng)過各方面文章和幫助文檔的相互參考,發(fā)現(xiàn)對于2.4/2.5版本,提供了PyGILState_Ensure, PyGILState_Release,哎,這下可方便大發(fā)了。
一、首先定義一個封裝類,主要是保證PyGILState_Ensure, PyGILState_Release配對使用,而且這個類是可以嵌套使用的。
#include <python.h>
class PyThreadStateLock
{
public:
PyThreadStateLock(void)
{
state = PyGILState_Ensure( );
}
~PyThreadStateLock(void)
{
PyGILState_Release( state );
}
private:
PyGILState_STATE state;
};
二、在主線程中,這樣處理
// 初始化
Py_Initialize();
// 初始化線程支持
PyEval_InitThreads();
// 啟動子線程前執(zhí)行,為了釋放PyEval_InitThreads獲得的全局鎖,否則子線程可能無法獲取到全局鎖。
PyEval_ReleaseThread(PyThreadState_Get());
// 其他的處理,如啟動子線程等
......
// 保證子線程調(diào)用都結(jié)束后
PyGILState_Ensure();
Py_Finalize();
// 之后不能再調(diào)用任何python的API
三、在主線程,或者子線程中,調(diào)用python本身函數(shù)的都采用如下處理
{
class PyThreadStateLock PyThreadLock;
// 調(diào)用python的API函數(shù)處理
......
}
呵呵,看這樣是否非常簡單了。
另外還有兩個和全局鎖有關(guān)的宏,Py_BEGIN_ALLOW_THREADS 和 Py_END_ALLOW_THREADS。這兩個宏是為了在較長時間的C函數(shù)調(diào)用前,臨時釋放全局鎖,完成后重新獲取全局鎖,以避免阻塞其他python的線程繼續(xù)運行。這兩個宏可以這樣調(diào)用
{
class PyThreadStateLock PyThreadLock;
// 調(diào)用python的API函數(shù)處理
......
Py_BEGIN_ALLOW_THREADS
// 調(diào)用需要長時間的C函數(shù)
......
Py_END_ALLOW_THREADS
// 調(diào)用python的API函數(shù)處理
......
}
4. 可能的錯誤及解決
a. 在vs 200x 下 debug 模式出現(xiàn)鏈接問題
extmodule.obj : error LNK2019: unresolved external symbol __imp___Py_Dealloc referenced in function _PySwigObject_format
extmodule.obj : error LNK2019: unresolved external symbol __imp___Py_NegativeRefcount referenced in function _PySwigObject_format
extmodule.obj : error LNK2001: unresolved external symbol __imp___Py_RefTotal
extmodule.obj : error LNK2019: unresolved external symbol __imp___PyObject_DebugFree referenced in function _PySwigObject_dealloc
extmodule.obj : error LNK2019: unresolved external symbol __imp___PyObject_DebugMalloc referenced in function _PySwigObject_New
extmodule.obj : error LNK2019: unresolved external symbol __imp__Py_InitModule4TraceRefs referenced in function _init_extmodule
主要是因為 Py_DEBUG/Py_TRACE_REFS 引起, 修改 Python\include 下的 pyconfig.h, object.h 兩個文件就行了 ... 詳見 http://www.nabble.com/link-error-in-debug-mode-td3126668.html
Python 支持Com調(diào)用(client com) 以及撰寫COM 組件(server com).
1. com 調(diào)用示例(使用Windows Media Player 播放音樂)
from win32com.client import Dispatch
mp = Dispatch("WMPlayer.OCX")
tune = mp.newMedia("C:/WINDOWS/system32/oobe/images/title.wma")
mp.currentPlaylist.appendItem(tune)
mp.controls.play()
2. com server 的編寫
主要可以參考 <<
Python Programming on Win32 之 Chapter 12 Advanced Python and COM http://oreilly.com/catalog/pythonwin32/chapter/ch12.html >>
示例(分割字符串)
- 代碼
class PythonUtilities:
_public_methods_ = [ 'SplitString' ]
_reg_progid_ = "PythonDemos.Utilities"
# NEVER copy the following ID
# Use "print pythoncom.CreateGuid()" to make a new one.
_reg_clsid_ = "{41E24E95-D45A-11D2-852C-204C4F4F5020}"
def SplitString(self, val, item=None):
import string
if item != None: item = str(item)
return string.split(str(val), item)
# Add code so that when this script is run by
# Python.exe, it self-registers.
if __name__=='__main__':
print "Registering COM server
"
import win32com.server.register
win32com.server.register.UseCommandLine(PythonUtilities)
- 注冊/注銷Com
Command-Line Option
|
Description
|
|
The default is to register the COM objects.
|
--unregister
|
Unregisters the objects. This removes all references to the objects from the Windows registry.
|
--debug
|
Registers the COM servers in debug mode. We discuss debugging COM servers later in this chapter.
|
--quiet
|
Register (or unregister) the object quietly (i.e., don't report success).
|
- 使用COM 可以在python 命令行下運行
>>> import win32com.client
>>> s = win32com.client.Dispatch("PythonDemos.Utilities")
>>> s.SplitString("a,b,c", ",")
((u'a', u'a,b,c'),)
>>>
3. python server com 原理
其實在注冊表中查找到python com 的實現(xiàn)內(nèi)幕
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}]
@="PythonDemos.Utilities"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Debugging]
@="0"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories]

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories\{B3EF80D0-68E2-11D0-A689-00C04FD658FF}]

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\InprocServer32]
@="pythoncom25.dll"
"ThreadingModel"="both"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\LocalServer32]
@="D:\\usr\\Python\\pythonw.exe \"D:\\usr\\Python\\lib\\site-packages\\win32com\\server\\localserver.py\" {41E24E95-D45A-11D2-852C-204C4F4F5020}"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\ProgID]
@="PythonDemos.Utilities"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOM]
@="PythonDemos.PythonUtilities"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOMPath]
@="D:\\"


inproc server 是通過pythoncom25.dll 實現(xiàn)
local server 通過localserver.py 實現(xiàn)
com 對應(yīng)的python 源文件信息在 PythonCOMPath & PythonCOM
4. 使用問題
用PHP 或者 c 調(diào)用com 的時候
<?php
$com = new COM("PythonDemos.Utilities");
$rs = $com->SplitString("a b c");
foreach($rs as $r)
echo $r."\n";
?>
會碰到下面的一些錯誤.
pythoncom error: PythonCOM Server - The 'win32com.server.policy' module could not be loaded.
<type 'exceptions.ImportError'>: No module named server.policy pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)
可以通過2種方式解決:
a. 設(shè)置環(huán)境 PYTHONHOME = D:\usr\Python
另外在c ++ 使用python 的時候, 如果import module 出現(xiàn)錯誤
'import site' failed; use -v for traceback 的話, 也可以通過設(shè)置這個變量解決.
b. 為com 生產(chǎn)exe, dll 可執(zhí)行文件, setup.py 代碼如下 :
from distutils.core import setup
import py2exe

import sys
import shutil

# Remove the build tree
ALWAYS do that!
shutil.rmtree("build", ignore_errors=True)

# List of modules to exclude from the executable
excludes = ["pywin", "pywin.debugger", "pywin.debugger.dbgcon", "pywin.dialogs", "pywin.dialogs.list"]

# List of modules to include in the executable
includes = ["win32com.server"]

# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
try:
# if this doesn't work, try import modulefinder
import py2exe.mf as modulefinder
import win32com
for p in win32com.__path__[1:]:
modulefinder.AddPackagePath("win32com", p)
for extra in ["win32com.shell", "win32com.server"]: #,"win32com.mapi"
__import__(extra)
m = sys.modules[extra]
for p in m.__path__[1:]:
modulefinder.AddPackagePath(extra, p)

except ImportError:
# no build path setup, no worries.
pass

# Set up py2exe with all the options
setup(
options = {"py2exe": {"compressed": 2,
"optimize": 2,
#"bundle_files": 1,
"dist_dir": "COMDist",
"excludes": excludes,
"includes": includes}},
# The lib directory contains everything except the executables and the python dll.
# Can include a subdirectory name.
zipfile = None,
com_server = ['PythonDemos'], # 文件名!!
)

ref:
http://oreilly.com/catalog/pythonwin32/chapter/ch12.html http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx