<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>漂泊如风</title>
	<atom:link href="http://www.linux-field.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.linux-field.com</link>
	<description>关于Linux,Python,Php的那些事</description>
	<lastBuildDate>Mon, 13 Feb 2012 05:03:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Windows 7 硬盘安装Fedora 16[zt]</title>
		<link>http://www.linux-field.com/archives/804</link>
		<comments>http://www.linux-field.com/archives/804#comments</comments>
		<pubDate>Mon, 13 Feb 2012 05:03:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[系统管理]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=804</guid>
		<description><![CDATA[http://www.linuxidc.com/Linux/2011-12/48724.htm &#160; 从Fedora15开始，安装镜像ISO文件中不再有install.img文件了，因此在使用非光盘安装时，会出现要求网络配置的问题，所以不能再像Fedora14那样安装以后的版本了。 1、从Fedora官网下载Fedora16的DVD ISO：Fedora-16-i386-DVD.iso，放到Fat32格式的分区里，我这里是C盘，即把ISO放到C盘下（不能是NTFS格式的，否则不能安装） &#160; 2、解压ISO里的isolinux文件夹里的vmlinuz和initrd.img文件，放到C盘（即和ISO同一个盘） &#160; 3、解压ISO里的images文件夹，放到C盘（即和ISO同一个盘） &#160; 4、下载EasyBCD并安装：http://www.linuxidc.com/Linux/2007-12/10060.htm &#160; &#160; &#160;安装完成后打开EasyBCD，选择&#160;Add New Entry &#8212; NeoGrub &#8212; Install&#160;&#8212; Configure &#160; &#160; &#160;如下图 &#160; &#160; 5、将如下内容添加到弹出的menu记事本中： title Install Fedora 16 kernel (hd0,0)/vmlinuz&#160;linux askmethod initrd (hd0,0)/initrd.img &#160; 注1：必须要加linux askmethod，否则会启动网络安装， 注2：(hd0,0)是我的C盘（即放ISO文件的那个盘），这个要根据自己放ISO文件的分区进行修改 &#160; 6、重启Win7，选择Install Fedora 16即可安装Fedora16了。 &#160; !&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; 从Fedora15开始，安装镜像ISO文件中不再有install.img文件了，因此在使用非光盘安装时，会出现要求网络配置的问题，所以不能再像Fedora14那样安装以后的版本了。 1、从Fedora官网下载Fedora16的DVD ISO：Fedora-16-i386-DVD.iso，放到Fat32格式的分区里，我这里是C盘，即把ISO放到C盘下（不能是NTFS格式的，否则不能安装） &#160; &#160; 2、解压ISO里的isolinux文件夹里的vmlinuz和initrd.img文件，放到C盘（即和ISO同一个盘） &#160; 3、解压ISO里的images文件夹，放到C盘（即和ISO同一个盘） &#160; [...]]]></description>
			<content:encoded><![CDATA[<p style="border-width: 0px; margin-top: 0px; font-size: 14px; margin-bottom: 0px; padding-bottom: 0px; line-height: 26px; padding-top: 0px; font-family: Arial; text-align: left;">http://www.linuxidc.com/Linux/2011-12/48724.htm</p>
<p style="border-width: 0px; margin-top: 0px; font-size: 14px; margin-bottom: 0px; padding-bottom: 0px; line-height: 26px; padding-top: 0px; font-family: Arial; text-align: left;">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">从<a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a>15开始，安装镜像ISO文件中不再有install.img文件了，因此在使用非光盘安装时，会出现要求网络配置的问题，所以不能再像Fedora14那样安装以后的版本了。</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">1、从<a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a>官网下载Fedora16的DVD ISO：Fedora-16-i386-DVD.iso，放到<span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: rgb(255,0,0); PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">Fat32</span>格式的分区里，我这里是C盘，即把ISO放到C盘下（不能是NTFS格式的，否则不能安装）</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">2、解压ISO里的isolinux文件夹里的<span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: rgb(255,0,0); PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">vmlinuz和initrd.img</span>文件，放到C盘（即和ISO同一个盘）</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">3、解压ISO里的<span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: rgb(255,0,0); PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">images</span>文件夹，放到C盘（即和ISO同一个盘）</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">4、下载EasyBCD并安装：<font color="#ca0000"><a href="http://www.linuxidc.com/Linux/2007-12/10060.htm">http://www.linuxidc.com/Linux/2007-12/10060.htm</a></font></span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px"><span style="FONT-FAMILY: verdana,geneva,lucida,'lucida grande',arial,helvetica,sans-serif,simsun,宋体,bitstream,Nimbus; BACKGROUND-COLOR: rgb(247,251,255)">&nbsp; &nbsp; &nbsp;安装完成后打开EasyBCD，选择&nbsp;</span><span style="FONT-FAMILY: verdana,geneva,lucida,'lucida grande',arial,helvetica,sans-serif,simsun,宋体,bitstream,Nimbus; BACKGROUND-COLOR: rgb(247,251,255); TEXT-ALIGN: left">Add New Entry &mdash; NeoGrub &mdash; Install&nbsp;<strong>&mdash; Configure</strong></span></span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px"><span style="FONT-FAMILY: verdana,geneva,lucida,'lucida grande',arial,helvetica,sans-serif,simsun,宋体,bitstream,Nimbus; BACKGROUND-COLOR: rgb(247,251,255); TEXT-ALIGN: left"><strong>&nbsp; &nbsp; &nbsp;如下图</strong></span></span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px"><span style="FONT-FAMILY: verdana,geneva,lucida,'lucida grande',arial,helvetica,sans-serif,simsun,宋体,bitstream,Nimbus; BACKGROUND-COLOR: rgb(247,251,255); TEXT-ALIGN: left"><strong>&nbsp;<span style="WHITE-SPACE: pre"><img alt="" src="http://www.linuxidc.com/upload/2011_12/111205133058281.gif" /></span></strong></span></span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">5、将如下内容添加到弹出的menu记事本中：</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">title Install <a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a> 16</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">kernel (hd0,0)/vmlinuz&nbsp;<span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: rgb(255,0,0); PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">linux askmethod</span></span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">initrd (hd0,0)/initrd.img</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: rgb(255,0,0); PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">注1：必须要加linux askmethod，否则会启动网络安装，</span></span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: rgb(255,0,0); PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; WHITE-SPACE: pre; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">注2：</span></span>(hd0,0)是我的C盘（即放ISO文件的那个盘），这个要根据自己放ISO文件的分区进行修改</span></p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px">&nbsp;</p>
<p style="BORDER-TOP-WIDTH: 0px; MARGIN-TOP: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 14px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; LINE-HEIGHT: 26px; PADDING-TOP: 0px; FONT-FAMILY: Arial; TEXT-ALIGN: left; BORDER-RIGHT-WIDTH: 0px"><span style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 18px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-RIGHT-WIDTH: 0px">6、重启Win7，选择Install <a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a> 16即可安装Fedora16了。</span></p>
<p style="border-width: 0px; margin-top: 0px; font-size: 14px; margin-bottom: 0px; padding-bottom: 0px; line-height: 26px; padding-top: 0px; font-family: Arial; text-align: left;">&nbsp;</p>
<p style="border-width: 0px; margin-top: 0px; font-size: 14px; margin-bottom: 0px; padding-bottom: 0px; line-height: 26px; padding-top: 0px; font-family: Arial; text-align: left;">!&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<div id="content">
<p><span style="FONT-SIZE: 18px">从<a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a>15开始，安装镜像ISO文件中不再有install.img文件了，因此在使用非光盘安装时，会出现要求网络配置的问题，所以不能再像Fedora14那样安装以后的版本了。</span></p>
<p><span style="FONT-SIZE: 18px">1、从<a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a>官网下载Fedora16的DVD ISO：Fedora-16-i386-DVD.iso，放到<span style="COLOR: #ff0000">Fat32</span>格式的分区里，我这里是C盘，即把ISO放到C盘下（不能是NTFS格式的，否则不能安装）</span></p>
<table align="center" border="0" width="97%">
<tbody>
<tr>
<td colspan="3">&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">2、解压ISO里的isolinux文件夹里的<span style="COLOR: #ff0000">vmlinuz和initrd.img</span>文件，放到C盘（即和ISO同一个盘）</span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">3、解压ISO里的<span style="COLOR: #ff0000">images</span>文件夹，放到C盘（即和ISO同一个盘）</span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">4、下载grub4dos：<a href="http://www.linuxidc.com/Linux/2009-01/18027.htm">http://www.linuxidc.com/Linux/2009-01/18027.htm</a></span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">5、将grub4dos下的menu.lst和grldr复制到XP的系统盘，我这是C盘</span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">6、修该menu.lst文件，在文件最后加上如下三行内容：</span></p>
<p><span style="FONT-SIZE: 18px">install <a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a> 16</span></p>
<p><span style="FONT-SIZE: 18px">kernel (hd0,0)/vmlinuz <span style="COLOR: #ff0000">linux askmethod</span></span></p>
<p><span style="FONT-SIZE: 18px">initrd (hd0,0)/initrd.img</span></p>
<p>&nbsp;</p>
<p><span style="COLOR: #ff0000"><span style="FONT-SIZE: 18px">&nbsp;&nbsp;注1：必须要加linux askmethod，否则会启动网络安装，</span></span></p>
<p><span style="FONT-SIZE: 18px; COLOR: #ff0000"><span style="WHITE-SPACE: pre"><span style="FONT-SIZE: 18px">注2：</span></span>(hd0,0)是我的C盘（即放ISO文件的那个盘），这个要根据自己放ISO文件的分区进行修改</span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">7、修改XP系统盘（即C盘）下的boot.ini文件，这个文件是隐藏文件，在文件末尾加上：C:\grldr=&quot;Grub4Dos&quot;</span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">8、重启XP，选择Grub4Dos，进入Grub引导，然后选择install <a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a> 16即可安装Fedora16了。</span></p>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18px">9、<a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a>16安装好后，可能无法引导XP，这时就要修改引导菜单，使其能够引导XP，在终端输入如下命令：</span></p>
<p><span style="FONT-SIZE: 18px">su root</span></p>
<p><span style="FONT-SIZE: 18px">gedit /boot/grub2/grub.cfg</span></p>
<p><span style="FONT-SIZE: 18px">在grub.cfg文件适当的位置（你懂的）加入如下内容：</span></p>
<p><span style="FONT-SIZE: 18px">&nbsp; &nbsp; &nbsp; &nbsp; menuentry &quot;Windows XP&quot; {</span></p>
<p><span style="FONT-SIZE: 18px">&nbsp; &nbsp; &nbsp; &nbsp; chainloader (hd0,0)+1</span></p>
<p><span style="FONT-SIZE: 18px">}</span></p>
<p><span style="FONT-SIZE: 18px">保存文件，重启系统在引导菜单选择Windows XP即可成功进入XP了。</span></p>
<p><span style="COLOR: #ff0000"><span style="WHITE-SPACE: pre"><span style="FONT-SIZE: 18px">（注：</span></span><span style="FONT-SIZE: 18px"><a href="http://www.linuxidc.com/topicnews.aspx?tid=5" title="Fedora">Fedora</a>16是由grub2来引导的，不再是以前的grub了，所以需修改grub2的引导菜单）</span></span></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/804/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FreeSWITCH 初步 【zt】</title>
		<link>http://www.linux-field.com/archives/802</link>
		<comments>http://www.linux-field.com/archives/802#comments</comments>
		<pubDate>Wed, 08 Feb 2012 10:14:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[voip]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=802</guid>
		<description><![CDATA[http://www.dujinfang.com/past/2010/4/14/freeswitch-chu-bu/ 我准备写一本关于FreeSWITCH的书，由于最近很忙，只写了个第二章，初学FreeSWITCH的朋友可以做个参考，也顺便提提意见。 第二章 FreeSWITCH 初步 什么是 FreeSWITCH ？ FreeSWITCH 是一个开源的电话交换平台，它具有很强的可伸缩性&#8211;从一个简单的软电话客户端到运营商级的软交换设备几乎无所不能。能原生地运行于Windows、 Max OS X、Linux、BSD 及 solaris 等诸多32/64位平台。可以用作一个简单的交换引擎、一个PBX，一个媒体网关或媒体支持IVR的服务器等。 它支持SIP、H323、Skype、Google Talk等协议，并能很容易地与各种开源的PBX系统如sipXecs、Call Weaver、Bayonne、YATE及Asterisk等通信。 FreeSWITCH 遵循RFC并支持很多高级的SIP特性，如 presence、BLF、SLA以及TCP、TLS和sRTP等。它也可以用作一个SBC进行透明的SIP代理（proxy）以支持其它媒体如T.38 等。FreeSWITCH 支持宽带及窄带语音编码，电话会议桥可同时支持8、12、16、24、32及48kHZ的语音. 而在传统的电话网络中，要做到三方通话或多方通话需要通过专门的芯片来处理，其它像预付费，彩铃等业务在PSTN网络中都需要依靠智能网(IN)才能实 现，而且配置起来相当不灵活。 快速体验 FreeSWITCH 的功能确实非常丰富和强大，在进一步学习之前我们先来做一个完整的体验。FreeSWITCH 默认的配置是一个SOHO PBX(家用电话小交换机)，那么我们本章的目标就是从0安装，实现分机互拨电话，测试各种功能，并通过添加一个SIP-PSTN网关拨打PSTN电话。 这样，即使你没有任何使用经验，你也应该能顺利走完本章，从而建立一个直接的认识。在体验过程中，你会遇到一点稍微复杂的配置，如果不能完全理解，也不用 担心，我们在后面会详细的介绍。当然，如果你是一个很有经验的 FreeSWITCH 用户，那么大可跳过本章。 安装FreeSWITCH基本系统 在本文写作时，最新的版本1.0.5pre10，但说不定当你读到时1.0.5正式版已经发布了。FreeSWITCH支持32位及64位的 Linux、 MacOSX、BSD、Solaris、Windows等众多平台。某些平台上有编译好的安装包，但本人强烈建议从源代码进行安装，因为 FreeSWITCH 更新非常快，而已编译好的版本通常都比较旧。你可以下载源码包，也可以直接从SVN仓库中取得最新的代码。与其它项目不同的是，其SVN主干 (trunk)代码通常比稳定的发布版更稳定。而且，当你需要技术支持时，开发人员也通常建议你先升级到SVN中最新的代码，再看是不是仍有问题。 Windows用户可以直接下载安装文件 http://files.freeswitch.org/windows/installer/x86/freeswitch.msi （再提醒一下，版本比较旧代，如果从源代码安装的话，需要Visual Studio 2008。另外，64位用户下载：http://files.freeswitch.org/windows/installer/x64/freeswitch.msi）。安装完成执行 c:\freeswitch\freeswitch.exe (或c:\&#34;programe files&#34;\freeswitch\freeswitch.exe)便可启动，其配置文件都在c:\freeswitch\conf\。 以下假定你使用 Linux 平台，并假定你有 Linux 的基本知识。如何从头安装 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.dujinfang.com/past/2010/4/14/freeswitch-chu-bu/">http://www.dujinfang.com/past/2010/4/14/freeswitch-chu-bu/</a></p>
<p>我准备写一本关于FreeSWITCH的书，由于最近很忙，只写了个第二章，初学FreeSWITCH的朋友可以做个参考，也顺便提提意见。</p>
<p><span id="more-802"></span></p>
<h1>第二章 FreeSWITCH 初步</h1>
<h2>什么是 FreeSWITCH ？</h2>
<p>FreeSWITCH 是一个开源的电话交换平台，它具有很强的可伸缩性&#8211;从一个简单的软电话客户端到运营商级的软交换设备几乎无所不能。能原生地运行于Windows、 Max OS X、Linux、BSD 及 solaris 等诸多32/64位平台。可以用作一个简单的交换引擎、一个PBX，一个媒体网关或媒体支持IVR的服务器等。 它支持SIP、H323、Skype、Google Talk等协议，并能很容易地与各种开源的PBX系统如sipXecs、Call Weaver、Bayonne、YATE及Asterisk等通信。 FreeSWITCH 遵循RFC并支持很多高级的SIP特性，如 presence、BLF、SLA以及TCP、TLS和sRTP等。它也可以用作一个SBC进行透明的SIP代理（proxy）以支持其它媒体如T.38 等。FreeSWITCH 支持宽带及窄带语音编码，电话会议桥可同时支持8、12、16、24、32及48kHZ的语音. 而在传统的电话网络中，要做到三方通话或多方通话需要通过专门的芯片来处理，其它像预付费，彩铃等业务在PSTN网络中都需要依靠智能网(IN)才能实 现，而且配置起来相当不灵活。</p>
<h2>快速体验</h2>
<p>FreeSWITCH 的功能确实非常丰富和强大，在进一步学习之前我们先来做一个完整的体验。FreeSWITCH 默认的配置是一个SOHO PBX(家用电话小交换机)，那么我们本章的目标就是从0安装，实现分机互拨电话，测试各种功能，并通过添加一个SIP-PSTN网关拨打PSTN电话。 这样，即使你没有任何使用经验，你也应该能顺利走完本章，从而建立一个直接的认识。在体验过程中，你会遇到一点稍微复杂的配置，如果不能完全理解，也不用 担心，我们在后面会详细的介绍。当然，如果你是一个很有经验的 FreeSWITCH 用户，那么大可跳过本章。</p>
<h2>安装FreeSWITCH基本系统</h2>
<p>在本文写作时，最新的版本1.0.5pre10，但说不定当你读到时1.0.5正式版已经发布了。FreeSWITCH支持32位及64位的 Linux、 MacOSX、BSD、Solaris、Windows等众多平台。某些平台上有编译好的安装包，但本人强烈建议从源代码进行安装，因为 FreeSWITCH 更新非常快，而已编译好的版本通常都比较旧。你可以下载源码包，也可以直接从SVN仓库中取得最新的代码。与其它项目不同的是，其SVN主干 (trunk)代码通常比稳定的发布版更稳定。而且，当你需要技术支持时，开发人员也通常建议你先升级到SVN中最新的代码，再看是不是仍有问题。</p>
<p>Windows用户可以直接下载安装文件 <a href="http://files.freeswitch.org/windows/installer/x86/freeswitch.msi">http://files.freeswitch.org/windows/installer/x86/freeswitch.msi</a> （再提醒一下，版本比较旧代，如果从源代码安装的话，需要Visual Studio 2008。另外，64位用户下载：<a href="http://files.freeswitch.org/windows/installer/x64/freeswitch.msi">http://files.freeswitch.org/windows/installer/x64/freeswitch.msi</a>）。安装完成执行 c:\freeswitch\freeswitch.exe (或c:\&quot;programe files&quot;\freeswitch\freeswitch.exe)便可启动，其配置文件都在c:\freeswitch\conf\。</p>
<p>以下假定你使用 Linux 平台，并假定你有 Linux 的基本知识。如何从头安装 Linux 超出了本书的范围，而且，你也可以很容易的从网上找到这些资料。一般来说，任何发行套件都是可以的，但是，有些发行套件的内核、文件系统、编译环 境，LibC 版本会有一些问题。所以，如果你在遇到问题后想获得社区支持，最好选择一种大家都熟悉的发行套件。FreeSWITCH 开发者使用的平台是 CentOS 5.2/5.3（CentOS 5.4 上会有一些问题，并不总是版本越高越好），社区中也有许多人在使用 Ubuntu 和 Debian，如果你想用于生产环境，建议使用 LTS（Long Term Support） 的版本，即 Ubuntu8.04/10.04 或 Debian Stable。在安装之前，我们需要先准备一些环境(FreeSWITCH 可以以普通用户权限运行，但为了简单起见，以下所有操作均用 root 执行）：</p>
<p>CentOS:</p>
<pre><code>yum install -y subversion autoconf automake libtool gcc-c++ ncurses-devel make
</code></pre>
<p>Ubuntu:</p>
<pre><code>apt-get -y install build-essential subversion automake autoconf wget libtool libncurses5-dev
</code></pre>
<p>以下三种安装方式任选其一，默认安装位置在/usr/local/freeswitch。安装过程中会下载源代码目录，请保留，以便以后升级及安装配置其它组件。</p>
<h3>解压缩源码包安装:</h3>
<pre><code>wget http://latest.freeswitch.org/freeswitch-1.0.5-latest.tar.gz
tar xvzf freeswitch-1.0.5-latest.tar.gz
cd freeswitch-1.0.5
./configure
make install
</code></pre>
<p>这是在在 Linux 上从源代码安装软件的标准过程。首先第 1 行下载最新的源代码，第 2 行解压缩，第 4 行配置编译环境，第 5 行编译安装。</p>
<h3>从 SVN 仓库安装：</h3>
<p>FreeSWITCH 使用 Subversion 管理源代码，从代码库安装能让你永远使用最新的版本。</p>
<pre><code>svn co http://svn.freeswitch.org/svn/freeswitch/trunk freeswitch
cd freeswitch
./bootstrap.sh
./configure
make install
</code></pre>
<p>与上一种方法不同的是，直接从代码库安装需要执行一个 bootstrap.sh 以初始化一些环境。</p>
<h3>最快安装（推荐）</h3>
<pre><code>wget http://www.freeswitch.org/eg/Makefile &amp;&amp; make install
</code></pre>
<p>以上命令会下载一个 Makefile，然后使用 make 执行安装过程。安装过程中它会从 SVN 仓库中获取代码，实际上执行的操作跟上一种安装方式相同。</p>
<h2>安装声音文件</h2>
<p>在以下例子中我们需要一些声音文件，而安装这些声音文件也异常简单。你只需在源代码目录中执行：</p>
<pre><code>make sounds-install
make moh-install
</code></pre>
<p>以下高质量的声音文件可选择安装。FreeSWITCH支持8、16、32及48kHz的语音，很少有其它电话系统支持如此多的抽样频率（普通电话是8K，更高频率意味着更好的通话质量）。</p>
<pre><code>make cd-sounds-install
make cd-moh-install
</code></pre>
<p>安装完成后，会显示一个有用的帮助，</p>
<pre><code>+---------- FreeSWITCH install Complete ----------+
+ FreeSWITCH has been successfully installed.     +
+                                                 +
+       Install sounds:                           +
+       (uhd-sounds includes hd-sounds, sounds)   +
+       (hd-sounds includes sounds)               +
+       ------------------------------------      +
+                make cd-sounds-install           +
+                make cd-moh-install              +
+                                                 +
+                make uhd-sounds-install          +
+                make uhd-moh-install             +
+                                                 +
+                make hd-sounds-install           +
+                make hd-moh-install              +
+                                                 +
+                make sounds-install              +
+                make moh-install                 +
+                                                 +
+       Install non english sounds:               +
+       replace XX with language                  +
+       (ru : Russian)                            +
+       ------------------------------------      +
+                make cd-sounds-XX-install        +
+                make uhd-sounds-XX-install       +
+                make hd-sounds-XX-install        +
+                make sounds-XX-install           +
+                                                 +
+       Upgrade to latest:                        +
+       ----------------------------------        +
+                make current                     +
+                                                 +
+       Rebuild all:                              +
+       ----------------------------------        +
+                make sure                        +
+                                                 +
+       Install/Re-install default config:        +
+       ----------------------------------        +
+                make samples                     +
+                                                 +
+       Additional resources:                     +
+       ----------------------------------        +
+       http://www.freeswitch.org                 +
+       http://wiki.freeswitch.org                +
+       http://jira.freeswitch.org                +
+       http://lists.freeswitch.org               +
+                                                 +
+       irc.freenode.net / #freeswitch            +
+-------------------------------------------------+
</code></pre>
<p>至此，已经安装完了。在Unix类操作系统上，其默认的安装位置是/usr/local/freeswtich，下文所述的路径全部相对于该路径。 两个常用的命令是 bin/freeswitch 和 bin/fs_cli，为了便于使用，建议将这两个命令做符号链接放到你的搜索路径中，如：</p>
<pre><code>ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
</code></pre>
<p>当然，如果 /usr/local/bin 不在你的搜索路径中，可以把上面 /usr/local/bin 换成 /usr/bin/。 另外你也可以修改你的PATH环境变量以包含该路径。</p>
<p>接下来就应该可以启动了，通过在终端中执行freeswitch命令(如果你已做符号链接的话，否则要执行/usr/local /freeswitch/bin/freeswitch)可以将其启动到前台，启动过程中会有许多log输出，第一次启动时会有一些错误和警告，可以不用 理会。启动完成后会进入到系统控制台(以下称称FS-Con)。并显示类似的提示符&ldquo;freeswitch@internal&gt;&rdquo;(以下简作 &ldquo;FS&gt; &rdquo;)。通过在FS-Con中输入shutdown命令可以关闭FreeSWITCH。</p>
<p>如果您想将FreeSWITCH启动到后台(daemon，服务模式)，可以使用freeswitch -nc (No console)。后台模式没有控制台，如果这时想控制FreeSWITCH，可以使用客户端软件fs_cli连接。注意，在fs_cli中需要使用 fsctl shutdown 命令关闭 FreeSWITCH。当然，也可以直接在 Linux 提示符下通过 freeswitch -stop 命令关闭。如果不想退出 FreeSWITCH 服务，只退出fs_cli客户端，则需要输入 /exit，或Ctrl + D，或者，直接关掉终端窗口。</p>
<h3>连接SIP软电话</h3>
<p>FreeSWITCH最典型的应用是作为一个服务器(它实际上是一个背靠背的用户代理，B2BUA)，并用电话客户端软件（一般叫软电话）连接到 它。虽然 FreeSWITCH 支持 IAX、H323、Skype、Gtalk 等众多通信协议，但其最主要的协议还是 SIP。支持SIP的软电话有很多，最常用的是 X-Lite 和 Zoiper。这两款软电话都支持 Linux、MacOSX 和 Windows平台，免费使用但是不开源。在 Linux 上你还可以使用 ekiga 软电话。</p>
<p>强烈建议在同一局域网上的其它机器上安装软电话，并确保麦克风和耳机可以正常工作 。当然，如果你没有多余的机器做这个实验，那么你也可以在同一台机器上安装。只是需要注意，软电话不要占用 UDP 5060 端口，因为 FreeSWITCH 默认要使用该端口，这是新手常会遇到的一个问题。你可以通过先启动 FreeSWITCH 再启动软电话来避免该问题，另外有些软电话允许你修改本地监听端口。</p>
<p>通过输入以下命令可以知道 FreeSWITCH 监听在哪个IP地址上，记住这个 IP 地址(:5060以前的部分)，下面要用到：</p>
<pre><code>netstat -an | grep 5060
</code></pre>
<p>FreeSWITCH 默认配置了 <em>1000 ~ 1019</em> 共 20 个用户，你可以随便选择一个用户进行配置：</p>
<p>在 X-Lite 上点右键，选 Sip Account Settings&#8230;，点Add添加一个账号，填入以下参数(Zoiper 可参照配置)：</p>
<pre><code>Display Name: 1000
User name: 1000
Password: 1234
Authorization user name: 1000
Domain: 你的IP地址，就是刚才你记住的那个
</code></pre>
<p>其它都使用默认设置，点 OK 就可以了。然后点 Close 关闭 Sip Account 设置窗口。这时 X-Lite 将自动向 FreeSWITCH 注册。注册成功后会显示&quot;Ready. Your username is 1000&quot;，另外，左侧的&ldquo;拨打电话&rdquo;（Dial）按钮会变成绿色的。如下图。</p>
<p><img src="http://commondatastorage.googleapis.com/freeswitch.org.cn/images/2-1.png" /></p>
<p>激动人心的时刻就要来了。输入&ldquo;9664&rdquo;按回车（或按绿色拨打电话按钮），就应该能听到保持音乐(MOH, Music on Hold)。如果听不到也不要气馁，看一下 FS-Con 中有没有提示什么错误。如果有&ldquo;File Not Found&rdquo;之类的提示，多半是声音文件没有安装，重新查看 make moh-install 是否有错误。接下来，可以依次试试拨打以下号码：</p>
<pre><code>------------------
号码        |   说明
----------------------
9664      |   保持音乐
9196      |   echo，回音测试
9195      |   echo，回音测试，延迟5秒
9197      |   milliwatte extension，铃音生成
9198      |   TGML 铃音生成示例
5000      |   示例IVR
4000      |   听取语音信箱
33xx      |   电话会议，48K(其中xx可为00-99，下同)
32xx      |   电话会议，32K
31xx      |   电话会议，16K
30xx      |   电话会议，8K
2000-2002 |   呼叫组
1000-1019 |   默认分机号

表一： 默认号码及说明
</code></pre>
<p>详情见 <a href="http://wiki.freeswitch.org/wiki/Default_Dialplan_QRF">http://wiki.freeswitch.org/wiki/Default_Dialplan_QRF</a>。</p>
<p>另外，也许你想尝试注册另外一个SIP用户并在两者间通话。最好是在同一个局域网中的另外一台机器上启动另一个 X-Lite ，并使用 1001 注册，注册完毕后就可以在 1000 上呼叫 1001，或在 1001 上呼叫 1000 。当然，你仍然可以在同一台机器上做这件事（比方说用Zoiper注册为1001），需要注意的是，由于你机器上只有一个声卡，两者可能会争用声音设备。 特别是在Linux上，有些软件会独占声音设备。如果同时也有一个USB接口的耳机，那就可以设置不同的软件使用不同的声音设备。</p>
<h2>配置简介</h2>
<p>FreeSWITCH配置文件默认放在 conf/， 它由一系列XML配置文件组成。最顶层的文件是freeswitch.xml，系统启动时它依次装入其它一些XML文件并最终组成一个大的XML文件。</p>
<pre><code>文件                                |    说明
---------------------------------------------------
vars.xml                          | 一些常用变量
dialplan/default.xml              | 缺省的拨号计划
directory/default/*.xml           | SIP用户，每用户一个文件
sip_profiles/internal.xml         | 一个SIP profile，或称作一个SIP-UA，监听在本地IP及端口5060，一般供内网用户使用
sip_profiles/externa.xml          | 另一个SIP-UA，用作外部连接，端口5080
autoload_configs/modules.conf.xml | 配置当FreeSWITCH启动时自动装载哪些模块
</code></pre>
<h2>添加一个新的SIP用户</h2>
<p>FreeSWITCH默认设置了20个用户(1000-1019)，如果你需要更多的用户，或者想通过添加一个用户来学习FreeSWITCH配置，只需要简单执行以下三步：</p>
<ul>
<li>在 conf/directory/default/ 增加一个用户配置文件</li>
<li>修改拨号计划(Dialplan)使其它用户可以呼叫到它</li>
<li>重新加载配置使其生效</li>
</ul>
<p>如果想添加用户Jack，分机号是1234。只需要到 conf/directory/default 目录下，将 1000.xml 拷贝到 1234.xml。打开1234.xml，将所有1000都改为1234。并把 effective_caller_id_name 的值改为 Jack，然后存盘退出。如：</p>
<pre><code>&lt;variable name=&quot;effective_caller_id_name&quot; value=&quot;Jack&quot;/&gt;
</code></pre>
<p>接下来，打开 conf/dialplan/default.xml，找到 &lt;condition field=&quot;destionation_number&quot;<br />
	expression=&quot;^(10[01][0-9])$&quot;&gt; 一行，改为 &lt;condition field=&quot;destionation_number&quot; expression=&quot;^(10[01][0-9]|1234)$&quot;&gt;。熟悉正则表达式的人应该知道，&ldquo;^(10[01][0-9])$&rdquo;匹配被 叫号码1000-1019。因此我们修改之后的表达式就多匹配了一个1234。FreeSWITCH使用Perl兼容的正则表达式(PCRE)。</p>
<p>现在，回到FS-Con，或启动fs_cli，执行 reloadxml 命令或按快捷键F6，使新的配置生效。</p>
<p>找到刚才注册为1001的那个软电话(或启动一个新的，如果你有足够的机器的话)，把1001都改为1234然后重新注册，则可以与1000相互进 行拨打测试了。如果没有多台机器，在同一台机器上运行多个软电话可能有冲突，这时，也可以直接进在FreeSWITCH控制台上使用命令进行测试：</p>
<pre><code>FS&gt; sofia status profile internal  (显示多少用户已注册）
FS&gt; originate sofia/profile/internal/1000 &amp;echo  (拨打1000并执行echo程序）
FS&gt; originate user/1000 &amp;echo  (同上）
FS&gt; originate sofia/profile/internal/1000 9999    (相当于在软电话1000上拨打9999)
FS&gt; originate sofia/profile/internal/1000 9999 XML default   (同上)
</code></pre>
<p>其中，echo() 程序一个很简单的程序，它只是将你说话的内容原样再放给你听，在测试时很有用，在本书中，我们会经常用它来测试。</p>
<h2>FreeSWITCH用作软电话</h2>
<p>FreeSWITCH也可以简单的用作一个软电话，如X-Lite. 虽然相比而言比配置X-Lite略微麻烦一些，但你会从中得到更多好处：FreeSWITCH是开源的，更强大、灵活。关键是它是目前我所知道的唯一支持CELT高清通话的软电话。</p>
<p>FreeSWITCH使用mod_portaudio支持你本地的声音设备。该模块默认是不编译的。到你的源代码树下，执行：</p>
<pre><code>make mod_portaudio
make mod_portaudio-install
</code></pre>
<p>其它的模块也可以依照上面的方式进行重新编译和安装。然后到FS-Con中，执行:</p>
<pre><code>FS&gt; load mod_portaudio
</code></pre>
<p>如果得到&ldquo;Cannot find an input device&rdquo;之类的错误可能是你的声卡驱动有问题。如果是提示&ldquo;+OK&rdquo;就是成功了，接着执行：</p>
<pre><code>FS&gt; pa devlist

API CALL [pa(devlist)] output:
0;Built-in Microphone;2;0;
1;Built-in Speaker;0;2;r
2;Built-in Headphone;0;2;
3;Logitech USB Headset;0;2;o
4;Logitech USB Headset;1;0;i
</code></pre>
<p>以上是在我笔记本上的输出，它列出了所有的声音设备。其中，3和4最后的&ldquo;o&rdquo;和&ldquo;i&rdquo;分别代表声音输出(out)和输入(in)设备。在你的电脑上可能不一样，如果你想选择其它设备，可以使用命令：</p>
<pre><code>FS&gt; pa indev #0
FS&gt; pa outdev #2
</code></pre>
<p>以上命令会选择我电脑上内置的麦克风和耳机。</p>
<p>接下来你就可以有一个可以用命令行控制的软电话了，酷吧？</p>
<pre><code>FS&gt; pa looptest    (回路测试，echo)
FS&gt; pa call 9999
FS&gt; pa call 1000
FS&gt; pa hangup
</code></pre>
<p>如上所示，你可以呼叫刚才试过的所有号码。现在假设想从SIP分机1000呼叫到你，那需要修改拨号计划(Dialplan)。用你喜欢的编辑器编辑以下文件放到conf/dialplan/default/portaudio.xml</p>
<pre><code>&lt;include&gt;
  &lt;extension name=&quot;call me&quot;&gt;
    &lt;condition field=&quot;destination_number&quot; expression=&quot;^(me|12345678)$&quot;&gt;
      &lt;action application=&quot;bridge&quot; data=&quot;portaudio&quot;/&gt;
    &lt;/condition&gt;
  &lt;/extension&gt;
&lt;/include&gt;
</code></pre>
<p>然后，在FS-Con中按&ldquo;F6&rdquo;或输入以下命令使之生效：</p>
<pre><code>FS&gt; reloadxml
</code></pre>
<p>在分机1000上呼叫&ldquo;me&rdquo;或&ldquo;12345678&rdquo;(你肯定想为自己选择一个更酷的号码)，然后在FS-Con上应该能看到类似&ldquo;[DEBUG] mod_portaudio.c:268 BRRRRING! BRRRRING! call 1&rdquo;的输出（如果看不到的话按&ldquo;F8&rdquo;能得到详细的Log），这说明你的软电话在振铃。多打几个回车，然后输入&ldquo;pa answer&rdquo;就可以接听电话了。&ldquo;pa hangup&rdquo;可以挂断电话。</p>
<p>当然，你肯定希望在振铃时能听到真正的振铃音而不是看什么BRRRRRING。好办，选择一个好听一声音文件(.wav格式)，编辑conf/autoload_configs/portaudio.conf.xml，修改下面一行：</p>
<pre><code>&lt;param name=&quot;ring-file&quot; value=&quot;/home/your_name/your_ring_file.wav&quot;/&gt;
</code></pre>
<p>然后重新加载模块：</p>
<pre><code>FS&gt; reloadxml
FS&gt; reload mod_portaudio
</code></pre>
<p>再打打试试，看是否能听到振铃音了？</p>
<p>如果你用不惯字符界面，可以看一下FreeSWITCH-Air(http://www.freeswitch.org.cn /download)，它为 FreeSWITCH 提供一个简洁的软电话的图形界面。另外，如果你需要高清通话，除需要设置相关的语音编解码器(codec)外，你还需要有一幅好的耳机才能达到最好的效 果。本人使用的是一款USB耳机。</p>
<h2>配置SIP网关拨打外部电话</h2>
<p>如果你在某个运营商拥有SIP账号，你就可以配置上拨打外部电话了。该SIP账号（或提供该账号的设备）在 FreeSWITCH 中称为SIP网关（Gateway）。添加一个网关只需要在 conf/sip_profiles/external/ 创建一个XML文件，名字可以随便起，如gw1.xml。</p>
<pre><code>&lt;gateway name=&quot;gw1&quot;&gt;
    &lt;param name=&quot;realm&quot; value=&quot;SIP服务器地址，可以是IP或IP:端口号&quot;/&gt;
    &lt;param name=&quot;username&quot; value=&quot;SIP用户名&quot;/&gt;
    &lt;param name=&quot;password&quot; value=&quot;密码&quot;/&gt;
    &lt;param name=&quot;register&quot; value=&quot;true&quot; /&gt;
&lt;/gateway&gt;
</code></pre>
<p>如果你的SIP网关还需要其它参数，可以参阅同目录下的 example.xml，但一般来说上述参数就够了。你可以重启 FreeSWITCH，或者执行以下命令使用之生效。</p>
<pre><code>FS&gt; sofia profile external rescan reloadxml
</code></pre>
<p>然后显示一下状态：</p>
<pre><code>FS&gt; sofia status
</code></pre>
<p>如果显示 gateway gw1 的状态是 REGED ，则表明正确的注册到了网关上。你可以先用命令试一下网关是否工作正常：</p>
<pre><code>FS&gt; originate sofia/gateway/gw1/xxxxxx &amp;echo()
</code></pre>
<p>以上命令会通过网关 gw1 呼叫号码 xxxxxx（可能是你的手机号），被叫号码接听电话后，FreeSWITCH 会执行 echo() 程序，你应该能听到自己的回音。</p>
<h3>从某一分机上呼出</h3>
<p>如果网关测试正常，你就可以配置从你的SIP软电话或portaudio呼出了。由于我们是把 FreeSWITCH 当作 PBX 用，我们需要选一个出局字冠。常见的 PBX 一般是内部拨小号，打外部电话就需要加拨 0 或先拨 9 。当然，这是你自己的交换机，你可以用任何你喜欢的数字（甚至是字母）。 继续修改拨号计划，创建新XML文件： conf/dialplan/default/call_out.xml :</p>
<pre><code>&lt;include&gt;
  &lt;extension name=&quot;call out&quot;&gt;
    &lt;condition field=&quot;destination_number&quot; expression=&quot;^0(\d+)$&quot;&gt;
      &lt;action application=&quot;bridge&quot; data=&quot;sofia/gateway/gw1/$1&quot;/&gt;
    &lt;/condition&gt;
  &lt;/extension&gt;
&lt;/include&gt;
</code></pre>
<p>其中，(\d+)为正则表达式，匹配 0 后面的所有数字并存到变量 $1 中。然后通过 bridge 程序通过网关 gw1 打出该号码。当然，建立该XML后需要在Fs-Con中执行 reloadxml 使用之生效。</p>
<h3>呼入电话处理。</h3>
<p>如果你的 SIP 网关支持呼入，那么你需要知道呼入的 DID 。 DID的全称是 Direct Inbound Dial，即直接呼入。一般来说，呼入的 DID 就是你的 SIP 号码，如果你不知道，也没关系，后面你会学会如何得到。 编辑以下XML文件放到 conf/dialplan/public/my_did.xml</p>
<pre><code>&lt;include&gt;
  &lt;extension name=&quot;public_did&quot;&gt;
    &lt;condition field=&quot;destination_number&quot; expression=&quot;^(你的DID)$&quot;&gt;
      &lt;action application=&quot;transfer&quot; data=&quot;1000 XML default&quot;/&gt;
    &lt;/condition&gt;
  &lt;/extension&gt;
&lt;/include&gt;
</code></pre>
<p>reloadxml 使之生效。上述配置会将来话直接转接到分机 1000 上。在后面的章节你会学到如何更灵活的处理呼入电话，如转接到语音菜单或语音信箱等。</p>
<h2>小结</h2>
<p>其实本章涵盖了从安装、配置到调试、使用的相当多的内容，如果你能顺利走到这儿，你肯定对 FreeSWITCH 已经受不释手了。如果你卡在了某处，或某些功能未能实现，也不是你的错，主要是因为 FreeSWITCH 博大精深，我不能在短短的一章内把所有的方面解释清楚。在后面的章节中，你会学到更多的基本概念、更加深入地了解 FreeSWITCH 的哲学，学到更多的调试技术和技巧，解决任何问题都会是小菜一碟了。</p>
<p>本文参考自<a href="http://www.freeswitch.org/node/202">http://www.freeswitch.org/node/202</a>，但非翻译作品，且已通知原作者。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/802/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>python multicast [组播编程]</title>
		<link>http://www.linux-field.com/archives/799</link>
		<comments>http://www.linux-field.com/archives/799#comments</comments>
		<pubDate>Thu, 02 Feb 2012 03:19:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=799</guid>
		<description><![CDATA[http://hi.baidu.com/liuhangbin/blog/item/988a4722964cab58ac34de68.html 好 久没用用python了，几乎都快忘光了&#8230;&#8230;最近正在学组播，看了一些资料，发现python写组播的小case很方便啊，开始的时候google查的英 文资料，结果不知道是比较旧还是什么问题，总是实现不了。今天百度了一下国内资料，尝试了一下，居然成功了。不过原来尝试是在RHEL6上，这次是在 fedora14上，不知道有没有这个问题。总之这次代码确实能通过了。 Server : $ cat multiserv.py&#160; #!/usr/bin/env python from socket import * import struct s = socket(AF_INET, SOCK_DGRAM) s.bind((&#39;&#39;, 9998)) mreq = struct.pack(&#34;=4sl&#34;, inet_aton(&#34;224.1.1.1&#34;), INADDR_ANY) s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq) count = 0 while count &#60; 100: &#160;&#160; &#160;f = s.recv(4096) &#160;&#160; &#160;print &#34;recv message :&#34;, f &#160;&#160; &#160;count += 1 s.close() &#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://hi.baidu.com/liuhangbin/blog/item/988a4722964cab58ac34de68.html">http://hi.baidu.com/liuhangbin/blog/item/988a4722964cab58ac34de68.html</a></p>
<p>好 久没用用python了，几乎都快忘光了&hellip;&hellip;最近正在学组播，看了一些资料，发现python写组播的小case很方便啊，开始的时候google查的英 文资料，结果不知道是比较旧还是什么问题，总是实现不了。今天百度了一下国内资料，尝试了一下，居然成功了。不过原来尝试是在RHEL6上，这次是在 fedora14上，不知道有没有这个问题。总之这次代码确实能通过了。</p>
<p><span id="more-799"></span></p>
<p>Server :</p>
<p>$ cat multiserv.py&nbsp;<br />
	#!/usr/bin/env python<br />
	from socket import *<br />
	import struct<br />
	s = socket(AF_INET, SOCK_DGRAM)<br />
	s.bind((&#39;&#39;, 9998))<br />
	mreq = struct.pack(&quot;=4sl&quot;, inet_aton(&quot;224.1.1.1&quot;), INADDR_ANY)<br />
	s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)<br />
	count = 0<br />
	while count &lt; 100:<br />
	&nbsp;&nbsp; &nbsp;f = s.recv(4096)<br />
	&nbsp;&nbsp; &nbsp;print &quot;recv message :&quot;, f<br />
	&nbsp;&nbsp; &nbsp;count += 1<br />
	s.close()</p>
<p>&nbsp;</p>
<p>Client :<br />
	$ cat multicli.py<br />
	#!/usr/bin/env python<br />
	from socket import *<br />
	import struct<br />
	s = socket(AF_INET, SOCK_DGRAM)<br />
	s.sendto(&quot;Hello World!&quot;, (&quot;224.1.1.1&quot;, 9998))</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>For IPv6&nbsp;</p>
<p>&nbsp;</p>
<p>$ cat multiserv.py<br />
	#!/usr/bin/env python<br />
	from socket import *<br />
	import struct<br />
	s = socket(AF_INET6, SOCK_DGRAM)<br />
	s.bind((&#39;&#39;, 9998))<br />
	s.setsockopt(IPPROTO_IPV6, IPV6_JOIN_GROUP,<br />
	&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;inet_pton(AF_INET6,&quot;ff02::1234&quot;)+&#39;\0&#39;*4)<br />
	count = 0<br />
	while count &lt; 100:<br />
	&nbsp;&nbsp; &nbsp;data = s.recv(4096)<br />
	&nbsp;&nbsp; &nbsp;print &quot;recv message : &quot;, data<br />
	&nbsp;&nbsp; &nbsp;count += 1<br />
	s.close()</p>
<p>&nbsp;</p>
<p>$ cat multicli.py<br />
	#!/usr/bin/env python<br />
	from socket import *<br />
	import struct<br />
	s = socket(AF_INET6, SOCK_DGRAM)<br />
	s.sendto(&quot;Hello World!&quot;, (&quot;ff02::1234&quot;, 9998))</p>
<p>参考资料：http://blog.wodeshufang.com/p/python-multicast-receive.html</p>
<p>http://svn.python.org/projects/python/trunk/Demo/sockets/mcast.py</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/799/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>实现将VirtualBox 虚拟机转换为KVM虚拟机的步骤(zt)</title>
		<link>http://www.linux-field.com/archives/795</link>
		<comments>http://www.linux-field.com/archives/795#comments</comments>
		<pubDate>Sat, 21 Jan 2012 05:14:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=795</guid>
		<description><![CDATA[http://blog.csdn.net/starshine/article/details/7032316 &#160;&#160;&#160;&#160;&#160; 原来在桌面上一直使用virtualbox虚拟机管理程序（VMM）构建虚拟机安装不同的操作系统，现在 研究linux下的KVM，能否将已经建立的virtualBox虚拟客户机（guest）转换为KVM虚拟机呢？经过查找 资料，还真可以。下面说明一下步骤： 1、将virtualbox虚拟机的虚拟磁盘文件（VDI）转换成raw格式的文件 &#160;&#160;&#160;&#160; 此步骤使用virtualbox的命令行工具vboxmanage，这个工具对于通过编制脚本生成虚拟机很有帮助， 其提供的功能比virtualbox图形配置提供的功能要强大的多。具体命令如下： &#160;&#160;&#160;&#160; VBoxManage clonehd &#8211;format raw centos.vdi centos.img &#160;&#160;&#160;&#160; 说明：将名为centos.vdi 的虚拟磁盘文件转换为raw格式的虚拟磁盘文件，raw格式的文件可以说是 不同格式虚拟磁盘文件之间转换的桥梁，其他格式的虚拟磁盘文件都可以先转换成此格式，然后在转换为 其他目标格式。转换完成后，生成的raw格式文件大小是在配置虚拟机时指定的大小，实际vdi文件只占用 实际应用的大小，如配置时虽然指定为20G，但安装完操作系统及相关软件后，可能只需要8G，那么实际 的虚拟磁盘文件(vdi格式）只占用8G，但是在用上面的命令转换后，则转换后的文件大小就是在建立虚拟 机时指定磁盘空间的大小，在这里就是20G，因此在转换前需要查看一下磁盘空间是否足够。 &#160;&#160; 命令参数： clonehd&#160;&#160; &#8211;克隆虚拟磁盘 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;format raw&#160;&#160;&#160; &#8211;指定转换格式 &#160;&#160; clone这个此在虚拟化技术中用的很多，诸如备份、迁移等很多都是通过这个技术实现。 2、将转换后的raw格式文件转换为kvm使用的qcow2格式文件 &#160;&#160;&#160;&#160; 此步骤使用qemu-img工具实现，如果机器上没有，可以通过rpm或yum进行安装，包名为qemu-img。 &#160;&#160;&#160;&#160; qemu-img是专门虚拟磁盘映像文件的qemu命令行工具。 &#160;&#160;&#160;&#160; 具体命令如下： &#160;&#160;&#160;&#160; qemu-img convert -f raw centos.img -O qcow2 centos.qcow2 &#160;&#160;&#160;&#160; 参数说明：convert&#160;&#160; 将磁盘文件转换为指定格式的文件 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; -f&#160;&#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.csdn.net/starshine/article/details/7032316">http://blog.csdn.net/starshine/article/details/7032316</a></p>
<div class="article_content" id="article_content">
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:Microsoft YaHei">原来在桌面上一直使用virtualbox虚拟机管理程序（VMM）构建虚拟机安装不同的操作系统，现在</span></p>
<p><span style="font-family:Microsoft YaHei">研究linux下的</span><span style="font-family:Microsoft YaHei">KVM，能否将已经建立的virtualBox虚拟客户机（guest）转换为KVM虚拟机呢？经过查找</span></p>
<p><span style="font-family:Microsoft YaHei">资料，还真可以。下面说明一下步骤：</span></p>
<p><span style="font-family:Microsoft YaHei"><strong>1、将virtualbox虚拟机的虚拟磁盘文件（VDI）转换成raw格式的文件</strong></span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 此步骤使用virtualbox的命令行工具vboxmanage，这个工具对于通过编制脚本生成虚拟机很有帮助，</span></p>
<p><span style="font-family:Microsoft YaHei">其提供的功能比virtualbox图形配置提供的功能要强大的多。具体命令如下：</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#000099">VBoxManage clonehd &#8211;format raw centos.vdi centos.img</span></span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 说明：将名为centos.vdi 的虚拟磁盘文件转换为raw格式的虚拟磁盘文件，raw格式的文件可以说是</span></p>
<p><span style="font-family:Microsoft YaHei">不同格式虚拟磁盘文件之间转换的桥梁，其他格式的虚拟磁盘文件都可以先转换成此格式，然后在转换为</span></p>
<p><span style="font-family:Microsoft YaHei">其他目标格式。转换完成后，生成的raw格式文件大小是在配置虚拟机时指定的大小，</span><span style="font-family:Microsoft YaHei">实际vdi文件只占用</span></p>
<p><span style="font-family:Microsoft YaHei">实际应用的大小，如配置时虽然指定为20G，但安装完操作系统及相关软件后，可能只需要8G，那么实际</span></p>
<p><span style="font-family:Microsoft YaHei">的虚拟磁盘文件(vdi格式）只占用8G，但是在用上面的命令转换后，则转换后的文件大小就是在建立虚拟</span></p>
<p><span style="font-family:Microsoft YaHei">机时指定磁盘空间的大小，在这里就是20G，因此在转换前需要查看一下磁盘空间是否足够。</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp; 命令参数： clonehd&nbsp;&nbsp; &#8211;克隆虚拟磁盘</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8211;format raw&nbsp;&nbsp;&nbsp; &#8211;指定转换格式</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp; <span style="color:#330099">clone这个此在虚拟化技术中用的很多，诸如备份、迁移等很多都是通过这个技术实现。</span></span></p>
<p><span style="font-family:Microsoft YaHei"><strong>2、将转换后的raw格式文件转换为kvm使用的qcow2格式文件</strong></span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 此步骤使用qemu-img工具实现，如果机器上没有，可以通过rpm或yum进行安装，包名为qemu-img。</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; qemu-img是专门虚拟磁盘映像文件的qemu命令行工具。</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 具体命令如下：</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#330099">qemu-img convert -f raw centos.img -O qcow2 centos.qcow2</span></span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 参数说明：convert&nbsp;&nbsp; 将磁盘文件转换为指定格式的文件</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -f&nbsp;&nbsp; 指定需要转换文件的文件格式</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -O&nbsp; 指定要转换的目标格式</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 转换完成后，将新生产一个目标映像文件，原文件仍保存。</span></p>
<p><span style="font-family:Microsoft YaHei"><strong>3、利用qemu-kvm命令基于转换后的虚拟磁盘镜像启动虚拟机</strong></span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在生成kvm支持的文件格式后，即可以使用qemu-kvm基于已转换的磁盘文件启动虚拟机了，语法</span></p>
<p><span style="font-family:Microsoft YaHei">如下：</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#000066">qemu-kvm -m&nbsp;1024 -M pc -smp&nbsp;2 -hda /opt/images/centos.qcow2 -boot c -name centos \</span></span></p>
<p><span style="font-family:Microsoft YaHei"><span style="color:#000066">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-k en-us vnc :0&nbsp;</span></span><span style="font-family:Microsoft YaHei; color:#000066"> -usb -usbdevice tablet</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 启动后，将生产一个单独的qemu-kvm进程，利用vnc工具可以连接到这个虚拟机，在本例中vnc端口为</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 5900，连接后，可以在客户机中进行各种操作。</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数说明： -m 1024&nbsp;&nbsp;&nbsp; 指定内存大小</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -M&nbsp; pc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 真的机器类型，这里为RHEL 5.4.0 PC</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -smp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用2个虚拟cpu仿真对称多处理器系统</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -hda&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定虚拟磁盘文件名称</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -boot&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定引导设备 c 为硬盘，d为光驱</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定虚拟机名字</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -k&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定键盘layout</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vnc ：0&nbsp;&nbsp; 指定vnc连接端口，最终端口为后面的数字+5900</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-usb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使usb设备有效</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -usbdevice tablet&nbsp;&nbsp; 加入把设备，tablet是指使用绝对坐标的指针设备，如鼠标</span></p>
<p><span style="font-family:Microsoft YaHei"><strong>4、其他说明</strong></span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用第三步生成的虚拟机只是临时的，在此进程被关闭后，此虚拟机也不存在。可以手工编制一个</span></p>
<p><span style="font-family:Microsoft YaHei">配置文件，保护虚拟机的各类参数保存在/etc/libvirt/qemu目录下，这样就能够被virsh进行管理，可以</span></p>
<p><span style="font-family:Microsoft YaHei">方便的启动和关闭。配置文件可以使用已有虚拟机的配置文件作为模板。</span></p>
<p><span style="font-family:Microsoft YaHei">&nbsp;&nbsp;&nbsp;&nbsp; 在用virtualbox生成的虚拟机中，如果安装了virtualbox的VBoxGuestAdditions（主要用来控制鼠标</span></p>
<p><span style="font-family:Microsoft YaHei">捕获等功能），则需要先在虚拟机中卸载，因此kvm不支持。</span></p>
</div>
<p><span id="more-795"></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/795/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PIL应用之生成验证码图片[zt]</title>
		<link>http://www.linux-field.com/archives/792</link>
		<comments>http://www.linux-field.com/archives/792#comments</comments>
		<pubDate>Wed, 04 Jan 2012 07:13:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=792</guid>
		<description><![CDATA[http://qinxuye.me/article/create-validate-code-image-with-pil/ 现在的网页中，为了防止机器人提交表单，图片验证码是很常见的应对手段之一。这里就不详细介绍了，相信大家都遇到过。 现在就给出用Python的PIL库实现验证码图片的代码。代码中有详细注释。 #!/usr/bin/env python #coding=utf-8 import random from PIL import Image, ImageDraw, ImageFont, ImageFilter _letter_cases = &#34;abcdefghjkmnpqrstuvwxy&#34; # 小写字母，去除可能干扰的i，l，o，z _upper_cases = _letter_cases.upper() # 大写字母 _numbers = &#39;&#39;.join(map(str, range(3, 10))) # 数字 init_chars = &#39;&#39;.join((_letter_cases, _upper_cases, _numbers)) def create_validate_code(size=(120, 30), chars=init_chars, img_type=&#34;GIF&#34;, mode=&#34;RGB&#34;, bg_color=(255, 255, 255), fg_color=(0, 0, 255), font_size=18, font_type=&#34;ae_AlArabiya.ttf&#34;, length=4, draw_lines=True, n_line=(1, 2), [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://qinxuye.me/article/create-validate-code-image-with-pil/">http://qinxuye.me/article/create-validate-code-image-with-pil/</a></p>
<p>现在的网页中，为了防止机器人提交表单，图片验证码是很常见的应对手段之一。这里就不详细介绍了，相信大家都遇到过。</p>
<p><span id="more-792"></span></p>
<p>现在就给出用Python的PIL库实现验证码图片的代码。代码中有详细注释。</p>
<pre class="brush:python;">#!/usr/bin/env python
#coding=utf-8

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

_letter_cases = &quot;abcdefghjkmnpqrstuvwxy&quot; # 小写字母，去除可能干扰的i，l，o，z
_upper_cases = _letter_cases.upper() # 大写字母
_numbers = &#39;&#39;.join(map(str, range(3, 10))) # 数字
init_chars = &#39;&#39;.join((_letter_cases, _upper_cases, _numbers))

def create_validate_code(size=(120, 30),
                         chars=init_chars,
                         img_type=&quot;GIF&quot;,
                         mode=&quot;RGB&quot;,
                         bg_color=(255, 255, 255),
                         fg_color=(0, 0, 255),
                         font_size=18,
                         font_type=&quot;ae_AlArabiya.ttf&quot;,
                         length=4,
                         draw_lines=True,
                         n_line=(1, 2),
                         draw_points=True,
                         point_chance = 2):
    &#39;&#39;&#39;
    @todo: 生成验证码图片
    @param size: 图片的大小，格式（宽，高），默认为(120, 30)
    @param chars: 允许的字符集合，格式字符串
    @param img_type: 图片保存的格式，默认为GIF，可选的为GIF，JPEG，TIFF，PNG
    @param mode: 图片模式，默认为RGB
    @param bg_color: 背景颜色，默认为白色
    @param fg_color: 前景色，验证码字符颜色，默认为蓝色#0000FF
    @param font_size: 验证码字体大小
    @param font_type: 验证码字体，默认为 ae_AlArabiya.ttf
    @param length: 验证码字符个数
    @param draw_lines: 是否划干扰线
    @param n_lines: 干扰线的条数范围，格式元组，默认为(1, 2)，只有draw_lines为True时有效
    @param draw_points: 是否画干扰点
    @param point_chance: 干扰点出现的概率，大小范围[0, 100]
    @return: [0]: PIL Image实例
    @return: [1]: 验证码图片中的字符串
    &#39;&#39;&#39;

    width, height = size # 宽， 高
    img = Image.new(mode, size, bg_color) # 创建图形
    draw = ImageDraw.Draw(img) # 创建画笔

    def get_chars():
        &#39;&#39;&#39;生成给定长度的字符串，返回列表格式&#39;&#39;&#39;
        return random.sample(chars, length)

    def create_lines():
        &#39;&#39;&#39;绘制干扰线&#39;&#39;&#39;
        line_num = random.randint(*n_line) # 干扰线条数

        for i in range(line_num):
            # 起始点
            begin = (random.randint(0, size[0]), random.randint(0, size[1]))
            #结束点
            end = (random.randint(0, size[0]), random.randint(0, size[1]))
            draw.line([begin, end], fill=(0, 0, 0))

    def create_points():
        &#39;&#39;&#39;绘制干扰点&#39;&#39;&#39;
        chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]

        for w in xrange(width):
            for h in xrange(height):
                tmp = random.randint(0, 100)
                if tmp &gt; 100 - chance:
                    draw.point((w, h), fill=(0, 0, 0))

    def create_strs():
        &#39;&#39;&#39;绘制验证码字符&#39;&#39;&#39;
        c_chars = get_chars()
        strs = &#39; %s &#39; % &#39; &#39;.join(c_chars) # 每个字符前后以空格隔开

        font = ImageFont.truetype(font_type, font_size)
        font_width, font_height = font.getsize(strs)

        draw.text(((width - font_width) / 3, (height - font_height) / 3),
                    strs, font=font, fill=fg_color)

        return &#39;&#39;.join(c_chars)

    if draw_lines:
        create_lines()
    if draw_points:
        create_points()
    strs = create_strs()

    # 图形扭曲参数
    params = [1 - float(random.randint(1, 2)) / 100,
              0,
              0,
              0,
              1 - float(random.randint(1, 10)) / 100,
              float(random.randint(1, 2)) / 500,
              0.001,
              float(random.randint(1, 2)) / 500
              ]
    img = img.transform(size, Image.PERSPECTIVE, params) # 创建扭曲

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜，边界加强（阈值更大）

    return img, strs

if __name__ == &quot;__main__&quot;:
    code_img = create_validate_code()
    code_img.save(&quot;validate.gif&quot;, &quot;GIF&quot;)</pre>
<p>最后结果返回一个元组，第一个返回值是Image类的实例，第二个参数是图片中的字符串（比较是否正确的作用）。</p>
<p>需要提醒的是，如果在生成ImageFont.truetype实例的时候抛出IOError异常，有可能是运行代码的电脑没有包含指定的字体，需要下载安装。</p>
<p>生成的验证码图片效果：</p>
<p><a href="http://qinxuye.me/static/uploads/validate.png" class="highslide-image" onclick="return hs.expand(this);"><img alt="validate" height="34" src="http://qinxuye.me/static/uploads/validate.png" width="136" /></a></p>
<p>这时候，细心的同学可能要问，如果每次生成验证码，都要先保存生成的图片，再显示到页面。这么做让人太不能接受了。这个时候，我们需要使用python内置的<a href="http://docs.python.org/library/stringio.html" target="_blank">StringIO模块</a>，它有着类似file对象的行为，但是它操作的是内存文件。于是，我们可以这么写代码：</p>
<pre class="brush:python;">try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

mstream = StringIO.StringIO()

img = create_validate_code()[0]
img.save(mstream, &quot;GIF&quot;)</pre>
<p>这样，我们需要输出的图片的时候只要使用&ldquo;mstream.getvalue()&rdquo;即可。比如在Django里，我们首先定义这样的url：</p>
<pre class="brush:python;">from django.conf.urls.defaults import *

urlpatterns = patterns(&#39;example.views&#39;,
    url(r&#39;^validate/$&#39;, &#39;validate&#39;, name=&#39;validate&#39;),
)</pre>
<p>在views中，我们把正确的字符串保存在session中，这样当用户提交表单的时候，就可以和session中的正确字符串进行比较。</p>
<pre class="brush:python;">from django.shortcuts import HttpResponse

from validate import create_validate_code

def validate(request):
    mstream = StringIO.StringIO()

    validate_code = create_validate_code()
    img = validate_code[0]
    img.save(mstream, &quot;GIF&quot;)

    request.session[&#39;validate&#39;] = validate_code[1]

    return HttpResponse(mstream.getvalue(), &quot;image/gif&quot;)</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/792/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python模块包中__init__.py文件的作用[zt]</title>
		<link>http://www.linux-field.com/archives/790</link>
		<comments>http://www.linux-field.com/archives/790#comments</comments>
		<pubDate>Tue, 27 Dec 2011 09:56:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[基础知识]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=790</guid>
		<description><![CDATA[http://hi.baidu.com/nkhzj/blog/item/a6f0df00b2c39716728b65f1.html 模块包： 包通常总是一个目录，目录下为首的一个文件便是 __init__.py。然后是一些模块文件和子目录，假如子目录中也有 __init__.py 那么它就是这个包的子包了。差不多就像这样吧： Package1/ __init__.py Module1.py Module2.py Package2/ __init__.py Module1.py Module2.py 我们可以就这样导入一个包： import Package1 或者调入一个子模块和子包： from Package1 import Module1 from Package1 import Package2 import Packag1.Module1 import Packag1.Package2 可以深入好几层包结构： from Package1.Package2 import Module1 import Package1.Package2.Module1 大致就这样吧，我觉得，包的精髓应该是在 __init__.py 这个文件之中的。 &#160; &#160; &#160; __init__.py 文件: __init__.py 控制着包的导入行为。假如 __init__.py 为空，那么仅仅导入包是什么都做不了的。 &#62;&#62;&#62; import Package1 &#62;&#62;&#62; Package1.Module1 Traceback [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://hi.baidu.com/nkhzj/blog/item/a6f0df00b2c39716728b65f1.html">http://hi.baidu.com/nkhzj/blog/item/a6f0df00b2c39716728b65f1.html</a></p>
<p><strong><font color="#000000">模块包：</font></strong></p>
<p><font color="#000000">包通常总是一个目录，目录下为首的一个文件便是 __init__.py。然后是一些模块文件和子目录，假如子目录中也有 __init__.py 那么它就是这个包的子包了。差不多就像这样吧：</font></p>
<p><span id="more-790"></span></p>
<pre>Package1/ __init__.py

    Module1.py

    Module2.py

    Package2/ __init__.py

       Module1.py

       Module2.py</pre>
<p><font color="#000000">我们可以就这样导入一个包：</font></p>
<pre>import Package1</pre>
<p><font color="#000000">或者调入一个子模块和子包：</font></p>
<pre>from Package1 import Module1

from Package1 import Package2

import Packag1.Module1

import Packag1.Package2</pre>
<p><font color="#000000">可以深入好几层包结构：</font></p>
<pre>from Package1.Package2 import Module1

import Package1.Package2.Module1</pre>
<p><font color="#000000">大致就这样吧，我觉得，包的精髓应该是在 __init__.py 这个文件之中的。<br />
	</font></p>
<p>
	&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong><font color="#000000">__init__.py 文件:<br />
	</font></strong><br />
	<font color="#000000">__init__.py 控制着包的导入行为。假如 __init__.py 为空，那么仅仅导入包是什么都做不了的。</font></p>
<pre>&gt;&gt;&gt; import Package1

&gt;&gt;&gt; Package1.Module1

Traceback (most recent call last):
 File &quot;&lt;pyshell#1&gt;&quot;, line 1, in ?
 Package1.Module1

AttributeError: &#39;module&#39; object has no attribute &#39;Module1&#39;</pre>
<p><font color="#000000">我们需要在 __init__.py 里把 Module1 预先导入：</font></p>
<pre><span style="color: rgb(0,153,0)">#文件 __init__.py</span>

import Module1</pre>
<p><font color="#000000">测试：</font></p>
<pre>&gt;&gt;&gt; import Package1

&gt;&gt;&gt; Package1.Module1

&lt;module &#39;Package1.Module1&#39; from
&#39;Module.pyc&#39;&gt;</pre>
<p><font color="#000000">__init__.py 中还有一个重要的变量，叫做 __all__。我们有时会使出一招&ldquo;全部导入&rdquo;，也就是这样：</font></p>
<pre>from PackageName import *</pre>
<p><font color="#000000">这时 import 就会把注册在包 __init__.py 文件中 __all__ 列表中的子模块和子包导入到当前作用域中来。比如：</font></p>
<pre>#文件 __init__.py

__all__ = [&#39;Module1&#39;, &#39;Module2&#39;, &#39;Package2&#39;]</pre>
<p><font color="#000000">测试：</font></p>
<pre>&gt;&gt;&gt; from Package1 import *

&gt;&gt;&gt; Module2

&lt;module &#39;Package1.Module2&#39; from &#39;Module.pyc&#39;&gt;</pre>
<p><font color="#000000">__init__.py 文件会在导入时被执行。</font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/790/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>python中字符串和变量名相互转换问题</title>
		<link>http://www.linux-field.com/archives/788</link>
		<comments>http://www.linux-field.com/archives/788#comments</comments>
		<pubDate>Tue, 27 Dec 2011 09:22:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[基础知识]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=788</guid>
		<description><![CDATA[http://markmail.org/message/wdneu2oyzmgl7ynf 2008/5/24 liz &#60;shen&#8230;@gmail.com&#62; 大家好～ 现想实现以下功能： 1、使用字符串指代变量名。 比如说，有两个变量 a=&#34;bbb&#34;和bbb={&#34;c&#34;:1}，引用a如何得到{&#34;c&#34;:1}，也就是a的值&#39;bbb&#39;所代表的变量bbb的值。 google了下，查到http://www.douban.com/group/topic/2193745/上的以下四种方式能够将字符串转作变量，分别是： exec(&#39;abc = 5&#39;) globals()[&#39;abc&#39;] = 6 setattr(__builtins__, &#39;abc&#39;, 9) __import__(&#39;sys&#39;)._getframe(0).f_globals[&#39;abc&#39;] = 27 四种都可以实现，那么，对于引用a如何得到{&#34;c&#34;:1}，则应该是： a=&#39;bbb&#39; bbb={&#34;c&#34;:1} exec(&#39;a=%s&#39; % a) a {&#34;c&#34;: 1} 即可实现。有没其他方法了？ globals()[a] 另外，若想把exec的字符串&#39;a=%s&#39; % a中的a动态改变，而不是指定a，那岂不要先获得变量a的名字。就是第2个问题。 2、从变量名获得其字符串 比如说，变量a=&#39;bbb&#39;，一般引用a后结果是a的值&#39;bbb&#39;，那我该如何得到a的名字字符串&#39;a&#39;? 有没必要? 没必要。 在程序中如何得到一个变量的变量名字符串？ 似乎没什么好办法（也许是没必要）。 不过python号称一切皆对象，那么变量的所有属性，包括变量名都应该可以获取才对啊。 不知哪位有什么好办法？ 谢谢！ &#8211; blog : http://www.leefurong.cn photo:http://picasaweb.google.com/leefurong Cell phone: +86 13651506196]]></description>
			<content:encoded><![CDATA[<p><a href="http://markmail.org/message/wdneu2oyzmgl7ynf">http://markmail.org/message/wdneu2oyzmgl7ynf</a></p>
<div class="messagebody" id="body">
<div class="pws">
<p>2008/5/24 liz &lt;<span>shen<a class="email mklink">&#8230;</a>@gmail.com</span>&gt;</p>
<div class="quote quote-1">
<p>大家好～</p>
<p>现想实现以下功能： 1、使用字符串指代变量名。 比如说，有两个变量 a=&quot;bbb&quot;和bbb={&quot;c&quot;:1}，引用a如何得到{&quot;c&quot;:1}，也就是a的值&#39;bbb&#39;所代表的变量bbb的值。 google了下，查到http://www.douban.com/group/topic/2193745/上的以下四种方式能够将字符串转作变量，分别是： exec(&#39;abc = 5&#39;) globals()[&#39;abc&#39;] = 6 setattr(__builtins__, &#39;abc&#39;, 9) __import__(&#39;sys&#39;)._getframe(0).f_globals[&#39;abc&#39;] = 27 四种都可以实现，那么，对于引用a如何得到{&quot;c&quot;:1}，则应该是：</p>
<div class="quote quote-2">
<div class="quote quote-3">
<div class="quote quote-4">
<p>a=&#39;bbb&#39; bbb={&quot;c&quot;:1} exec(&#39;a=%s&#39; % a) a</p>
</p></div>
</p></div>
</p></div>
<p>{&quot;c&quot;: 1} 即可实现。有没其他方法了？</p>
</p></div>
<p>globals()[a]</p>
<div class="quote quote-1">
<p>另外，若想把exec的字符串&#39;a=%s&#39; % a中的a动态改变，而不是指定a，那岂不要先获得变量a的名字。就是第2个问题。</p>
<p>2、从变量名获得其字符串 比如说，变量a=&#39;bbb&#39;，一般引用a后结果是a的值&#39;bbb&#39;，那我该如何得到a的名字字符串&#39;a&#39;? 有没必要?</p>
</p></div>
<p>没必要。 在程序中如何得到一个变量的变量名字符串？ 似乎没什么好办法（也许是没必要）。 不过python号称一切皆对象，那么变量的所有属性，包括变量名都应该可以获取才对啊。 不知哪位有什么好办法？</p>
<div class="quote quote-1">
<p>谢谢！</p>
</p></div>
<div class="footer signature">
<p>&#8211; blog : <a class="exlink mklink" href="http://www.leefurong.cn/" rel="nofollow">http://www.leefurong.cn</a> photo:<a class="exlink mklink" href="http://picasaweb.google.com/leefurong" rel="nofollow">http://picasaweb.google.com/leefurong</a> Cell phone: +86 13651506196</p>
</p></div>
</p></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/788/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jinja2学习笔记暨官方文档的翻译[zt]</title>
		<link>http://www.linux-field.com/archives/786</link>
		<comments>http://www.linux-field.com/archives/786#comments</comments>
		<pubDate>Mon, 26 Dec 2011 09:02:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[flask]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=786</guid>
		<description><![CDATA[http://blog.csdn.net/lgg201/article/details/4647471 呵呵, 刚刚看完Python模板引擎Jinja2的文档, 感觉很好, 觉得动态语言真是很好.&#160; 模板引擎竟然可以做的如此灵活&#8230;.真是不错&#8230;. &#160; &#160; 下面直接把看文档过程的笔记发布出来, 呵呵, 基本上就是翻译, 加了不多的一点自己的解释&#8230;&#8230;希望可以帮到大家 &#160; &#160; 补充： 1. 在模板中设置自定义变量： &#160;&#160;&#160; {%&#160;set variable_name = value&#160;%} &#160;&#160; 比如设置{%&#160;set username&#160;=&#160;&#39;Jack&#39;&#160;%} &#160; 那么在设置之后就可以使用{{ username }}得到输出Jack &#160; &#160; &#160; section 1 API 1 jinja2的Hello world: import jinja2 as jj template = jj.Template(&#8216;Hello {{where}}&#8217;) template.render(where = &#8216;World&#8217;) 基础: 2.1 jinja2中有一个核心对象: template Environment(模板环境), 这个类的实例被用于存储配置信息, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.csdn.net/lgg201/article/details/4647471">http://blog.csdn.net/lgg201/article/details/4647471</a></p>
<p>呵呵, 刚刚看完Python模板引擎Jinja2的文档, 感觉很好, 觉得动态语言真是很好.&nbsp; 模板引擎竟然可以做的如此灵活&#8230;.真是不错&#8230;.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>下面直接把看文档过程的笔记发布出来, 呵呵, 基本上就是翻译, 加了不多的一点自己的解释&#8230;&#8230;希望可以帮到大家</p>
<p>&nbsp;</p>
<p><span id="more-786"></span></p>
<p>&nbsp;</p>
<p>补充：</p>
<p>1. 在模板中设置自定义变量：</p>
<p>&nbsp;&nbsp;&nbsp; {%&nbsp;set variable_name = value&nbsp;%}</p>
<p>&nbsp;&nbsp; 比如设置{%&nbsp;set username&nbsp;=&nbsp;&#39;Jack&#39;&nbsp;%}</p>
<p>&nbsp; 那么在设置之后就可以使用{{ username }}得到输出Jack</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1>section 1 API</h1>
<p style="margin-left:8.5pt;">1 jinja2的Hello world:</p>
<p>import jinja2 as jj</p>
<p>template = jj.Template(&lsquo;Hello {{where}}&rsquo;)</p>
<p>template.render(where = &lsquo;World&rsquo;)</p>
<p style="margin-left:8.5pt;">基础:</p>
<p style="margin-left:17pt;">2.1 jinja2中有一个核心对象: template Environment(模板环境), 这个类的实例被用于存储配置信息, 全局对象, 从文件系统或其他位置加载模板, 甚至如果你使用Template的构造器创建一个String类型的模板的时候, 也会自动的创建一个Environment对象.</p>
<p style="margin-left:17pt;">2.2 Environment一般在一个应用中只创建一个, 当系统中有不同的配置需求的时候, 就需要创建多个Environment对象相互支持.</p>
<p align="left" style="margin-left:17pt;">创建一个Environment对象: env = Environment(loader = FileSystemLoader(&lsquo;templates&rsquo;))&hellip;意思是创建一个template Environment对象, 使用的加载器loader是FileSystemLoader类型, 可以加载的模板是当前工作目录下的templates目录下的模板文件.</p>
<p align="left" style="margin-left:17pt;">加载一个模板: template = env.get_template(&lsquo;mytemplate.txt&rsquo;), 使用env的模板环境加载名为mytemplate.txt的模板文件.</p>
<p align="left" style="margin-left:17pt;">渲染一个模板: template.render(name = &lsquo;Jack&rsquo;), 渲染模板template, 传入了模板参数name值为Jack</p>
<p align="left" style="margin-left:8.5pt;">高级api</p>
<p align="left" style="margin-left:17pt;">3.1 class Environment(block_start_string = &lsquo;{%&rsquo;, block_end_string = &lsquo;%}&rsquo;, variable_start_string = &lsquo;{{&rsquo;, variable_end_string = &lsquo;}}&rsquo;, comment_start_string = &lsquo;{#&rsquo;, comment_end_string = &lsquo;#}&rsquo;, line_statement_prefix = None, trim_blocks = False, extensions = (), optimized = True, undefined = &lt;class &lsquo;jinja2.runtime.Undefined&rsquo;&gt;, finalize = None, autoescape = False, loader = None, cache_size = 50, auto_reload = True):&nbsp; 下面单独列出的属性解释不都是构造器中的参数</p>
<p align="left" style="margin-left:25.5pt;">3.1.1 block_start_string = &lsquo;{%&rsquo;, block_end_string = &lsquo;%}&rsquo;, variable_start_string = &lsquo;{{&rsquo;, variable_end_string = &lsquo;}}&rsquo;, comment_start_string = &lsquo;{#&rsquo;, comment_end_string = &lsquo;#}&rsquo;用来定义块, 变量, 注释的开始和结束标记.</p>
<p align="left" style="margin-left:25.5pt;">3.1.2 line_statement_prefix: 单行语句前缀</p>
<p align="left" style="margin-left:25.5pt;">3.1.3 trim_blocks: 布尔值, 块后面的第一行将会被移除(块, 非变量标签), 默认是False</p>
<p align="left" style="margin-left:25.5pt;">3.1.4 extensions: Jinja的扩展对象列表, 可以是导入路径的字符串或扩展类</p>
<p align="left" style="margin-left:25.5pt;">3.1.5 optimized: 布尔值, 表明优化是否允许.</p>
<p align="left" style="margin-left:25.5pt;">3.1.6 undefined: jinja2.runtime.Undefined或其子类的实例, 用来描绘模板中的值为undefined的变量</p>
<p align="left" style="margin-left:25.5pt;">3.1.7 finalize: 一个可调用对象, 用来最终确定一个变量, 默认使用apply, 需要HTML转码时可以设置为escape</p>
<p align="left" style="margin-left:25.5pt;">3.1.8 autoescape: 设置为true就打开了XML/HTML的自动escape功能</p>
<p align="left" style="margin-left:25.5pt;">3.1.9 cache_size: 缓存大小, 默认50, 意思是如果有超过50个模板被加载器加载, 就会清理刚刚使用过的模板.&nbsp; 如果设置为0, 表示所有的模板都会被重编译, 也就是不使用缓存, 如果设置为-1, 表示缓存不会被清理.</p>
<p align="left" style="margin-left:25.5pt;">3.1.10 auto_reload: 如果模板的文件发生了变化, 加载器会重新编译该模板进行加载.</p>
<p align="left" style="margin-left:25.5pt;">3.1.11 shared: 使用Template的构造器创建一个模板的时候, 会自动的创建一个Environment对象, 这个Environment对象就是一个共享的Environment对象, 很多模板都共享着同一个匿名Environment对象, 对于共享Environment对象而言, shared属性为True, 其他情况都是False</p>
<p align="left" style="margin-left:25.5pt;">3.1.12 sandboxed: SandboxedEnvironment的实例对象此属性为True</p>
<p align="left" style="margin-left:25.5pt;">3.1.13 filters: 一个字典描述的filters过滤器集合, 如果非模板被加载的时候, 可以安全的添加filters或移除较早的.</p>
<p align="left" style="margin-left:25.5pt;">3.1.14 tests: 一个字典描述的测试函数集合, 如果非模板被加载, 可以安全的修改这个字典.</p>
<p align="left" style="margin-left:25.5pt;">3.1.15 globals: 一个字典描述的全局变量集合, 这些变量可以在所有的模板中使用, 并且不能被模板重写(如果optimizer设置为允许). 如果非模板被加载, 它可以安全的修改这个字典.</p>
<p align="left" style="margin-left:25.5pt;">3.1.16 from_string(source, globals = None, template_class = None): 从一个字符串加载一个模板, 将source指定的字符串转换成一个模板对象.&nbsp;&nbsp; 该方法是一个实例方法</p>
<p align="left" style="margin-left:25.5pt;">3.1.17 join_path(template, parent): 不知道用途. 联接一个模板和父模板.&nbsp; 通过默认的查找查找关联的根, 这个方法返回没有修改过的template参数, 但是, 如果paths可以随父模板改变, 这个函数就可以用来得到模板的真实名称.(模板父名称+模板名称???), 子类可以重写这个方法实现自己的模板路径联接</p>
<p align="left" style="margin-left:25.5pt;">3.1.18 get_template(name, parent = None, globals = None): 加载一个模板, 如果parent参数不是None, 会调用join_path()方法得到模板的真实名称在加载之前.&nbsp; 如果加载器配置了这个方法就会加载name指定的模板.&nbsp; globals参数用来提供编译时的全局模板参数, 未来可能会允许优化的渲染templates的部分在编译时&hellip;&hellip;&hellip;.编译不允许有TemplateNotFound异常</p>
<p align="left" style="margin-left:25.5pt;">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): &nbsp;获取一个新的Environment, 该对象继承获得所有当前Environment对象的配置属性, 调用此方法传递的参数会覆盖原有的配置属性.</p>
<p align="left" style="margin-left:17pt;">3.2 class Template(): 核心的模板对象, 用来提供使用构造器创建模板对象, 构造器参数和Environment的相同, 但是不能提供loader, 使用构造器创建的模板对象有一个临时的Environment对象, 这个对象和所有其他使用构造器创建的Template共享.&nbsp;&nbsp; 下面介绍Template中的主要成员:</p>
<p align="left" style="margin-left:25.5pt;">3.2.1 globals: 模板中使用的全局变量???</p>
<p align="left" style="margin-left:25.5pt;">3.2.2 name: 返回加载模板时指定的名称(如果是FileSystemLoader加载的, 会返回文件名.)</p>
<p align="left" style="margin-left:25.5pt;">3.2.3 render(*args, **kwargs): 接受关键字参数或字典作为参数.&nbsp; 返回渲染模板的结果字符串</p>
<p align="left" style="margin-left:25.5pt;">3.2.4 stream(*args, **kwargs): 接受参数同上, 返回一个TemplateStream对象, TemplateStream做类似生成器的工作.</p>
<p align="left" style="margin-left:25.5pt;">3.2.5 generate(*agrs, **kwargs): 对于很大的模板, 使用generate接口并不会一次渲染整个模板, 而是返回一个生成器, 每次next的时候, 使用yield方式生成一个模板片段.</p>
<p align="left" style="margin-left:25.5pt;">3.2.6 module: 是一个TemplateModule对象, 该对象对用于运行时导出模板变量.例如:</p>
<p align="left" style="margin-left:17pt;">t = Template(&ldquo;{% macro foo() %}42{% endmacro %}&rdquo;)</p>
<p align="left" style="margin-left:17pt;">t.module.foo()就会返回42</p>
<p align="left" style="margin-left:25.5pt;">3.2.7 make_module(vars = None, shared = False): 不传递参数相当于module属性.&nbsp; 传递参数功能未知.</p>
<p align="left" style="margin-left:17pt;">3.3 class TemplateStream(gen): 一个模板流, 和python的生成器工作原理基本相同, 但是, 这里可以通过更多项的缓存, 以减少迭代次数., 默认是不支持缓存的, 可以通过enable_buffering()开启缓存</p>
<p align="left" style="margin-left:25.5pt;">3.3.1 disable_buffering(): 展示输出缓存</p>
<p align="left" style="margin-left:25.5pt;">3.3.2 enable_buffering(size = 5): 开启缓存, 缓存的项数默认是5, 缓存发生的时机在yielding之前</p>
<p align="left" style="margin-left:8.5pt;">4 Undefined Types: Environment的构造器中提供了设置接口, 如果在模板中查找不到一个名称或不能访问一个属性的时候, 就会创建一个Undefined对象并返回.</p>
<p align="left" style="margin-left:17pt;">4.1 class Undefined(hint = None, obj = None, name = None): 默认的Undefined类型, 这个undefined类型只能被打印, 遍历, 布尔判断, 其他的任何访问都会引发UndefinedError.</p>
<p align="left" style="margin-left:17pt;">4.2 class DebugUndefined(hint = None, obj = None, name = None): 用来打印返回debug信息的Undefined类型</p>
<p align="left" style="margin-left:17pt;">4.3 class StrictUndefined(hint = None, obj = None, name = None):</p>
<p align="left" style="margin-left:8.5pt;">上下文环境:</p>
<p align="left" style="margin-left:17pt;">5.1 class Context(environment, parent, name, blocks): 用来保存模板的上下文环境变量. 不支持直接创建实例, 因为它是在模板的不同评估阶段自动创建的.&nbsp; Context对象是不可变的, 不可以在parent中修改, 只允许在创建template代码的时候在vars上修改. 模板的filters和全局函数被标记为contextfunction(), 当前活动的context会作为第一个参数被传递给这些全局函数, 并且是只读的.</p>
<p align="left" style="margin-left:17pt;">上下文环境支持只读的字典操作: get, __getitem__, __contains__, 然而__getitem__失败之后不会发生KeyError, 而是返回一个Undefined对象.</p>
<p align="left" style="margin-left:17pt;">属性解释:</p>
<p align="left" style="margin-left:25.5pt;">5.3.1 parent: 一个只读的字典, 其中存放全局变量, 这些变量可能来自另外的Context实例, Enviroment.globals或者Template.globals. 他们都是不可修改的.</p>
<p align="left" style="margin-left:25.5pt;">5.3.2 vars: 模板的本地变量. 是字典类型, &nbsp;包含了来自parent的environment和 context functions作为本地的可以从模板修改和导出的变量. 模板将会修改这个字典在评估template的时候, 但是filters和context functions是只读的.</p>
<p align="left" style="margin-left:25.5pt;">5.3.3 environment: 加载这个模板的environment对象</p>
<p align="left" style="margin-left:25.5pt;">5.3.4 exported_vars: 这个集合包含所有template导出的名称, 名称的值在vars字典中.&nbsp; 可以通过get_exported()方法获得一个新的导出变量字典.</p>
<p align="left" style="margin-left:25.5pt;">5.3.5 name: 拥有这个context的模板的加载名</p>
<p align="left" style="margin-left:25.5pt;">5.3.6 blocks: 一个当前已经映射的block字典. keys是所有block的名字, 值是所有block的注册值. 最后一项是当前活动的block</p>
<p align="left" style="margin-left:25.5pt;">5.3.7 super(name, current): 渲染一个父级的block</p>
<p align="left" style="margin-left:25.5pt;">5.3.8 get(key, default = None): 获取模板context中的一项, 如果key不存在, 返回default</p>
<p align="left" style="margin-left:25.5pt;">5.3.9 get_exported(): 返回一个exporeted variables字典</p>
<p align="left" style="margin-left:25.5pt;">5.3.10 get_all(): 返回一个完整的context拷贝(包含所有的全局变量)</p>
<p align="left" style="margin-left:8.5pt;">加载器</p>
<p align="left" style="margin-left:17pt;">所有的加载器继承自BaseLoader, 可以通过继承BaseLoader并重写get_source方法创建自己的加载器.</p>
<p align="left" style="margin-left:17pt;">6.2 class BaseLoader(): 所有加载器的基类&hellip;.Environment 提供的get_template方法会调用加载器的get_source()加载模板.</p>
<p align="left" style="margin-left:25.5pt;">6.2.1 get_source(environment, template): 获取模板的源, 文件名和reload帮助器.&nbsp; 接受environment和模板名, 返回一个元组(source, filename, uptodate), 如果加载不到, 可以触发TemplateNotFound异常.&nbsp;&nbsp;&nbsp; 返回的source是模板的unicode或ASCII字符串形式.&nbsp; 文件名必须是真正在文件系统中存在的文件全路径, 如果不是从文件系统加载可以返回None, 最后一个返回uptodate是一个函数, 如果自动reloading允许, 就会在模板的源发生改变的时候自动调用这个方法. 这个函数不接受任何参数, 因此需要在函数中保留一些原来的状态, 可以使用闭包来保存状态.&nbsp; 如果这个uptadate方法返回的是False, 模块就会被重新加载一次.</p>
<p align="left" style="margin-left:25.5pt;">6.2.2 load(environment, name, globals = None): 甲子啊一个模板, 这个方法从缓存中查找一个模板或调用get_source()加载.&nbsp; 子类可以重写这个方法来改变加载方式.</p>
<p align="left" style="margin-left:17pt;">其他的jinja2内建加载器:</p>
<p align="left" style="margin-left:25.5pt;">6.3.1 class FileSystemLoader(searchpath, encoding = &lsquo;utf-8&rsquo;): 从文件系统加载</p>
<p align="left" style="margin-left:25.5pt;">6.3.2 class PackageLoader(package_name, package_path = &lsquo;templates&rsquo;, encoding = &lsquo;utf-8&rsquo;): 从包中加载</p>
<p align="left" style="margin-left:25.5pt;">6.3.3 DictLoader(mapping): 从指定字典中加载</p>
<p align="left" style="margin-left:25.5pt;">6.3.4 FunctionLoader(load_func): 调用指定的函数加载, 该函数返回一个元组tuple(source, filename, uptodatefunc), 其中uptodatefunc同BaseLoader.get_source()返回中的uptodatefunc, 用来在重加载时判断是否需要重加载.&nbsp; 返回False会进行重加载</p>
<p align="left" style="margin-left:25.5pt;">6.3.5 PrefixLoader(mapping, delimiter = &lsquo;/&rsquo;): 前缀加载器, mapping是一个字典, {&lsquo;loader1&rsquo;: loader1, &lsquo;loader2&rsquo;: loader2}, 则加载&rsquo;loader1/template.html会调用loader1加载器, delimiter是一个间隔字符串, delimiter之前的就会被作为mapping的key获取具体的加载器.</p>
<p align="left" style="margin-left:25.5pt;">6.3.6 ChoiceLoader(loaders): 接受一个加载器列表, 在加载模板的时候, 如果使用其中一个加载器加载失败就会选用下一个加载器继续加载.</p>
<p align="left" style="margin-left:8.5pt;">公共工具: 用来自定义filter和函数</p>
<p align="left" style="margin-left:17pt;">7.1 environmentfilter(f): 装饰器, 标记为environment依赖的filter, filter会作为filter的第一个参数被传递.</p>
<p align="left" style="margin-left:17pt;">7.2 contextfilter(f): 装饰器, 标记为context依赖filter, 当前context会作为第一个参数被传递给filter.</p>
<p align="left" style="margin-left:17pt;">7.3 environmentfunction(f): 该装饰器被用于标记一个可调用对象作为enviroment的可调用对象,</p>
<p align="left" style="margin-left:17pt;">7.4 contextfunction(f): 该装饰器被用于标记一个可调用对象作为context的可调用对象,</p>
<p align="left" style="margin-left:17pt;">7.5 escape(s): 转换(&amp;, &lt;, &gt;, &ldquo;)字符成为HTML的安全序列.&nbsp; 返回的是一个Markup对象, 由于Markup是标记为安全的不需要escape的, 所以, 一个串是不可能被二次escape的.&nbsp; 如果需要自动转码, 可以将environment的finalize属性设置为escape</p>
<p align="left" style="margin-left:17pt;">7.6 clear_caches(): 清理缓存的接口.</p>
<p align="left" style="margin-left:17pt;">7.7 class Markup()&nbsp; 标记一个string包含的html/xml是安全的, 不需要escape&hellip;.</p>
<p align="left" style="margin-left:8.5pt;">异常:</p>
<p align="left" style="margin-left:17pt;">8.1 TemplateError(): 所有模板异常的基类</p>
<p align="left" style="margin-left:17pt;">8.2 UndefinedError(): 模板尝试操作一个Undefined类型的时候触发异常</p>
<p align="left" style="margin-left:17pt;">8.3 TemplateNotFound(name): 模板查找不到的异常, 参数是模板的名称</p>
<p align="left" style="margin-left:17pt;">8.4 TemplateSyntaxError(message, lineno, filename): 模板内部有语法错误的时候触发, message是异常消息, lineno是异常发生的行号, filename是发生异常的模板的文件名.</p>
<p align="left" style="margin-left:17pt;">8.5 TemplateAssertionError(message, lineno, filename): 不懂</p>
<p align="left" style="margin-left:8.5pt;">自定义过滤器: 在模板中使用{{ obj | myfilter(args)}}对应的就会调用过滤器:</p>
<p align="left">def myfilter(obj, args):</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass</p>
<p align="left" style="margin-left:17pt;">自定义过滤器的注册: environment.filters[&lsquo;filter_name&rsquo;] = filter, 内建的filters可以通过调用environment.filters获取.</p>
<p align="left" style="margin-left:17pt;">注册为environment过滤器使用装饰器environmentfilter</p>
<p align="left" style="margin-left:17pt;">注册为context过滤器使用装饰器contextfilter</p>
<p align="left" style="margin-left:8.5pt;">自定义测试: 在模板中使用{% if obj is test_name %}的方式进行测试.</p>
<p align="left" style="margin-left:17pt;">10.1 test返回的必须是True或False.</p>
<p align="left" style="margin-left:17pt;">10.2 test的注册: environment.tests[&lsquo;test_name&rsquo;] = test</p>
<p align="left" style="margin-left:17pt;">同样可以使用environment.tests获取所有内建的tests</p>
<p align="left" style="margin-left:17pt;">注册为environment过滤器使用装饰器environmentfunction??</p>
<p align="left" style="margin-left:17pt;">注册为context过滤器使用装饰器contextfunction???</p>
<p align="left" style="margin-left:8.5pt;">全局名称空间: Environment.globals, 或Template.globals</p>
<h1>section 2 Template Designer</h1>
<p align="left" style="margin-left:8.5pt;">概要:</p>
<p align="left" style="margin-left:17pt;">一个模板就是一个简单的文本文件, 它可以生成任何基于文本的格式(HTML, XML, CSV, LaTeX 等等), 没有明确的扩展名, .html, .xml 或者其他任何都可以.</p>
<p align="left" style="margin-left:17pt;">模板包含变量(或表达式), 当模板被评估(解析)的时候这些变量会被替换成值.</p>
<p align="left" style="margin-left:17pt;">模板有一些标签, 用来控制模板解释时的逻辑.</p>
<p align="left" style="margin-left:17pt;">模板的语法多是使用Django和python创造的.</p>
<p align="left" style="margin-left:17pt;">1.5 {% %}用来执行语句, {{ }}用来返回一个变量的值.</p>
<p align="left" style="margin-left:8.5pt;">变量:</p>
<p align="left" style="margin-left:17pt;">可以使用.号来获取对象的属性</p>
<p align="left" style="margin-left:17pt;">支持切片操作</p>
<p align="left" style="margin-left:17pt;">如果访问的对象在模板中没有被找到, 就返回一个预定义的Undefined对象.</p>
<p align="left" style="margin-left:8.5pt;">过滤器:</p>
<p align="left" style="margin-left:17pt;">变量的修改可以使用过滤器.</p>
<p align="left" style="margin-left:17pt;">过滤器的语法是使用管道操作符|, 过滤器可以多重嵌套使用, 前面的过滤器的返回值将会作为下一个过滤器的第一个输入参数.&nbsp;&nbsp; 这里的管道和linux的管道概念上是类似的, 将前面的表达式的返回值交给后面的表达式(或函数)处理</p>
<p align="left" style="margin-left:8.5pt;">测试: 和filter类似, is前面的值将会被作为test的第一个参数传入, 如果还有其他的参数, test名称后面加空格跟随其他参数, 或者使用方法调用符&rdquo;()&rdquo;进行参数的传入.</p>
<p align="left" style="margin-left:8.5pt;">注释: {#&nbsp; #}中间包含注释语句.</p>
<p align="left" style="margin-left:8.5pt;">模板继承: 通过在一个框架模板中定义一些公用的输出, 在通过定义子块block达到代码共享, 这样, 其他的模板继承框架模板, 就不用再写重复的公用代码.&nbsp;&nbsp; 其中的block在父模板中可以有实现, 在子类中通过重写达到多态效果.</p>
<p align="left" style="margin-left:17pt;">定义block: {% block block_name %} {% endblock %}</p>
<p align="left" style="margin-left:17pt;">子模板中继承父模板: {% extends &lsquo;base.html&rsquo; %}, 这一句告诉模板引擎, 这个模板继承另一个模板, 当解析这个模板的时候, 首先会本地化它的父模板. extends标签如果有则必须是模板中的第一个标签.</p>
<p align="left" style="margin-left:17pt;">在同一个模板中, 不允许有重名的block</p>
<p align="left" style="margin-left:17pt;">在模板中, 可以通过self获取自身的引用来调用指定名字的block内容, 例如{{self.block_name }}</p>
<p align="left" style="margin-left:17pt;">在block中, 如果重写了父模板的block, 又期望显示父模板的内容(当只是对父模板做了一些填充性的扩展需求发生时), 可以使用{{super()}}来显示父模板中该block的内容</p>
<p align="left" style="margin-left:8.5pt;">7 HTML Escaping</p>
<p align="left" style="margin-left:17pt;">当从模板生成一个HTML的时候, 会由于变量包含一些HTML标签带来危险. 对于这个问题有两种解决方法: 手动转码每个变量或者通过默认指定自动转码所有的变量</p>
<p align="left" style="margin-left:17pt;">7.2 Jinja2对两种解决方法都支持, 具体使用哪个根据应用程序的配置, 默认的配置是非自动转码.</p>
<p align="left" style="margin-left:17pt;">默认使用手动转码的原因:</p>
<p align="left" style="margin-left:25.5pt;">自动转码会对所有的变量都进行转码, 对于很多的变量实际上是不包含HTML元素的, 也就不会产生安全影响, 这样转码就会对性能带来影响.</p>
<p align="left" style="margin-left:25.5pt;">变量的安全信息是非常脆弱的, 可能会因为转码和解码导致数据丢失.</p>
<p align="left" style="margin-left:17pt;">使用手动转码的工作方式:</p>
<p align="left" style="margin-left:25.5pt;">对于可能包含&gt;, &lt;, &amp;, &ldquo;等字符的不可靠变量进行转码</p>
<p align="left" style="margin-left:25.5pt;">转码使用管道调用filter: {{user.username | e}}</p>
<p align="left" style="margin-left:17pt;">使用自动转码的工作方式: 会对所有未设置为安全的变量进行转码</p>
<p align="left" style="margin-left:8.5pt;">8 For:&nbsp; {% for user in users %} {% endfor %}: 下面列出for循环块内部可用的变量</p>
<p align="left" style="margin-left:17pt;">8.1 loop.index: 当前迭代索引, 1开始</p>
<p align="left" style="margin-left:17pt;">8.2 loop.index0: 当前迭代索引, 0开始</p>
<p align="left" style="margin-left:17pt;">8.3 loop.revindex: 当前迭代到结束还有多少个元素, 包含当前元素</p>
<p align="left" style="margin-left:17pt;">8.4 loop.revindex: 当前迭代到结束还有多少个元素, 不包含当前元素.</p>
<p align="left" style="margin-left:17pt;">8.5 loop.first: 当前迭代元素是否是第一个元素</p>
<p align="left" style="margin-left:17pt;">8.6 loop.last: 当前迭代元素是否是最后一个元素</p>
<p align="left" style="margin-left:17pt;">8.7 loop.length: 迭代对象一共有多少个元素</p>
<p align="left" style="margin-left:17pt;">8.8 loop.cycle: 返回一个包装的Cycle对象. 该对象描述迭代的当前状态.</p>
<p align="left" style="margin-left:8.5pt;">9 If: {% if bool_expression %}</p>
<p align="left" style="margin-left:8.5pt;">10 Macros: {% macro macro_name(args, kwargs) %} 内部可以使用传入的参数, 就像普通的方法的方法体 {% endmacro %}</p>
<p align="left" style="margin-left:17pt;">10.1 Macros的调用: {{macro_name(*args, **kwargs)}}&nbsp; 返回的是定义的macro的标签体内的输出.</p>
<p align="left" style="margin-left:17pt;">内置属性:&nbsp; 可以在{% macro %}和{% endmacro %}之间使用的属性</p>
<p align="left" style="margin-left:25.5pt;">10.2.1 varargs: 如果调用时传递的位置参数多于定义的位置参数, 多出的会以一个元组的形式保存在这个变量中</p>
<p align="left" style="margin-left:25.5pt;">10.2.2 kwargs: 如果调用时传递的关键字参数多于定义的关键字参数, 多出的会以一个字典的形式保存在这个变量中</p>
<p align="left" style="margin-left:25.5pt;">10.2.3 caller: 调用这个macro对象的call对象, 该对象是一个可调用对象, 可以使用{{caller()}}的方式获取call中的自己输出.</p>
<p align="left" style="margin-left:17pt;">外部可调用属性:&nbsp; 可以在macro定义外部通过macro_name.field_name调用的属性</p>
<p align="left" style="margin-left:25.5pt;">10.3.1 name: 获取macro定义的名称</p>
<p align="left" style="margin-left:25.5pt;">10.3.2 arguments: 获取定义中的所有参数名称, 返回一个元组</p>
<p align="left" style="margin-left:25.5pt;">10.3.3 defaults: 获取所有定义中的有默认值的参数的默认值.</p>
<p align="left" style="margin-left:25.5pt;">10.3.4 catch_kwargs: 如果为True表示macro的定义可以接受扩展关键字参数, 也就是可以接受在定义中没有指定的参数</p>
<p align="left" style="margin-left:25.5pt;">10.3.5 catch_varargs: 如果为True表示macro的定义可以接受扩展位置参数, 也就是可以接受在定义中没有指定的参数</p>
<p align="left" style="margin-left:25.5pt;">10.3.6 caller: 布尔类型, 表明在macro定义中是否调用了caller()对象</p>
<p align="left" style="margin-left:8.5pt;">11 Call: {% call macro_name(*args, **kwargs)%}内部可以定义自己的输出{% endcall %},</p>
<p align="left" style="margin-left:17pt;">用来对macro定义的函数的扩展.</p>
<p align="left" style="margin-left:17pt;">在调用的时候, 还可以使用参数传递:</p>
<p align="left" style="margin-left:25.5pt;">在macro定义中调用时, 使用{{call(*args, **kwargs)}}的方式进行调用, 就会把参数传递给{% call %}</p>
<p align="left" style="margin-left:25.5pt;">在{% call %}中需要接受参数时使用{% call(*args, **kwargs) macro_name(*args, **kwargs) %}</p>
<p align="left" style="margin-left:8.5pt;">12 Assignments: 为模板指定别名的语法: {% navigation = [(&lsquo;index.html&rsquo;, &lsquo;index&rsquo;), (&lsquo;about.html&rsquo;, &lsquo;about&rsquo;)] %}</p>
<p align="left" style="margin-left:8.5pt;">13 Block: 定义模板中的块</p>
<p align="left" style="margin-left:8.5pt;">14 Include: 将预定义的模板引入到当前模板中, 语法是{% include &lsquo;template_name&rsquo;%}, 这个标签没有结束符, 默认会传递当前context到被引入的模板</p>
<p align="left" style="margin-left:8.5pt;">15 Import: {% import &lsquo;template_name&rsquo; as new_name %} 将一个模板引入作为新的变量, 就跟模块的引入相似, 引入后可以使用.点号操作符获取其中定义的macro等元素, 也可以使用from-import语法{% from &lsquo;template_name&rsquo; import element_name as new_name %}将模板中的元素引入并赋予一个新的名称.&nbsp; 默认不会传递当前的context到被引入的模板</p>
<p align="left" style="margin-left:8.5pt;">16 Import Context Behavior:</p>
<p align="left" style="margin-left:17pt;">16.1 {% import &lsquo;template_name&rsquo; with context %}, 引入template并传递当前context, 同样, from-import的引入方法也使用with context语法</p>
<p align="left" style="margin-left:17pt;">16.2 {% include &lsquo;template_name&rsquo; without context %}, 包含一个template, 但是不传递当前context</p>
<p align="left" style="margin-left:8.5pt;">17 Expressions:</p>
<p align="left" style="margin-left:17pt;">17.1 &ldquo;string&rdquo;引号中间的就是字符串</p>
<p align="left" style="margin-left:17pt;">17.2 42 / 42.23: 直接用数值表示float, int</p>
<p align="left" style="margin-left:17pt;">17.3 [1, 2, 3, 4]: 列表</p>
<p align="left" style="margin-left:17pt;">17.4 (1, 2, 3, 4): 元组</p>
<p align="left" style="margin-left:17pt;">17.5 {&lsquo;one&rsquo;: 1, &lsquo;two&rsquo;: 2} 字典</p>
<p align="left" style="margin-left:17pt;">17.6 true/false</p>
<p align="left" style="margin-left:8.5pt;">18 +, -, *, /, **, //, %等数学运算符都支持.</p>
<p align="left" style="margin-left:8.5pt;">逻辑运算符and, or, not也同样支持</p>
<p align="left" style="margin-left:8.5pt;">其他操作</p>
<p align="left" style="margin-left:17pt;">20.1 in 判断元素是否在集合中</p>
<p align="left" style="margin-left:17pt;">20.2 | 管道操作符, 默认使用Apply调用一个方法</p>
<p align="left" style="margin-left:17pt;">20.3 ~&nbsp; 字符串连接</p>
<p align="left" style="margin-left:17pt;">20.4 ( )&nbsp; 调用可调用对象</p>
<p align="left" style="margin-left:17pt;">20.5 . 和 [ ]获取属性</p>
<p align="left" style="margin-left:8.5pt;">三元操作: value1 if expression else value2支持</p>
<p align="left" style="margin-left:8.5pt;">内建filter: (对于内建filter的别名, 可以在jinja2的filters.py文件中查找)</p>
<p align="left" style="margin-left:17pt;">22.1 abs(number)&nbsp; 返回一个值的绝对值</p>
<p align="left" style="margin-left:17pt;">22.2 batch(value, lincount, fill_with = None): 接受的value是一个序列对象, linecount表明个数, 最后生成一个列表, 列表个数为linecount, 如果提供的value长度小于linecount, 不足的使用fill_with填充</p>
<p align="left" style="margin-left:17pt;">22.3 capitalize(string): 接受一个字符串, 将其转换为首字母大写, 其他字母小写的形式返回</p>
<p align="left" style="margin-left:17pt;">22.4 center(value, width = 80): 接受一个字符串, 将其至于80的长度中居中, 不足的字符使用空格填充</p>
<p align="left" style="margin-left:17pt;">22.5 default(value, default_value = u&rdquo;&rdquo;, boolean = False): 返回value指定的变量的值, 如果value是Undefined那么返回default_value指定的值, boolean意义未知</p>
<p align="left" style="margin-left:17pt;">22.6 dictsort(value, case_sensitive = False, by = &lsquo;key&rsquo;): value为要遍历的字典, case_sensitive指示是否立即加载, 设置为False表示延时加载, by表示以什么排序, 可以通过设置by = &lsquo;value&rsquo;来以值排序.</p>
<p align="left" style="margin-left:17pt;">22.7 escape(string): 返回一个转码的安全HTML</p>
<p align="left" style="margin-left:17pt;">22.8 filesizeformat(value): 接受一个数值, 返回人易读的文件大小表示.</p>
<p align="left" style="margin-left:17pt;">22.9 first(sequence): 返回序列的第一个元素</p>
<p align="left" style="margin-left:17pt;">22.10 float(value, default = 0.0): 将接受到的value转换成float类型, 如果转换失败返回指定的default值</p>
<p align="left" style="margin-left:17pt;">22.11 forceescape(value): 强制进行HTML转码, 也就是说不检查要转码的字符串是否是标记为安全的,这样可能会发生二次转码</p>
<p align="left" style="margin-left:17pt;">22.12 format(value, *attribute): 类似于字符串格式化&rsquo;%d&nbsp;&nbsp;&nbsp;&nbsp; %s&rsquo;这样的功能value是格式定义, attribute不定参数接受占位符代表的值.</p>
<p align="left" style="margin-left:17pt;">22.13 groupby(value, attribute): 按照指定的共有属性将集合进行分组, 返回元组组成的列表, 元组中第一个元素是用来分组的属性的值, 第二个元素是分组得到的所有原集合元素的列表.</p>
<p align="left" style="margin-left:17pt;">22.14 indent(string, width = 4, indentfirst = False): 将接受到的string, 每行缩进width指定的字符数, indentfirst用来指定首行是否缩进.</p>
<p align="left" style="margin-left:17pt;">22.15 int(value, default = 0): 将接受到的value转换成int型, 如果转换失败, 返回default指定的值</p>
<p align="left" style="margin-left:17pt;">22.16 join(value, d = u&rdquo;&rdquo;): 接受一个序列类型的对象, 向序列中进行插空d指定的字符串返回一个字符串</p>
<p align="left" style="margin-left:17pt;">22.17 last(seq): 返回指定序列的最后一个元素</p>
<p align="left" style="margin-left:17pt;">22.18 length(obj): 返回序列或者字典的项数</p>
<p align="left" style="margin-left:17pt;">22.19 list(value): 将接受到的value转换成一个list</p>
<p align="left" style="margin-left:17pt;">22.20 lower(string): 将接受到的字符串转换成小写形式.</p>
<p align="left" style="margin-left:17pt;">22.21 pprint(value, verbose = False): 漂亮的打印一个变量的值, 多用于调试, verbose表示是否显示冗长的信息</p>
<p align="left" style="margin-left:17pt;">22.22 random(seq): 接受一个序列对象, 随机返回其中的一个元素</p>
<p align="left" style="margin-left:17pt;">22.23 replace(string, old, new, count = None): 接受一个字符串, 将其中的old表示的子串替换成new指定的子串, 从左到右替换count次, 如果count不指定, 则替换一次</p>
<p align="left" style="margin-left:17pt;">22.24 reverse(value): 接受一个可迭代对象, 返回逆序的迭代器</p>
<p align="left" style="margin-left:17pt;">22.25 round(value, precision = 0, method = &lsquo;common&rsquo;): 舍去运算, 接受一个值, precision表示精度(小数点后保留几位), method可以取值common | ceil | floor, 分别表示四舍五入 | 进位 | 舍去</p>
<p align="left" style="margin-left:17pt;">22.26 safe(value): 标记传入的value值是安全的, 使用escape转码时不会发生二次转码</p>
<p align="left" style="margin-left:17pt;">22.27 slice(value, slices, fill_width = None): 切片, 接受一个可迭代对象, 返回slices指定的前n个元素, 不足n个使用fill_width指定的对象进行填充</p>
<p align="left" style="margin-left:17pt;">22.28 sort(value, reverse = False): 接受一个序列对象, 进行排序, reverse指定是否逆序</p>
<p align="left" style="margin-left:17pt;">22.29 string(obj): 接受一个对象, 转换成一个string字符串</p>
<p align="left" style="margin-left:17pt;">22.30 striptags(values): 接受一个字符串, 剥离SGML/XML标签, 并且将多个空白字符转换成单空格</p>
<p align="left" style="margin-left:17pt;">22.31 sum(sequence, start = 0): 接受一个序列对象, 返回序列对象的元素和start的总和, 如果指定的序列对象是空的, 就返回start指定的值</p>
<p align="left" style="margin-left:17pt;">22.32 title(string): 将接受到的字符串转换成标题模式, 即每个单词的首字母大写</p>
<p align="left" style="margin-left:17pt;">22.33 trim(value): 去掉字符串开始和末尾多余的空白字符</p>
<p align="left" style="margin-left:17pt;">22.34 truncate(string, length = 255, killwords = False, end = &ldquo;&hellip;&rdquo;): 切断接受到的字符串, 截取前length个字符, 如果字符串比length长, 切断后追加end指定的字符串, 如果killwords = True可以返回, 如果killwords = False不会有任何输出, 不明白.</p>
<p align="left" style="margin-left:17pt;">22.35 upper(string) 把接受到的字符串转成大写</p>
<p align="left" style="margin-left:17pt;">22.36 urlize(value, trim_url_limit = None, nofollow = False): 接受一个url, 转换成一个&lt;a&gt;标签表示的link, 这个link的href为传入的url, innerText是url截取前trim_url_limit个字符, nofollow设置为true时, 会为这个link加入一个属性 rel=&rsquo;nofollow&rsquo;</p>
<p align="left" style="margin-left:17pt;">22.37 wordcount(string): 计算string中的单词数</p>
<p align="left" style="margin-left:17pt;">22.38 wordwrap(string, width = 79, break_long_words = True): 返回经过包装的width指定宽度的字符, 也就是说每读取width个字符就会换行. , break_long_words表明在获取到width个字符之后, 如果一个单词还没有结束, 是否截断单词, False将不会截断</p>
<p align="left" style="margin-left:17pt;">22.39 xmlattr(d, autospace = True): 通过接受一个字典, 创建一个SGML/XML属性列表, 例如:</p>
<p align="left">&lt;ul {{ {&lsquo;class&rsquo; = &lsquo;my_list&rsquo;, &lsquo;missing&rsquo;: none, &lsquo;id&rsquo;: &lsquo;list&rsquo;} | xmlattr }} /&gt;</p>
<p align="left">可以得到输出</p>
<p align="left">&lt;ul class=&rsquo;my_list&rsquo; id=&rsquo;list&rsquo; /&gt;</p>
<p align="left">字典中指定的值为none的, 将不会被解析成标签属性.</p>
<p align="left" style="margin-left:8.5pt;">内建测试:</p>
<p align="left" style="margin-left:17pt;">23.1 callable(object): 测试一个对象是否是可调用对象</p>
<p align="left" style="margin-left:17pt;">23.2 defined(value): 测试传入的对象是否已经定义了</p>
<p align="left" style="margin-left:17pt;">23.3 divisibleby(value, num)测试传入的数值是否可以被num整除</p>
<p align="left" style="margin-left:17pt;">23.4 escaped(value): 检查传入的对象是否被转码了</p>
<p align="left" style="margin-left:17pt;">23.5 even(value): 如果传入的对象是even的返回True,&nbsp; 不懂even是什么样的对象</p>
<p align="left" style="margin-left:17pt;">23.6 iterable(value): 检查对象是否是可迭代的</p>
<p align="left" style="margin-left:17pt;">23.7 lower(value): 检查传入的字符串是否都是小写</p>
<p align="left" style="margin-left:17pt;">23.8 none(value): 检查对象是否是空对象None</p>
<p align="left" style="margin-left:17pt;">23.9 number(value): 检查对象是否是一个数字</p>
<p align="left" style="margin-left:17pt;">23.10 odd(value): 检查传入的数字是否是奇数</p>
<p align="left" style="margin-left:17pt;">23.11 sameas(value, other): 检查传入的对象和other指定的对象是否在内存中的同一块地址(同一个对象)</p>
<p align="left" style="margin-left:17pt;">23.12 sequence(value): 检查对象是否是序列, 序列同样是可迭代对象</p>
<p align="left" style="margin-left:17pt;">23.13 string(value): 检查对象是否是string</p>
<p align="left" style="margin-left:17pt;">23.14 undefined(value): 检查一个对象是否未定义</p>
<p align="left" style="margin-left:17pt;">23.15 upper(value): 检查一个字符串是否全部大写</p>
<p align="left" style="margin-left:8.5pt;">全局函数:</p>
<p align="left" style="margin-left:17pt;">24.1 range([start, ]stop[, step]):</p>
<p align="left">{% for i in range(10) %}</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {{ i }}</p>
<p align="left">{% endfor %}</p>
<p align="left" style="margin-left:17pt;">24.2 lipsum(n = 5, html = True, min = 20, max = 100): 不知道用途</p>
<p align="left" style="margin-left:17pt;">24.3 dict(**items)&nbsp; 根据传入的关键字参数构造一个字典对象.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/786/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>flask-使用全局变量</title>
		<link>http://www.linux-field.com/archives/783</link>
		<comments>http://www.linux-field.com/archives/783#comments</comments>
		<pubDate>Mon, 26 Dec 2011 05:15:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[flask]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=783</guid>
		<description><![CDATA[在开发flask 中需要使用全局变量，方法如下： 1， 启动文件设置： #!/usr/bin/env python # -*- coding: UTF-8 -*- import os,sys # from flask import Flask, request, session, g, redirect, url_for, \ abort, render_template, flash, current_app @app.before_request def before_request(): url_arr = str(request.path).lower().strip().split(&#34;/&#34;) #print str(request.path) #print url_arr #print &#34;----------------------------------------&#34; # app.Module=url_arr[1] app.Controller=url_arr[2] app.Action=url_arr[3] 在apps/core/controllers/authController.py文件中使用该变量： &#160; # -*- coding: UTF-8 -*- from flask import Blueprint, [...]]]></description>
			<content:encoded><![CDATA[<p>在开发flask 中需要使用全局变量，方法如下：</p>
<p>1， 启动文件设置：</p>
<pre class="brush:python;">#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os,sys
#
from flask import Flask, request, session, g, redirect, url_for, \
     abort, render_template, flash, current_app
@app.before_request
def before_request():
    url_arr = str(request.path).lower().strip().split(&quot;/&quot;)
    #print str(request.path)
    #print url_arr
    #print &quot;----------------------------------------&quot;
    #
    app.Module=url_arr[1]
    app.Controller=url_arr[2]
    app.Action=url_arr[3]
</pre>
<p>在apps/core/controllers/authController.py文件中使用该变量：<br />
	&nbsp;</p>
<pre class="brush:python;"># -*- coding: UTF-8 -*-
from flask import Blueprint, render_template, request, current_app
@core_auth.route(&quot;/test&quot;)
@core_auth.route(&quot;/core/auth/test&quot;)
def test():
    #print dir(current_app)
    return current_app.Action</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/783/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nginx+uwsgi+flask in Gentoo</title>
		<link>http://www.linux-field.com/archives/775</link>
		<comments>http://www.linux-field.com/archives/775#comments</comments>
		<pubDate>Thu, 15 Dec 2011 10:03:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[系统管理]]></category>

		<guid isPermaLink="false">http://www.linux-field.com/?p=775</guid>
		<description><![CDATA[由于需要在Gentoo下面开发基于Python的管理系统，而管理系统需要使用到root权限，所以直接使用apache来启用http是不现实的。 因为默认的apache不能使用root来运行。我就想到了nginx这个小而厉害的&#34;瑞士军刀&#34;。下面开始我们这此开发环境的配置之旅. 1, 安装nginx(注意打开uwsgi支持，我去除了默认的geoip的支持): 修改/etc/make.conf: NGINX_MODULES_HTTP=&#34;access auth_basic autoindex browser charset empty_gif fastcgi gzip limit_req limit_zone map memcached proxy referer rewrite scgi split_clients ssi upstream_ip_hash userid uwsgi&#34; 执行安装: # emerge nginx 2, 安装uwsgi 修改/etc/portage/package.keywords 添加下面行: &#62;=www-servers/uwsgi-0.9.8 ~x86 执行安装: # emerge uwsgi 3,&#160; 配置nginx. 编辑/etc/nginx/nginx.conf #user nginx nginx; user root root; worker_processes 1; error_log /var/log/nginx/error_log info; events [...]]]></description>
			<content:encoded><![CDATA[<p>由于需要在Gentoo下面开发基于Python的管理系统，而管理系统需要使用到root权限，所以直接使用apache来启用http是不现实的。</p>
<p>因为默认的apache不能使用root来运行。我就想到了nginx这个小而厉害的&quot;瑞士军刀&quot;。下面开始我们这此开发环境的配置之旅.</p>
<p><span id="more-775"></span></p>
<p>1, 安装nginx(注意打开uwsgi支持，我去除了默认的geoip的支持):</p>
<p>修改/etc/make.conf:</p>
<pre class="brush:plain;">NGINX_MODULES_HTTP=&quot;access auth_basic autoindex browser charset empty_gif fastcgi gzip limit_req limit_zone map memcached proxy referer rewrite scgi split_clients ssi upstream_ip_hash userid uwsgi&quot;</pre>
<p>执行安装:</p>
<pre class="brush:bash;"># emerge nginx</pre>
<p>2, 安装uwsgi</p>
<p>修改/etc/portage/package.keywords 添加下面行:</p>
<pre class="brush:plain;">&gt;=www-servers/uwsgi-0.9.8 ~x86</pre>
<p>执行安装:</p>
<pre class="brush:bash;"># emerge uwsgi</pre>
<p>3,&nbsp; 配置nginx.</p>
<p>编辑/etc/nginx/nginx.conf</p>
<pre class="brush:plain;">#user nginx nginx;
user root root;
worker_processes 1;

error_log /var/log/nginx/error_log info;

events {
	worker_connections 1024;
	use epoll;
}

http {
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	log_format main
		&#39;$remote_addr - $remote_user [$time_local] &#39;
		&#39;&quot;$request&quot; $status $bytes_sent &#39;
		&#39;&quot;$http_referer&quot; &quot;$http_user_agent&quot; &#39;
		&#39;&quot;$gzip_ratio&quot;&#39;;

	client_header_timeout 10m;
	client_body_timeout 10m;
	send_timeout 10m;

	connection_pool_size 256;
	client_header_buffer_size 1k;
	large_client_header_buffers 4 2k;
	request_pool_size 4k;

	gzip on;
	gzip_min_length 1100;
	gzip_buffers 4 8k;
	gzip_types text/plain;

	output_buffers 1 32k;
	postpone_output 1460;

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;

	keepalive_timeout 75 20;

	ignore_invalid_headers on;

	index index.html;

	server {
        listen 80;
		server_name _;

		access_log /var/log/nginx/access_log main;
		error_log /var/log/nginx/error_log info;

		#root /var/www/localhost/htdocs;
        location / {
            include /etc/nginx/uwsgi_params;
            uwsgi_pass unix:/var/run/adminhttp.sock;
        }
	}

	# SSL example
	server {
		listen 443;
		server_name _;

		ssl on;
		ssl_certificate /etc/ssl/nginx/nginx.pem;
		ssl_certificate_key /etc/ssl/nginx/nginx.key;

		access_log /var/log/nginx/ssl_access_log main;
		error_log /var/log/nginx/ssl_error_log info;

        ssl_session_timeout  5m;

        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
        ssl_prefer_server_ciphers   on;

	#	root /var/www/localhost/htdocs;
        location / {
            include /etc/nginx/uwsgi_params;
            uwsgi_pass unix:/var/run/adminhttp.sock;
        }
	}
}</pre>
<p>启动 nginx</p>
<p>/etc/init.d/nginx start</p>
<p>4, 建立flask项目:</p>
<p>hello.py</p>
<pre class="brush:python;">from flask import Flask
app = Flask(__name__)

@app.route(&#39;/&#39;)
def hello_world():
    return &quot;Hello World! &quot;

if __name__ == &#39;__main__&#39;:
    #app.run()
    app.debug = True
    app.run(host=&#39;0.0.0.0&#39;)</pre>
<p>5, 运行uwsgi</p>
<pre class="brush:bash;"># uwsgi -s /var/run/adminhttp.sock --module hello --callable app</pre>
<p>6, 测试 http://localhost or https://localhost</p>
<p>7, uwsgi使用xml配置模式的方式</p>
<p>建立配置文件: flask.xml</p>
<pre class="brush:xml;">&lt;uwsgi&gt;
    &lt;pythonpath&gt;/opt/adminhttp/python&lt;/pythonpath&gt;
    &lt;module&gt;hello&lt;/module&gt;
    &lt;callable&gt;app&lt;/callable&gt;
    &lt;processes&gt;3&lt;/processes&gt;
    &lt;socket&gt;/var/run/adminhttp.sock&lt;/socket&gt;
    &lt;master/&gt;
&lt;/uwsgi&gt;</pre>
<p>将uwsgi放在后台运行:</p>
<pre class="brush:bash;"># uwsgi -x flask.xml -d /var/log/uwsgi.log</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linux-field.com/archives/775/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

