利用pil,cStringIO将图片暂存上传

很简单的代码,记录一下。
    import Image
    image = Image.open('a.jpg')
    import cStringIO
    buf = cStringIO.StringIO()
    image.save(buf, image.format,quality=75)
    data = buf.getvalue()
    a = u.writeFile('/this/logo.jpg',data,True)
应用在 使用django,用户上传图片后,将图片转存到别的服务器。但是转存需要对图片进行处理,但是quality设定的保存,不知道可不可以在不是image.save()的时候。写的这个是保存时放到内存,然后直接提交到图片服务器。
Read more...

erlang学习笔记--BIF,二进制数据,比特语法

1.BIF: BIF:(built-in function)内建函数,是erlang语言的组成部分。是erlang虚拟机中的基本操作。 tuple_to_list/1将元组转换为列表,time/0返回当前时间的时,分,秒。 1> tuple_to_list({12,cat,"ddd"}). [12,cat,"ddd"] 3> time(). {12,35,57} 2.二进制数据: 一种数据类型,用来实现原始数据的高速存储。节省内存,输入输出更加高效。书写打印时,二进制数据以一个整数或者字符序列的形式出现,两端分别用尖括号括起来。其中的整数,每一个都要在0-255之间,如果二进制数据是可以打印的字符串,shell将显示字符串形式,否则会显示一串整数。 @spec 描述函数的参数和返回类型。类型标注,不是erlang代码而是注释文档的一部分,shell中不能使用这些标注。erlang中的模块声明也是注释的一部分。 erlang通过BIF来构造二进制数据或者从中提取数据,或者通过比特语法来完成这一过程。 @spec list_tbo_inary(IoList) -> binary() @spec split_binary(Bin,Pos) -> {Bin1,Bin2} @spec term_to_binary(Term) -> Bin @spec binary_to_term(Bin) -> Term list_tbo_inary将IoList中所有东西转换为一个二进制数据。split_binary在pos位置将二进制数据分割成两个部分。下面两个是互逆。 4> Bin1 = <<1,2,3>>. <<1,2,3>> 5> Bin2 = <<4,5>>. <<4,5>> 6> Bin3 = <<6>>. <<6>> 7> list_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]). <<1,2,3,1,2,3,4,5,4,6>> 12> split_binary(<<1,2,3,1,2,3,4,5,4,6>>,4). {<<1,2,3,1>>,<<2,3,4,5,4,6>> 14> term_to_binary({11,'333a',use}). <<131,104,3,97,11,100,0,4,51,51,51,97,100,0,3,117,115,101>> 15> binary_to_term(<<131,104,3,97,11,100,0,4,51,51,51,97,100,0,3,117,115,101>>). {11,'333a',use} 返回二进制数据字节长度 16> size(<<1,2,3,4>>). 4 3.比特语法 比特语法:一种模式匹配语法,用于二进制数据中的比特进行封包和解包工作。 比特语法是模式匹配的一种扩展。编写底层代码时,常会需要对比特级别的二进制数据进行封包解包,会体现比特语法的便捷,比特语法针对协议编程而设计(erlang的看家本领 哇塞)。 16bit色彩的封包解包 19> Red = 2. 2 20> Green = 54. 54 21> Blue = 20. 20 22> Men = <<Red:5,Green:6,Blue:5>>. <<22,212>> 23> Mem = <<Red:5,Green:5,Blue:5>>. <<21,84:7>> 24> <<R1:5,G1:6,B1:5>> = Men. <<22,212>> 25> R1. 2 27> G1. 54 28> B1. 20 可以看到是用:进行匹配,冒号前是数据,后是所占的比特数。 比特语法表达式 嗯,这里讲比特语法格式: 比特语法的形式:<<>>或者<<E1,E2,E3,E4,...,En>>。Ei有四种形式: Ei = Value | Value:Size | Value/TypeSpecifierList | Value:Size/TypeSpecifierList 二进制数据中总比特数恰好被8整除(二进制数据中每个字节都是8bit)。Value必须是一个绑定变量、文本串或者一个返回值的整数。浮点数、二进制数据的表达式。Size必须为一个整型或者整型绑定变量,不能是自由变量。整型默认Size为8,浮点型为64,二进制则为本身长度。SpecifierList决定字节序,取值为: @type End = big| little |native 书上给出一个例子来了解这三种排序和默认排序,不同机器可能不同。 37> {<<16#12345678:32/big>>,<<16#12345678:32/little>>,<<16#12345678:32/native>>,<<16#12345678:32>>}. {<<18,52,86,120>>, <<120,86,52,18>>, <<120,86,52,18>>, <<18,52,86,120>>} 4.使用总结 块表达式: begin Expr1, .... Exprn end 块得值就是快中最后一个表达式的值,用于当代码某处只允许使用单个表达式而你要用一串表达式时。 注释: 只有行注释%,没有块注释。 列表操作符++ ——:对列表进行添加和删除的中缀操作符。 比较表达式: 所有类型都定义了大小比较顺序: number<atom<reference<fun<port<pid<tuple<list<binary 作用:可以对存储了任何类型的列表进行排序,并根据比较顺序,编写高效的数据访问代码。 出了=:=,=/=外,其他都遵循下面规则: 如果一个比较参数为整数,另一个浮点数, 整数在比较前需要转换成浮点数。 如果两个比较参数都是整数或者浮点数,直接比较。。。 ==只适用于浮点数和整数的比较。最好都用=:=。   下划线变量: 如果一个变量在一个字句中只被使用一次,编译器会提出警告。但以下划线开始,那么编译器不会产生警告信息。 命名不准备使用的变量,增加可读性。方便调试。
Read more...

django文件上传源代码修改

当需要将上传的文件保存到别的服务器,而又不修改views里的代码,下面可能对你有点用。 Python26\Lib\site-packages\django\core\files\storage.py 这个文件里有一个FileSystemStorage类,类里的函数_save()进行了上传文件的保存。先上代码:
    def _save(self, name, content):
        full_path = self.path(name)
        print full_path,name
        # Create any intermediate directories that do not exist.
        # Note that there is a race between os.path.exists and os.makedirs:
        # if os.makedirs fails with EEXIST, the directory was created
        # concurrently, and we can continue normally. Refs #16082.
        directory = os.path.dirname(full_path)
        if not os.path.exists(directory):
            try:
                os.makedirs(directory)
            except OSError, e:
                if e.errno != errno.EEXIST:
                    raise
        if not os.path.isdir(directory):
            raise IOError("%s exists and is not a directory." % directory)

        # There's a potential race condition between get_available_name and
        # saving the file; it's possible that two threads might return the
        # same name, at which point all sorts of fun happens. So we need to
        # try to create the file, but if it already exists we have to go back
        # to get_available_name() and try again.

        while True:
            try:
                # This file has a file path that we can move.
                if hasattr(content, 'temporary_file_path'):
                    file_move_safe(content.temporary_file_path(), full_path)
                    content.close()

                # This is a normal uploadedfile that we can stream.
                else:
                    # This fun binary flag incantation makes os.open throw an
                    # OSError if the file already exists before we open it.
                    fd = os.open(full_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, 'O_BINARY', 0))
                    try:
                        locks.lock(fd, locks.LOCK_EX)
                        for chunk in content.chunks():
                            os.write(fd, chunk)
                    finally:
                        locks.unlock(fd)
                        os.close(fd)
            except OSError, e:
                if e.errno == errno.EEXIST:
                    # Ooops, the file exists. We need a new file name.
                    name = self.get_available_name(name)
                    full_path = self.path(name)
                else:
                    raise
            else:
                # OK, the file save worked. Break out of the loop.
                break

        if settings.FILE_UPLOAD_PERMISSIONS is not None:
            os.chmod(full_path, settings.FILE_UPLOAD_PERMISSIONS)

        return name
代码在这个文件的158行,函数传入参数name,第二句的print语句是我自己加上的,name路径就是存入数据库的路径,full_path路径是全路径,所以调用self.path的作用不言而喻了(代码在242行)。这里不需要全路径。 再往下两个if语句9行,功能:去掉文件名(就是文件夹路径),判断是否存在,不存在创建,然后创建不成功报错。这里也需要创建文件夹目录。 再往下的while语句就是存储文件代码了(\(≧▽≦)/激动~)。第一个if语句不明白是什么意思,在前面不知道怎么有这个属性,我也没往前找,不过应该不碍事,解释中介绍说普通上传在else里面。else里面的代码我只懂for循环,那个locks,在同一目录下有locks.py,看到一堆windows接口没兴趣研究,看注释好像是“有两个线程同时对同名文件写文件,会重新获取文件名”涉及到下面的except。这里直接设置保存图片代码。 最后的if语句应该是设置文件夹的权限。 找到这个文件,开始乱找一气,从models里的save开始没找到。后来想起调试了,没有设置错的上传路径,报错“Attempted access to '\a.jpg' denied”。然后根据Traceback,找到了文件。记录下执行顺序: views里的save(),下面省略若干,到了\lib\site-packages\django\db\models\fields\files.py 249行 file.save(file.name, file, save=False), 86行 self.name = self.storage.save(name, content) 然后到了文件\lib\site-packages\django\core\files\storage.py 44行 name = self.get_available_name(name) , 70行 while self.exists(name):, 230行 return os.path.exists(self.path(name)), 没错时,在45行,转到_save函数。
Read more...

erlang学习笔记-列表解析和断言

  1.列表解析。 1> L=[1,2,3,4] . [1,2,3,4] 4> lists:map(fun(X) -> 2*X end,L). [2,4,6,8] 5> [2*X || X <- L]. [2,4,6,8] [F(X) || X <- L] 代表由F(X)组成的列表,X取值于列表L。||右边用于匹配列表L中元素的模式,左边是一个构造器。 右边模式匹配可以像过滤器一样操作,注意大小写的区别。 6> [X || {a,X} <- [{a,1},{b,2},{c,3},{a,4},hello,"wow"]]. [1,4] 7> [X || {A,X} <- [{a,1},{b,2},{c,3},{a,4},hello,"wow"]]. [1,2,3,4] 2.列表解析快速排序算法。  
-module(lib_misc).
-export([qsort/1]).

qsort([]) -> [];
qsort([Pivot|T]) ->
qsort([X || X <- T, X < Pivot])
++ [Pivot] ++
qsort([X || X <- T,X >= Pivot]).
++中缀添加操作符 19> [1]++[2]++[3,4]. [1,2,3,4] 3.毕达哥拉斯三元组。  
pythag(N) ->
    [{A,B,C} ||
        A <- lists:seq(1,N),
        B <- lists:seq(1,N),
        C <- lists:seq(1,N),
        A+B+C =< N,
        A*A+B*B =:= C*C
    ].
lists:seq(1,N)返回一个1到N组成的列表。 4.断言。 功能:断言是一种用于强化模式匹配功能的结构。 断言序列: 用分号(;)分开的集合,只要有一个True,整个序列就为True。 用逗号(,)分开的集合,必须都为true,整个断言序列才为true。 断言序列的合法语法形式:(表格,p43) 原子true,其他常量(条件,或者绑定变量)求值为false, 断言谓词或BIF(内建函数),比较表达式,算术表达式,布尔表达式,短路布尔表达式 布尔表达式中,orelse,andalso与 or/and 区别:and/or 需要对参数都进行求值。
Read more...

vim使用小技巧,在工作目录打开vim

前面在找vim教程的时候,看到有介绍怎么修改vim打开的默认工作目录。当时看了配置文件比较麻烦,然后用vim编辑文档也不可能只在一个盘,一个目录下,输入打开路径也麻烦。 今天早上在shell下学习erlang想到了批处理,用批处理在工作目录打开vim。
:: open_vim.bat
@echo off
vim
vim字典:http://vimcdoc.sourceforge.net/doc/
Read more...

vim学习

  关于工作路径的快捷键 cd :                              改变vim的当前工作路径 lcd:                            改变当前窗口的工作路径 pwd:                            查看当前的工作路径 set autochdir:              自动设当前编辑的文件所在目录为当前工作路径   推荐一篇学习vim的文章:http://coolshell.cn/articles/5426.html 该篇文章的小补充: 用处不大,了解就好。 u → undo ,<C-r> → redo   ,我试了<C-z>也能实现撤销操作,<C-v>能实现复制,不过这可能与系统有关系(现在在windows下用的,以后再测试ununtu),不过需要按两个键,但是在编辑模式下也可以使用。 :e <path/to/file> → 打开一个文件, 使用vi <path/to/file>一样的功能 vim中翻页的命令 整页翻页 ctrl-f ctrl-b f就是forword b就是backward 翻半页 ctrl-d ctlr-u d=down u=up 滚一行 ctrl-e ctrl-y zz 让光标所杂的行居屏幕中央 zt 让光标所杂的行居屏幕最上一行 t=top zb 让光标所杂的行居屏幕最下一行 b=bottom
Read more...

erlang学习笔记--顺序型编程

妙不可言的函数编程。为什么这么说呢,当我看完第三章时,被erlang的编程方式深深的吸引住了,但是作者总是在我觉得很精妙的地方说:“该方法在实际编程中很少用到”T_T。python也有函数编程的思想,不过一直没有用到过,可能还停留在初级阶段。下面的笔记也只是自己学习中的所悟,可能有着大量的错误,如果你发现我理解的不对,感谢留言指正。请带着怀疑的态度看此笔记。 1、模块。 模块文件存放在扩展名为.erl的文件中,编译完成后的扩展名为.beam。 文件名geometry.erl(博客不支持erlang语法高亮,蛋疼了。。) -module(geometry). -export([area/1]). area({rectangle,Width,Ht}) -> Width * Ht; area({circle,R}) -> 3.14 * R * R 执行过程:先需要将erlang shell目录移动到代码目录下,查看当前目录命令pwd(),cd(Dir)。 2> c(geometry). {ok,geometry} 6> geometry:area({rectangle,10,5}). 50 7> geometry:area({circle,1.4}). 6.1544 字句顺序不重要,但调用参数的匹配过程是从上向下的。函数不能处理模式匹配失败的情况,将会抛出一个运行时错误。 2、fun匿名函数 1> Z = fun(X) -> 2*X end. #Fun<erl_eval.6.82930912> 2> Z(3). 6 这个简单的例子介绍fun函数的用法,用一个"end"做结尾。第三行语句的值为一个函数Z(X)=2*X 以fun为参数的函数 3> Even = fun(X) -> (X rem 2) =:= 0 end. #Fun<erl_eval.6.82930912> 4> Even(8). true 5> Even(3). false 6> lists:map(Even,[1,2,3,4,5,6,7,8]). [false,true,false,true,false,true,false,true] 7> lists:filter(Even,[1,2,3,4,5,6,7,8]). [2,4,6,8] 第三个语句,我们定义了一个Even函数,用来求变量是否是偶数,是返回true。 第四第五语句是函数的使用。 第六行将函数Even作为参数,将列表中的每一个元素代入Even,得到的值生成一个新的列表。lists:filter是将满足使Even值为true的列表元素生成一个新列表。 返回fun的函数 11> Fruit = [apple,pear,orange]. [apple,pear,orange] 12> MakeTest = fun(L) -> (fun(X) -> lists:member(X,L)end) end. #Fun<erl_eval.6.82930912> 13> IsFruit = MakeTest(Fruit). #Fun<erl_eval.6.82930912> 14> IsFruit(pear). true 15> IsFruit(dog). false 17> BoxList = [dog,orange,cat,apple,bear]. [dog,orange,cat,apple,bear] 18> lists:filter(IsFruit,BoxList). [orange,apple] 11行定义了一个Fruit列表,里面都是水果(⊙﹏⊙b汗)。十二行定义了一个函数MakeTest(L),他的值为一个fun函数,这个fun函数的功能是看变量X是否是L中的元素,是返回True。(感觉就是二元一次方程,你必须知道两个变量才能求得一个结果值) 第13行定义函数IsFruit(X)=lists:member(X,Fruit),当然我这样表示是不正确的,只是为了写得像数学上的函数。正确是IsFruit = fun(X) -> lists:member(X,Fruit) end,这样这个函数的功能变成:看X是否是水果,是返回true。 第14,15行进行了函数测试。十七行定义了一个篮子,里面各种东西,我们要挑出水果,用我们的lists标准库,如果IsFruit为true,那么是水果,则挑拣到另一个篮子里。哇哈哈~ 定义自己的抽象流程控制: 这里更是可以举一反三,做你想做的^_^。 书上给了一个for循环控制结构的实现:(语法不支持高亮,就用截图了,不高亮我自己看着别扭) [caption id="attachment_578" align="alignnone" width="300" caption="erlang编程"]erlang编程[/caption] 这是实现了for(i=0,i<10,i++),for i in range(0,10),简单的你可以实现一个for i in range(0,10,2)。 解释一下程序:如果第一个参数值与第二个相同,返回执行 F(Max),否则匹配第二个,F(I)作为列表的头,for(I+1,Max,F)作为列表尾。 如果看到这里,你也会有疑问,为什么不写第二条语句在第一条上面呢?因为交换以后,for(I,Max,F)将满足任何语句,就不会执行第二条语句。编译器也会提示给你:lib_misc.erl:6: Warning: this clause cannot match because a previous clause at line 5 always matches。你的执行将会死循环。当然如果你输入的匹配I>Max,也会进入死循环。 我感觉这将比其他语言的for循环更加灵活。 25> c(lib_misc). {ok,lib_misc} 26> lib_misc:for(1,10,fun(I) -> I end). [1,2,3,4,5,6,7,8,9,10] 27> lib_misc:for(1,10,fun(I) -> I*I end). [1,4,9,16,25,36,49,64,81,100] 28> 编译,26行打印1-10整数列表,27行打印平方列表。   先整理这么多,第二章的笔记是边学边记,第三章是一口气给看完了。⊙﹏⊙b汗
Read more...

vim erlang插件配置

The Erlang plugin for Vim,地址:https://github.com/onlychoice/vimerl/ windows下将文件复制到“安装目录/Vim/vimfiles”里面就行了。 安装完直接带有自动补全功能, Ctrl+c,Ctrl+o,应该是正确的。 这里找到一个管理vim插件的工具:pathogen。 地址:http://www.vim.org/scripts/script.php?script_id=2332 这个工具可以很方便的管理插件的安装和卸载,windows下在\vimfiles里建立一个 bundle 目录, 以后插件可以以整个文件夹的形式存放在里面。 方便安装删除。 下载的pathogen.vim文件放到Vim\vimfiles\autoload里,linux下安装到/.vim/。 配置pathogen: 修改~/.vimrc配置文件,加入: List代码 call pathogen#infect() syntax on filetype plugin indent on vim字体的修改方法参考文章:http://www.vimer.cn/2009/11/ vim%EF%BC%88gvim%EF%BC%89%E7%BC%96%E7%A8%8B%E5%AD%97%E4%BD%93%E6%8E%A8%E8%8D%90.html
Read more...

mysql图形化界面工具

当需要修改数据库表名字的时候,发现命令超长超麻烦,就想找一个可以界面显示的工具。以前接触phpmyadmin,那个需要php环境,但被我卸载了,又到网上搜索,随便找了一个,名字mysql-gui-tools-5.0-r17-win32.zip。具体叫什么我也不清楚,下载地址:http://dev.mysql.com/downloads/gui-tools/5.0.html 使用后发现很好操作,功能还没有都熟悉,感觉挺强大的。 安装目录下有个MySQLAdministrator.exe,打开后填写host,username,password进入。我只使用了导入导出功能、表的名字修改,字段的添加删除,名字修改。  
Read more...

网站采集小体会

这几天用python采集了两个网站,一个国内的一个国外的。有点小体会,记录: 前面已经写了一篇《今天采集某站数据经验总结》,是介绍国外网站的,今天再一起总结一下。 1、国内外网站html规范比较。 国内代码写得很标准,class标签用的很多,想显示格式一样的数据,可能都采用后台一个for循环生成代码。冗余代码可以说没有。采集时不容易准确定位 国外代码很乱,在标签中换行,各种空行,各种空格,还有你想不到的符号用来闭合标签。用的id属性很多,每个标签基本上都会有。定位容易,但是各种报错。 2、javascript比较。 国内倾向于将javascript用于网站功能上,浏览器显示的代码和html源码相差不大。很方便找到关键字。 国外界面显示代码很多是javascript修改的,但是你浏览器不启用js功能页面也不会有太大变化。需要保存源码,查看代码。 3、用urllib模块进行采集时,国内必须加入发送包头信息,但是这个很容易伪造浏览器信息,用处不大。   我在第一次采集的时候,将提取url功能,提取产品列表功能,提取产品信息的功能分开写的,发生网络连接错误,提取url和产品列表都要重新获取,影响速度。 第二次写,将总的url提取时,保存文件了。写第二个功能进行想要数据过滤时再读取文件进行过滤保存,后面再提取列表,保存都采用这种方式,会好一点。以后慢慢优化代码,写出个比较方便的工具,就是有时候特殊情况太多,工具代码的逻辑是死的,还是不方便。
Read more...

Previous Page 1 2 3 4 5 6 7 8 9 10 Next Page 最后一页