同一个域名,想绑定多个Web应用,简单的方式就是通过反向代理的方式实现。
比如我有一个域名www.xxx.com,并已映射到我本地服务器,同时又有两个应用blog和photo,已部署启动在后台服务器上,blog部署在本地3000端口(http://127.0.0.1:3000/blog),Photo部署在本地3001端口(http://127.0.0.1:3001/photo)。希望通过www.xxx.com/blog访问博客应用,通过www.xxx.com/photo访问相册应用,这时就可以用上反向代理的功能!
对于
Apache来说,反向代理的命令是ProxyPass。找到你的Apache配置文件(我的在/etc/apache2/sites-enable目录下),在VirtualHost节点里加上类似如下的语句:
ProxyPass /blog http://127.0.0.1:3000/blog ProxyPass /photo http://127.0.0.1:3001/photo |
对于Nginx来说,反向代理的命令是proxy_pass。找到你的Nginx配置文件(我的是/opt/nginx/conf/nginx.conf文件),在
server节点里加上类似如下的语句:
location ^~ /blog { proxy_pass http://127.0.0.1:3000/blog; } location ^~ /photo { proxy_pass http://127.0.0.1:3001/photo; } |
像如上配置好之后,服务器就会将带有/blog后缀的URL(如www.xxx.com/blog)反向代理到http://127.0.0.1:3000/blog应用上,将带有/photo后缀的URL(如www.xxx.com/photo)反向代理到http://127.0.0.1:3001/photo应用上,简单的实现一个域名绑定多个Web应用。
反向代理功能强大,它可以将远程服务器映射到本地服务器的URL空间,而这里是对反向代理的一个简单应用,也是初次试用,如有理解或使用不正确之处,欢迎批评指出!^_^
总的来说,通过反向代理,实现自定义二级目录在统一域名下访问不同的Web应用。好处是能够统一访问管理,还能共用OpenID等公用资源。但也需要做一些额外的操作,如对你的应用进行统一的route设置,使得应用的URL都带一个统一后缀,并需要解决静态资源文件加载的问题,否则会出现样式和图片的丢失!
做数据同步时遇到一个问题,在下载数据时需要批量的向sqlite插入数据,虽然数据不算多,但是实际
测试中每插入一条数据需要将近50ms的时间,这意味着1000条数据就需要花费50s左右的时间,对于用户来说,体验太差了,必须要优化。
在sqlite插入数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。明白了这个,解决方案就有了,在批量插入数据的时候,只开启一个事务,这样只会进行一次磁盘操作,代码如下:
db.beginTransaction(); try { for (...) { db.execSQL("...", new Object[]{}); } db.setTransactionSuccessful(); } catch (Exception e) { } finally { db.endTransaction(); } |
使用事务后性能有明显的提升,以批量操作100条为例,由原来的5s优化成了现在的1s
1、tar 命令最初的设计目的是将文件备份到磁带上(tape archive),因而得名tar;
tar 程序打包的数据,并没有压缩过;
tar是打包程序,这个命令可以在打包的同时调用gzip或者bzip2进行压缩.
一般以.tar.gz结尾的是用gzip压缩的,而.tar.bz2结尾的是用bzip2压缩的.
tar 对文件目录进行打包备份,生成一个.tar文档
gzip bzip2 都是压缩程序,可以和tar 结合使用:
在tar命令中可以直接调用gzip bzip2
#tar tvzf /tmp/my_home_directory.tar.gz //z 表示 gzip
#tar tvjf /tmp/my_home_directory.tar.bz2 //j 表示bzip2
使用 gzip要比bzip2快,但是bzip2会获得比 gzip高的压缩率
2、gzip(gzip,gunzip,zcat-compress or expand files)。
是GNUzip的缩写,它是一个GNU(全称是GNU's Not
Unix)自由软件的文件压缩程序;
#tar tvzf /tmp/my_home_directory.tar.gz //z 表示 gzip,通常选项f都放到最后面
3、bzip2(bzip2,bunzip2-a block-sorting file compressor,)
是一个基于Burrows-Wheeler 变换的无损压缩软件,压缩效果比传统的LZ77/LZ78压缩算法来得好;
#tar tvjf /tmp/my_home_directory.tar.bz2 //j 表示bzip2,通常选项f都放到最后面
4、 *.Z---compress程序压缩的档案;
compress是一个相当古老的 unix 档案压缩指令,压缩后的档案会加上一个 .Z 延伸档名以区别未压缩的档
案,压缩后的档案可以以 uncompress 解压。 若要将数个档案压成一个压缩档,必须先将档案 tar 起来再压缩。
由于 gzip 可以产生更理想的压缩比例,一般人多已改用 gzip 为档案压缩工具;
5、 *.tar.gz------ tar 程序打包的档案,其中并且经过 gzip的压缩
6、 *.tar.bz2------tar 程序打包癿档案,其中并且经过 bzip2 癿压缩
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
若说 gzip 是为了取代 compress 并提供更好的压缩比而成立的,那么 bzip2 则是为了取代 gzip 并提
供更佳的压缩比而来的。 bzip2 这玩意的压缩比竟然比 gzip 还要好~至与bzip2 的用法几乎与 gzip 相同!
那么如何通过对象对数据库进行各种对象的ddl与dml操作呢?
数据库对象操作的〈database-object ../〉+ SchemaExport
1、hibernate.cfg.xml
<?xml version="1.0" encoding="GBK"?> <!-- 指定Hibernate配置文件的DTD信息 --> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <!-- hibernate- configuration是连接配置文件的根元素 --> <hibernate-configuration> <session-factory> ...... <!-- 根据需要自动创建数据库:如果创建表,这里必须为create --> <property name="hbm2ddl.auto">create</property> <!-- 显示Hibernate持久化操作所生成的 SQL --> <property name="show_sql">true</property> <!-- 将SQL脚本进行格式化后再输出 --> <property name="hibernate.format_sql">true</property> <!-- 罗列所有的映射文件 --> <mapping resource="....../lovejk.hbm.xml"/> </session-factory> lt;/hibernate-configuration> |
2、lovejk.hbm.xml
<?xml version="1.0" encoding="gb2312"?> <!-- 指定Hiberante3映射文件的DTD信息 --> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- hibernate-mapping是映射文件的根元素 --> <hibernate-mapping> <!-- 使用data-object元素定义数据库对象 --> <database-object> <!-- 定义创建数据库对象的语句 --> <create>create table testjk(name varchar(256));</create> <!-- 让drop元素为空,不删除任何对象 --> <drop></drop> <dialect-scope name="org.hibernate.dialect.MySQLDialect"/> <dialect-scope name="org.hibernate.dialect.MySQLInnoDBDialect"/> </database-object> </hibernate-mapping> |
3、执行
public static void main(String[] args) throws Exception { //实例化Configuration,这行代码默认加载hibernate.cfg.xml文件 Configuration conf = new Configuration().configure(); //以Configuration创建SessionFactory SessionFactory sf = conf.buildSessionFactory(); // //创建SchemaExport对象 SchemaExport se = new SchemaExport(conf); // //设置输出格式良好的SQL脚本 se.setFormat(true); // //设置保存SQL脚本的文件名 se.setOutputFile("d:\\1.sql"); // //输出SQL脚本,并执行SQL脚本 se.create(true, true); sf.close(); } |
总结:简单粗暴!
在远程拷贝的时候,需要配置scp的 无密码 复制文件和目录。在编写
Shell脚本的时候非常有用,你不希望shell脚本在执行过程中因为要检验密码被打断而报权限错误吧。
整个过程如下:
本地服务器:A
远程服务器:B
1.在 A 上运行 ssh-keygen -t rsa 在/home/openpf/.ssh下生成id_rsa 和 id_rsa.pub 两个文件,然后在/home/openpf/.ssh下复制备份一份id_rsa.pub 命名为 id_rsa.pub.A,以便拷贝到服务器B,如图所示:
2. 在 B 上也同样运行 ssh-keygen -t rsa
3. 在 B 的/home/openpf/.ssh下创建authorized_keys文件,把A 中 id_rsa.pub.A 文件传到 B服务器/home/openpf/.ssh 下,
通过 cat 命令 把id_rsa.pub.A 追写到 authorized_keys 文件中,命令如下:
scp ./id_rsa.pub.A B的IP:/home/openpf/.ssh
cat id_rsa.pub.A >> authorized_keys
4.配置完毕
scp ./id_rsa.pub.A 10.16.133.200:/home/openpf/.ssh 无需输入密码执行成功
命令:
复制文件:
1.将本地文件拷贝到远程
scp 文件名 用户名@计算机IP:远程路径
2.从远程将文件拷回本地
scp 用户名@计算机IP:文件名 本地路径
复制目录:
1.将本地目录拷贝到远程
scp -r 目录名 用户名@计算机IP:远程路径
2.从远程将目录拷回本地
scp -r 用户名@计算机IP:目录名本地路径
File类
File类是 IO 包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操纵文件
File f = new File("d:/test/1.txt");
常用方法见 API
delete 方法删除由File对象的路径所表示 对磁盘文件或目录。如果删除的对象是目录,该目录中的内容必须为空。
节点流
我们将IO流类分为两个大类,节点流类和过滤流类(也叫处理流类)。
1. 程序用于直接操作目标设备所对应的类叫节点流类
2. 程序也可以通过一个间接流类去调用结点流类,以达到更加灵活方便地读写各种类型的数据,这个间接流类就是过滤流类(也叫处理流类)
InputStream 与 OutputStream (抽象类[字节流])
程序可以从中连续 读取字节 的对象叫输入流,用InputStream类完成
int read() // 返回 -1 表示遇到流的末尾,结束 int read(byte[] b) //读入b.length个直接放入到b中并返回实际读入的字节数 int read(byte[] b,int off,int len) void close() //关闭,通知系统释放与这个流相关的资源 |
程序能向其中连续 写入字节 的对象叫输出流,用OutputStream类完成
void write(int b) //将一个直接写到输入流 void write(byte[] b) //将整个直接数组写到输出流中 void write(byte[] b,int off,int len) // void flush() //彻底完成输出并清空缓冲区 void close() //关闭输出流 |
这里的输入输出是针对程序而言的,而非文件。
输入: 程序读取 输出:程序写出
将A文件的内容写入文件B中:
我们应该创建一个输入类来完成对A文件的操作,再创建一个输出类来完成对B文件的操作。
FileInputStream 与 FileOutputStream
这两个源节点用来操作磁盘文件,在创建一个FileInputStream对象时通过构造函数指定文件的路径和名字,当然这个文件应当是存在的和可读的。在创建一个FileOutputStream对象时指定文件如果存在将要被覆盖。
只能用来读取字节或字节数组!!!因此字符串需要使用getBytes()方法转为字节数组。
注:unicode是双字节的,而ASCII是单字节的。
java中的字符默认使用unicode编码!
编程实现利用FileOutputStream类向文件写入一串字符,并用FileInputStream读出:
public class FileStreamDemo { public static void main(String[] args) { File f = new File("Hello.txt"); //输出到文件中 try { FileOutputStream out = new FileOutputStream(f); byte buf[] = "hello,well".getBytes();//转成字节输出 out.write(buf); out.close(); } catch (Exception e) { e.printStackTrace(); } //从文件中读出显示到屏幕上 try { FileInputStream in = new FileInputStream(f); byte[] buff = new byte[1024]; int len = in.read(buff); System.out.println(new String(buff,0,len)); } catch (Exception e) { e.printStackTrace(); } } } |
为什么要 close ?
Java垃圾回收器只能管理程序中的类的实例对象,没法去管理系统产生的资源,所以程序要调用 close 方法,去通知系统去释放其自身产生的资源。
这两个类都只提供了对字节或字节数组进行读出的方法。对于字符串的读写,我们还需要进行额外的转换。
Reader和Writer
1. 抽象类,用于直接读取字符串文本
2. Java为字符文本(直接读取字符串)的输入输出专门提供的一套单独的类,其在处理字符串时简化了我们的编程。
对上面的程序进行如下的修改:—— 使用FileWriter 和 FileReader类来实现直接对字符串的读取:
public class FileStreamDemo2 { public static void main(String[] args) { File f = new File("Hello.txt"); try { FileWriter out = new FileWriter(f); out.write("hello world,hahaha"); out.close(); } catch (Exception e) { e.printStackTrace(); } try { FileReader in = new FileReader(f); char[] buf = new char[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); } catch (Exception e) { e.printStackTrace(); } } } |
FileReader的真正优势要结合包装流类才能体现出来!!
PipedInputStream 与 PipedOutputStream
一个PipeInputStream对象必须和一个PipedOutputStream对象进行连接而产生一个通信管道。
这两个类主要来完成线程之间的通信。 --- p 266
一个线程的PipedInputStream对象能够从另一个线程的PipedOutputStream对象中读取数据。
void connect(PipedOutputStream src)使此管道输入流连接到管道输出流 src。
JDK还提供了PipedWriter和PipedReader这两个类来用于字符串文本的管道通信。
使用管道流,可以实现各个程序模块之间的松耦合通信。
ByteArrayInputStream 与 ByteArrayOutputStream
1. 使用字节数组作为数据源
2. 作用:使用IO流的方式来完成对字节数组内容的读写
IO程序代码的复用
由于没有编码为 -1 的字符,所以OS使用 -1 作为硬盘上的每个文件的结尾标记
文本文件与二进制文件:
1. 如果一个文件专用于存储文本字符的数据,没有包含字符之外的其他数据,我们称之为文本文件
2. 除此之外的文件就是二进制文件
为了支持标准输入输出设备,Java定义了两个特殊的流对象:System.in 和 System.out
System.in 对应键盘,是InPutStream类型的,从键盘读取数据
System.out 对应屏幕,是PrintStream类型的
Scanner类
该类不属于IO类,而属于util类
它是一个可以用正则表达式来解析基本类型和字符串的简单文本扫描器
Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的next 方法将得到的标记转换为不同类型的值。
例如从键盘读取一行输入:
<span style="font-size:14px;"> Scanner cin = new Scanner(System.in);
String name = cin.nextLine();</span>
过滤流与包装流:
--- 即中间类,为哦我们往IO设备中写入各种类型的数据提供了帮助
DataOutputStream
writeBoolean()
writeShort()
writeChar()
writeInt()
......
程序 ---> 包装流类 ----> 节点流类 ---> 目标
输入包装类 -- see p273 的例子
输出包装类 --
包装流的使用:
DataOutputStream(OutputStream out) //将OutputStream包装为DataOutputStream
BufferedInputStream 与 BufferOutputStream
---缓冲流:对IO进行缓冲
利用缓冲流来进行改善性能
构造方法:
BufferedInputStream(InputStream in)
创建一个带有32直接缓冲区的缓冲流
BufferedInputStream(InputStream in, int size)
创建具有指定缓冲区大小的缓冲区
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size)
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
DataInputStream 与 DataOutputStream
———— 提供了可读写各种基本数据类型数据的各种方法
DataOutputStream提供了3种写入字符串的方法:
1. writeBytes(String s)
2. writeChars(String s)
3. writeUTF(Strng s)
PrintStream类
提供了一系列的print和println方法,可以实现将基本数据类型的格式化成字符串输出。
构造函数:
PrintStream(OutputStream out)
PrintStream(OutputStream out, boolean autoflush)
PrintStream(OutputStream out, boolean autoflush, String encoding)
autoflush控制java在遇到换行符(\n)时是否自动清空缓冲区
Java的PrintStream对象具有多个重载的Print和Println方法
在Windows的文本换行是 “\r\n” 而Linux下的文本换行是“\n”
PrintWriter的println方法能根据不同的操作系统生成相应的换行符
PrintWriter类 -- 与PrintStream相对应
该类若设置autoFlush, 其会在使用了println方法后使用自动清空缓冲区
ObjectInputStream 与 ObjectOutputStream
用于存储和读取对象的输入输出流类。
前言:
最近一直在分析hadoop的RPC机制。在hadoop中,DataNode和NameNode之间的控制信息的交流是通过RPC机制完成的,采用的是动态代理和
java NIO的方式。DataNode端是通过获得NameNode的代理,通过该代理和NameNode进行通信的,为了更好的分析hadoop的RPC机制我想先分析一下动态代理是怎么实现。下面就是动态代理的最最简单的代码实现,我们一起来看看吧。
代码如下:
package cn.xiaolu; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 动态代理类使用到了一个接口InvocationHandler和一个代理类Proxy ,这两个类配合使用实现了动态代理的功能。 * 那么什么是动态代理呢? * 我们平常说的代理类是指: 给每个具体类写一个代理类,以后要使用某个具体类时,只要创建它的代理类的对象,然后调用代理类的方法就可以了。 * 可是如果现在有许多的具体类,那就需要有许多的代理类才可以,这样很显然不合适。所以动态代理就应运而生了,我们只要写一个类实现 * InvocationHandler 并实现它的invoke方法,然后再用Proxy的工厂方法newProxyInstance()创建一个代理对象,这个对象同样可以实现对具体类的代理功能。 * 而且想代理哪个具体类,只要给Handler(以下代码中的Invoker)的构造器传入这个具体对象的实例就可以了。感觉是不是自己为该具体类造了一个代理类呢?呵呵~ */ //接口类 interface AbstractClass { public void show(); } // 具体类A class ClassA implements AbstractClass { @Override public void show() { // TODO Auto-generated method stub System.out.println("我是A类!"); } } // 具体类B class ClassB implements AbstractClass { @Override public void show() { // TODO Auto-generated method stub System.out.println("我是B类!"); } } //动态代理类,实现InvocationHandler接口 class Invoker implements InvocationHandler { AbstractClass ac; public Invoker(AbstractClass ac) { this.ac = ac; } @Override public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable { //调用之前可以做一些处理 method.invoke(ac, arg); //调用之后也可以做一些处理 return null; } } /** * @author 小路 */ class DynamicProxyTest { public static void main(String[] args) { //创建具体类ClassB的处理对象 Invoker invoker1=new Invoker(new ClassA()); //获得具体类ClassA的代理 AbstractClass ac1 = (AbstractClass) Proxy.newProxyInstance( AbstractClass.class.getClassLoader(), new Class[] { AbstractClass.class }, invoker1); //调用ClassA的show方法。 ac1.show(); //创建具体类ClassB的处理对象 Invoker invoker2=new Invoker(new ClassB()); //获得具体类ClassB的代理 AbstractClass ac2 = (AbstractClass) Proxy.newProxyInstance( AbstractClass.class.getClassLoader(), new Class[] { AbstractClass.class }, invoker2); //调用ClassB的show方法。 ac2.show(); } } |
程序运行后的结果如下:
我是A类!
我是B类!
TestNG是一个设计用来简化广泛
测试需求的 测试框架,旨在涵盖所有类型的测试,包括
单元测试、
功能测试、端到端集成测试等,而我们在基于TestNG搭建
自动化测试框架,编写
测试用例时,为保证测 试用例的稳定性,需要增加测试用例失败自动重跑功能,这便促成了Arrow的诞生。 Arrow是基于TestNG监听器扩展的插件,如果把TestNG比作一把强劲的弓,那么插件就是配合弓使用的箭,这也是Arrow命名的由来。
当前Arrow插件已开源,可通过以下地址访问:https://github.com/NetEase/arrow
一、Arrow功能介绍
1、 支持通过简单配置实现失败的测试用例自动重跑
2、 支持Html结果报告中展示测试用例运行次数
3、 支持自动解析源代码中的@author标签,在Html结果报告中展示(失败用例可以方便查找维护者)
4、 修复TestNG原生Html报告中锚点跳转不正确的
Bug 俗话说,眼见为实耳听为虚,下面就带大家看看实际效果图吧!
二、Arrow使用效果
使用Arrow插件运行基于TestNG的测试用例后会生成我们自定义的报告power-emailable-report.html,下图1显示 在测试用例中书写@author标签,使用arrow执行完用例后生成如图2的结果报告,报告中会自动读取authors信息以及running counts运行次数,通过authors信息方便自动获取到该用例的维护者,通过running counts方便知道当前用例是否失败重跑。
图1
图2
三、如何使用Arrow
使用Arrow无需修改原有的测试代码
1、 首先你需要有一套TestNG编写的测试用例
2、 测试工程中需要testng.jar(核心不能忘!),log4j.jar(用于日志的输出)以及我们提供的arrow.jar
3、 测试工程根目录下新建config.properties文件,同时配置如下参数
retrycount=1 #定义重跑次数,不是必填项, 默认值是0,即失败不重跑
sourcecodedir=src #定义源代码路径,不是必填项, 默认值是src
sourcecodeencoding=UTF-8 #定义源代码编码,不是必填项,默认值是utf-8
4、 在build.xml文件中加入监听器,配置如下,配置完成后通过ant运行TestNG测试用例后可以在生成的Html结果报告中查看效果
<target name="testng"> <mkdir dir="test-output" /> <testng outputDir="test-output" haltonfailure="false" listeners="com.netease.qa.testng.PowerEmailableReporter, com.netease.qa.testng.RetryListener, com.netease.qa.testng.TestResultListener"> <xmlfileset dir="." includes="testng.xml" /> </testng> </target> |
5、 如果您不习惯4的做法,可以在testng.xml中加入如下的监听器,配置完成后右键testng.xml文件运行测试用例即可
<listeners> <listener class-name="com.netease.qa.testng.TestResultListener" /> <listener class-name="com.netease.qa.testng.RetryListener" /> <listener class-name="com.netease.qa.testng.PowerEmailableReporter" /> </listeners> |
四、Arrow扩展-失败用例自动截图
由于截图功能在不同的测试框架上API会不同,所以当前Arrow中没有把这个功能集成进来,但是如果你需要该功能也可以很方便的进行扩展。
1、 在这里下载Arrow的源代码
2、 修改TestResultListener类,在onTestSkipped以及onTestFailure方法中加入如下代码
@Override public void onTestFailure(ITestResult tr) { super.onTestFailure(tr); saveScreenShot(tr); } @Override public void onTestSkipped(ITestResult tr) { super.onTestSkipped(tr); saveScreenShot(tr); } private void saveScreenShot(ITestResult tr) { SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); String mDateTime = formatter.format(new Date()); String fileName = mDateTime + "_" + tr.getName(); String filePath = ""; try { //这里可以调用不同框架的截图功能 File screenshot = ((TakesScreenshor)webdriver).getScreenshotas(OutputType.FILE); filePath = “screenshot/” + filename + “.jpg” File destFile = new File(filePath); FileUtils.copyFile(screenshot, destFile); } catch (Exception e) { filePath = fileName + " firefox tackScreentshot Failure:" + e.getMessage(); logger.error(filePath); } if (!"".equals(filePath)) { Reporter.setCurrentTestResult(tr); Reporter.log(filePath); //把截图写入到Html报告中方便查看 Reporter.log("<img src=\"../" + filePath + "\"/>"); } } |
3、修改完成后重新运行测试用例,即可实现失败自动截图,同时会把截图写入到Html结果报告中,方便定位问题,如图3。
图3
最后,欢迎大家使用以及共同改进Arrow,方便大家基于TestNG的测试工作。
1 网上下载JMeterPlugins-0.5.3【现在有更新的】 放到某目录下
2 运行JMeterPluginsCMD.bat
3 将JMeterPlugins.jar 复制到你的Jmeter安装路径下的lib下ext下面
4 运行Jmeter打开监视器的菜单,超多个监视器映入眼帘,cool~!
5 当然使用这些监视是有个前提的,运行你的
server agent下的start agent.bat 否则会报连接错误的~
还有另外一个不相干的知识点:新增JDBC request时,加入的sql语句,如果是delete语句,在选择类型的时候可以使用callable states或者update等等都得的。
最近在mac环境下玩tornado,发现明明
mysql安装成功的,但连mysql数据库一直报错。
NameError: global name ‘CONVERSIONS’ is not defined
网上搜了把,发现
python连mysql还得装mysql-python这个东东。
安装不是很顺利,发现不少问题。整理一下:
1. mysql必须是64位的
2. 安装mysql-python报错
EnvironmentError: mysql_config not found
查找本机的mysql_config路径
sudo find / -name mysql_config
a) 如果用mysql-python源文件来安装,>>下载MySQL-python-1.2.4.zip
修改setup_posix.py文件,在27行:
mysql_config.path = “mysql_config” 修改为:
mysql_config.path = “/usr/local/mysql-5.6.8-rc-osx10.7-x86_64/bin/mysql_config”
修改完成后保存,再执行
python setup.py build
python setup.py install
b) 如果用sudo easy_install mysql-python安装
修改环境变量:vim ~/.bash_profile
增加:export PATH=${PATH}:/usr/local/mysql-5.6.8-rc-osx10.7-x86_64/bin/
再执行sudo easy_install mysql-python
>>>import MySQLdb
import MySQLdb 时提示 Reason: image not found。
同样修改环境变量:
增加:export DYLD_LIBRARY_PATH=”$DYLD_LIBRARY_PATH:/usr/local/mysql/lib”
最后再次进入python
>>>MySQLdb.__version__
显示’1.2.4′
搞定收工