Posts
Will patch rename the filename?
幫朋友測試 patch 在使用 git diff 產出的 patch 檔案時,看會不會改名。 我測試的環境是 Ubuntu 18.04 先說結果,patch 是會為檔案改名的喔。
首先建立 bare repository
mkdir /tmp/foo.git cd /tmp/foo.git && git init --bare 到另外一個目錄,簽出 repository,然後加一個檔案
cd $HOME git clone /tmp/foo.git foo cd foo touch readme.md git add readme.md git commit -m "first initial" 再回到 HOME,簽出 repository,等等會回到這個目錄使用 patch 指令
cd $HOME git clone /tmp/foo.git foo-new 回到 foo ,先建立 branch,更名,然後製作 patch 檔
cd $HOME/foo git checkout -b file_is_renamed git mv readme.
Posts
Python asyncio
看 Linux Journal 時看到的,順便練一下。這篇只是前導,還沒到 asyncio 的新語法。不過後續文章可能不會繼續在 Linux journal 上刊登了,因為 Linux journal 公告停刊了。
Understanding Python’s asyncio
#!/usr/bin/env python # -*- coding: utf-8 -*- # 回傳結果是個 generator def hello(name): while True: name = yield f'Hello, {name}' if not name: # 當 name 為空時,就停止 break try: g = hello('world') # 取得 genrator print(next(g)) # 用 next 取得下個結果,得到 "Hello, world" print(g.send('foo')) # 用 send 送 "foo" 進去,得到 "Hello, foo" print(g.send('bar')) # 再用 send 送 "bar" 進去,得到 "Hello, bar" print(g.
Posts
Python property 能不能繼承
Python 的 property 在繼承之後,是有作用的。
#!/usr/bin/env python # -*- coding: utf-8 -*- class Base: @property def data(self): return {'Base': 'Base'} class Child(Base): @property def data(self): # 取得父類別的 data property data = super(Child, self).data # 增加 "Child" data.update({'Child': 'Child'}) return data def main(): base = Base() print("base.data={}".format(base.data)) child = Child() print("child.data={}".format(child.data)) if __name__ == "__main__": main()
Posts
Python - metaclass
好奇 Django 的 Meta 怎麼做的,上網找了資料,並且參考 Django 的原始 碼。
#!/usr/bin/env python # -*- coding: utf-8 -*- import six # 先做一個 Meta class ,Django 的 ModelBase 就是一個 Meta class class Meta(type): # 一定要繼承 type def __call__(self): print('Enter Meta.__call__: {}'.format(self)) obj = super(Meta, self).__call__() print('Exit Meta.__call__: {}'.format(obj)) return obj # 主要的關建 def __new__(cls, name, bases, attrs): print('Enter Meta.__new__: {} {} {} {}'.format( cls, name, bases, attrs)) newClass = super(Meta, cls).__new__(cls, name, bases, attrs) # 取得類別裡 Meta 子類別的 attribute metaClass = attrs.
Posts
Python - UTC 日期轉 local 日期
用 dateutil 做解析日期字串,然後用 arrow 做轉換,很方便。
from __future__ import print_function import sys from dateutil.parser import parse import arrow def utc2local(utc_date_str): utc_date = parse(utc_date_str) # 用 dateutil.parser.parse 來解析日期字串 local_date = arrow.get(utc_date).to('Asia/Taipei') # 拿到日期,用 to 轉換,收工 return local_date.format('YYYY-MM-DD HH:mm:ss') # 格式化以後傳回 def main(): if not len(sys.argv[1:]): print("No arguments") return for arg in sys.argv[1:]: print(utc2local(arg)) if __name__ == "__main__": main()
Posts
Python - 將句子中的單字首字轉換成大寫
在網路上看到,就順便試試看。來源:Let’s Start From Here: [JS/ES6] 將句子中的單字首字轉換成大寫-不用正規表示法
用 regular expression 的話,應該是可以用 \w+ 去找到每個 match,再用 capitalize() 轉換就行了。
# -*- coding: utf-8 -*- """Convert each words capital in string.""" from __future__ import print_function from argparse import ArgumentParser def convert_each_word_capital(s): """Convert each words capital in string.""" words = s.split(" ") capitaled_words = map(lambda x: x.capitalize(), words) return ' '.join(capitaled_words) def main(): """Main.""" parser = ArgumentParser() parser.add_argument('strings', metavar="S", type=str, nargs='+') args = parser.parse_args() for arg in args.
Posts
Python classmethod/staticemthod
知道但是不太熟,特別來試試看。 classmethod 跟 staticmethod 很相似,classmethod 有帶一個 cls ,就是 class 本身,staticmethod 比較像是 c++/java 裡的 static。
from __future__ import print_function class C(object): def __init__(self, name): self.name = name @classmethod def build(cls, arg1, arg2): print(cls) print(arg1) print(arg2) return cls("arg1={0} arg2={1}".format(arg1, arg2)) @staticmethod def create(): return C("Static") c1 = C.build(3, 4) print(c1.name) c2 = C("John") print(c2.name) c3 = c2.build(1, 2) # 也可以用 C.build(1, 2) print(c3.name) c4 = C.create() print(c4.name)
Posts
Python hasattr
今天看到這篇文章:一个危险的Python函数,不推荐使用| 编程派 | Coding Python
裏面說,在 Python 2 裡不要用 hasattr 來判斷是否有屬性存在,好奇做了實驗。
我使用的 Python2 是 2.7.6,Python 3 是 3.4.3
# test_hasattr.py # python2 有繼承 object 跟沒繼承 object 有差別,所以特別試試看。 # 沒繼承 object class B(): def __init__(self): self.name = "B" @property def y(self): # print("y") return "y" # 有繼承 object class C(object): def __init__(self): self.name = "B" @property def y(self): # print("y") return "y" print("hasattr(B(), 'y')={}".format(hasattr(B(), "y"))) print("hasattr(B(), 'name')={}".format(hasattr(B(), "name"))) print("hasattr(C(), 'y')={}".format(hasattr(C(), "y"))) print("hasattr(C(), 'name')={}".
Posts
Extract partial keys/attributes from dict/object
利用 dictionary comprehension 很輕易的就可以辦到這件事情。 參考自:http://stackoverflow.com/questions/5352546/best-way-to-extract-subset-of-key-value-pairs-from-python-dictionary-object
from datetime import datetime def getattrs(instance, attrs=[]): if isinstance(instance, dict): return { attr: instance[attr] for attr in attrs if attr in instance} elif isinstance(instance, object): return { attr: getattr(instance, attr) for attr in attrs } raise Exception("Not object or dict") class Book(object): def __init__(self, title, author, created=datetime.now()): self.title = title self.author = author self.created = created def __str__(self): return "{title} - {author}".format(title=self.title, author=self.author) def __repr__(self): return self.
Posts
Python try-except-else-finally
Python 的 try-except-finally 裡有 else 子句,這相當有意思。
finally 區塊的程式,不管 try-except 裡是否有 raise exception,都會被執行。而 else 則是只有在 try-except 裡沒有 raise exception 時才會被執行。
def foo(i): print("\ni={}".format(i)) try: if i == 0: raise Exception("i == 0") print("Hello") except Exception, ex: print(ex) else: print("else") finally: print("finally") foo(0) foo(1) 執行結果
i=0 i == 0 finally i=1 Hello else finally
Posts
bluebird Promise
sequelize 的 Promise 是用 bluebird 這個 package 實作的,就拿來練習。
var bluebird = require('bluebird'); var Promise = bluebird.Promise; function async(url) { console.log("async"); return new Promise(function(resolve, reject) { // 這邊簡單做,url 是 undefine 時,就呼叫 reject;否則就呼叫 resolve() // resolve() 就是走 then() 那路,reject() 就是走 catch() 那路。 if(url) { resolve(url); } else { reject("url is empty"); } }); } async("http://localhost").then(function(url) { console.log("then " + url); return "new url"; }).then(function(url) { // 2nd then() will get 1st then() returned value.
Posts
Javascript 動態改變 member function
純粹因為懶得 fork 出來改,所以想說看能不能動態改變,算是 monkey patch 這樣。 實驗的結果是可以,畢竟這是動態語言應該要具有的能力。
"use strict"; var User = function() { this.className = "User"; }; User.prototype.findByUsername = function(username, cb) { // 原來的函式 console.log("findByUsername"); }; User.prototype.toString = function() { return this.className; } function attachToUser(UserSchema) { // 在這裡動態進行更換 UserSchema.prototype.oldFindByUsername = UserSchema.prototype.findByUsername; UserSchema.prototype.findByUsername = function(username, cb) { console.log("new findByUsername"); }; } attachToUser(User); var obj = new User(); obj.findByUsername("admin", function() {}); obj.oldFindByUsername("root", function() {}); console.log(obj.toString()); 執行結果:
new findByUsername findByUsername User
Posts
C# template method and type constraint
在 linqpad 裡試著,記得先選為 c# program,再貼 code
void Main() { /* // show error run(20); run("Hello world"); */ run(new Dictionary<string, string>()); } // Define other methods and classes here // Add type constraint for run() // allow only IDictionary void run<T>(T x) where T: IDictionary { Console.WriteLine(typeof(T).ToString()); }
Posts
Java Short
沒想到簡單的 i + 1
class test_short { public void test() { Short i=1; i = i + 1; } } 在形態是 Short 的情況下是會編譯失敗的。
得這樣改才行
class test_short { public void test() { Short i=1; i = (short)(i+1); } }
Posts
Python Class variable
標題下的不好,因為不知道該怎麼說。類別裡宣告變數以後,之後方法裡,會怎麼去認定,為了搞清楚這點,就寫了小程式。
class Animal(object): NAME = "Animal" def __init__(self): print(Animal.NAME) def bark(self): print("Bark(1): " + Animal.NAME) print("Bark(2): " + self.NAME) animal = Animal() animal.bark() animal2 = Animal() animal2.NAME = "Planet" animal2.bark() 結果:
Animal Bark(1): Animal Bark(2): Animal Animal Bark(1): Animal Bark(2): Planet 依據結果的解讀是這樣,當用 Animal 宣告時,每個 instance 都會有一個 NAME,所以在變更 animal2.NAME 以後,bark 裡的 self.NAME 實際上就是變動後的內容 “Planet”;但如果用 Animal.NAME 就還是原來的 “Animal”。
Posts
C# Lazy
.Net framework 4 以後多了一個 Lazy,顧名思義是做 Lazy initialization 用的,有真正需要的時候,它才去賦值。
// Run with LINQPad // Please specify "Language" to "C# Program" void Main() { var t = new Lazy<int>(getDefaultInteger); if(!t.IsValueCreated) { Console.WriteLine("Not yet."); } Console.WriteLine(t.Value.ToString()); } // Define other methods and classes here int getDefaultInteger() { return 20; } 執行結果會先印出 “Not yet.” 才印出 20,當呼叫 Value 時,才真正取得值。
Posts
C# 練習:仿 Java Lambda
C# 從一開始仿 Java,到後來,語法上的發展已經超越 Java,所以現在反而是 Java 仿 C# 與其他語言。最近的 Java 8 在講的 Lambda ,早在 C# 2.0 時,就已經有了雛型,到了 C# 3.0 則已經發展成熟。
就拿這篇 認識 Lambda/Closure(1)從 JavaScript 的函式物件談起 by caterpillar | CodeData 裡的例子來改寫:
// lambda1.cs // How to build: // Linux: dmcs /t:exe lambda1.cs // Windows: csc /t:exe lambda1.cs using System; using System.Collections.Generic; public class DelegatePractice { public static void Main(string[] args) { new List<string>( new string[] {"1", "2", "3", "4", "5"} ).ForEach(delegate(string s) { Console.
Posts
C# about dynamic ExpandoObject member function
由於 ExpandoObject 自身的能力,增加屬性非常簡單。但如果要增加一個 member function,該怎麼做?這可以透過 Func 或 Action 來達成。
List<dynamic> userlist = new List<dynamic>(); // 利用 currying 來模擬類似 python 的 foo(self, x, y...) // C++ 的 this 其實跟 python 一樣,但是 this 不需要明確的寫出來,這部分是編譯器幫忙做掉 // 在 C# 裡,看來是沒辦法,所以在設置 member function 時,就先把 instance 傳進 toString, // 讓 toString 傳回另外一個新 function Func<dynamic, Func<string> > toString = delegate(dynamic user) { return new Func<string> (() => String.Format("User: {0} Age: {1}", user.Name, user.age) ); }; for(int i=0; i<100; i++) { dynamic user = new System.
Posts
C# about dynamic ExpandoObject
讀了 metaprogramming in .net 第一章,才知道 4.0 以後的 dynamic 很強大。
以前 c# 物件的成員,是必須先在類別裡指定好的,現在透過 ExpandoObject 就可以不需要了,直接就可以指定屬性,然後寫 linq 敘述時,就能直接使用。
List<dynamic> list = new List<dynamic>(); for(int i=0; i<100; i++) { dynamic container = new System.Dynamic.ExpandoObject(); container.id = i; container.Name = String.Format("John{0}", i); container.age = i+10; list.Add(container); } var query = from obj in list where obj.age>55 select obj; Console.WriteLine("query.count = {0}", query.Count()); 補充兩個有趣的 library: * Adventures with C# 4.0 dynamic - ExpandoObject, ElasticObject, and a Twitter client in 10 minutes * The Dynamic Sugar Library
Posts
C# 使用 CodeDomProvider 編譯程式
也是從 metaprogramming in .net 看來的,一樣是在 ubuntu 12.04 上用 dmcs /t:exe intantiatingCodeProviders.cs 編譯,執行沒問題。書裡說會有找不到 csc.exe 的情況,但至少在 Ubuntu 上是沒看到。
// intantiatingCodeProviders.cs using Microsoft.CSharp; using System.CodeDom.Compiler; using System.Collections.Generic; class IntantiatingCodeProviders { static void Main() { var providerOptions = new Dictionary<string, string>(); providerOptions.Add("CompilerVersion", "v4.0"); var csProv = new CSharpCodeProvider(providerOptions); var compilerParameters = new CompilerParameters(new string[] { }); CompilerResults results = csProv.CompileAssemblyFromSource(compilerParameters, @"namespace V3Features { class Program { static void Main() { var name = ""Kevin""; System.
Posts
C# CodeDom Provider
看 metaprogramming in .net 時,看到的範例,可以列出 CodeDom Provider:
using System; using System.CodeDom; public class Practice { public static void Main(string[] args) { foreach (System.CodeDom.Compiler.CompilerInfo ci in System.CodeDom.Compiler.CodeDomProvider.GetAllCompilerInfo()) { foreach (string language in ci.GetLanguages()) System.Console.Write("{0} ", language); System.Console.WriteLine(); } } } Ubuntu 12.04 上的結果,如果有裝 IronPython 之類的,或是有自訂會更多。
c# cs csharp vb vbs visualbasic vbscript js jscript javascript vj# vjs vjsharp c++ mc cpp
Posts
C# currying
順手試試看。 C# 的 Func 比較囉唆一點,寫完你會很懷念 javascript 或 python 之類的語言。第一個參數是傳給函數的參數,第二個參數是傳回的參數。所以要 Currying,就是把第二個參數再設為 Func 就可以。Func 不只有一個參數的版本,也有兩個、三個…等等的版本,但不是無限的,有一定限度,最多到 16 個,也就是 Func<T1, T2, T3…., T16, TResult> 。
using System; public class Anonymous { public static void Main() { Func<string, Func<string, int> > say = delegate(string greeting) { Func<string, int> foo = delegate(string name) { Console.WriteLine("{0} {1}", greeting, name); return 0; }; return foo; }; Func<string, int> hello = say("Hello"); hello("John"); } }
Posts
Javascript setTimeout
每次用每次都要查一下,這次要記下來。 有寫在 jsfiddle.net 那邊,網址是 http://jsfiddle.net/LaPFQ/ 應該是要再包成類別之類的會比較好,不過暫時就這樣吧。
HTML
<div id="log"></div> Javascript
var limit = 10; var count = 0; var trigger = function() { $("#log").append("triggered " + count + "<br/>"); count++; if(count<=limit) { setTimeout(trigger, 2000); // $("#log").append("scheduled<br/>"); } }; $("#log").append("started<br/>"); var timeout = setTimeout(trigger, 2000);
Posts
Python decorator
真的還是要自己試著憑空弄過一次才會比較清楚。
一般沒帶參數的 decorator,就是兩層。第一層負責接原來的函式,第二層的函式就是要傳回去的。有帶參數的 decorator,就是三層,第一層負責接參數,第二層負責接函式,第三層的函式是要傳回去的。
那如果有上多個 decorator 時,最裡層的會先被執行,接著才是外層的。
也可以用類別來寫,用類別寫就是要利用 __call__,之後再來試試看。
# -*- coding: utf-8 -*- from __future__ import print_function, unicode_literals def wrapper(f): def inside_func(*args, **kwargs): print("> wrapper") f(*args, **kwargs) print("< wrapper") return inside_func def before(s): def new_func(f): def inside_func(*args, **kwargs): print(s) f(*args, **kwargs) return inside_func return new_func def after(s): def new_func(f): def inside_func(*args, **kwargs): f(*args, **kwargs) print(s) return inside_func return new_func def repeat(n): def new_func(f): def inside_func(s): for i in range(n): f(s) return inside_func return new_func @wrapper def foo(s): print(s) @repeat(5) def foo1(s): print(s) @after("<<<") # then here @before(">>>") # run first def foo2(s): print(s) foo("Hello") # 前後會加上 '> wrapper' 與 '< wrapper' foo1("World") # 這會印五次 World,因為 repeat(5) foo2("Hello world") # 先印出 '>>>' ,執行原函式,再印出 '<<<' 輸出結果
Posts
Python nested if
之前在 checkio 網站有看過人家這樣寫:
def checkio(x, y): result = (x>10, y<10) conditions = { (True, True): 1, (True, False): 2, (False, True): 3, (False, False): 4 } return conditions(x, y) 真的有醍醐灌頂之感,原來 tuple 也可以拿來當作 dict 的 key。
不過今天不是說這個,昨天天寫出這種 code,覺得超級醜:
s = "Hello" pos = s.find('a') if pos == -1: pos = s.find('b') if pos == -1: pos = s.find('c') if pos == -1: return 今天就在想要怎麼寫會比較好,原本想說:
pos = s.find('a') or s.find('b') or s.
Posts
Python unshorten
在 Stackoverflow 上找到這兩篇: * curl - How can I un-shorten a URL using python? - Stack Overflow * How can I unshorten a URL using python? - Stack Overflow
原理很簡單,就是送 HEAD request 出去,然後判斷回傳的 status code;如果是 30x,表示是轉址,就拿取得的 header 裡的 location 繼續去查;如果是 20x,就表示拿到原來的網址了。
後來是用了第一篇的程式碼,程式是使用遞迴去處理網址是轉址的情況。
def unshorten_url(url): parsed = urlparse.urlparse(url) h = httplib.HTTPConnection(parsed.netloc) # 這邊是用 httplib,你可以用你熟悉的 module resource = parsed.path if parsed.query != "": resource += "?" + parsed.query h.request('HEAD', resource) # 送 HEAD response = h.
Posts
Python URL 組合之二
urlparse.urlparse 解析後的結果,如果有想要變動的話,可以再用 urlparse.urlunparse 組回去,下面是一個從網址把 Google analytics 參數移除的例子。
import urlparse from urllib import urlencode def remove_ga_params(url): """把以 utm_ 開頭的參數都移除掉,utm_ 開頭的參數多半是 Google analytics 使用的""" parsed = urlparse.urlparse(url) # 拆出來的 ParseResult 其實是 NamedTuple params = urlparse.parse_qs(parsed.query) # 將字串型態的 query 轉為 dict 型態,以利處理 for k in params.keys(): if k.startswith("utm_"): del params[k] modified = list(parsed) # 把 tuple 轉為 list,以便於修改 modified[4] = urlencode(params) # 4 => query # 第四個是 query,這部份可以看 urlparse 模組說明 return urlparse.urlunparse(modified) # 用 urlunparse 轉回網址
Posts
Python3 "\u860b\u679c" 轉為 Unicode 字串
這是在 fb 上看到人家問的問題,可是後來好像貼的人又移除貼文了。
原作的輸入是在檔案裡,所以用 python 讀入以後,看到是 “\u860b\u679c” 這樣,想要轉為 unicode 字串。
我最先的想法是用 re 來找出符合 \u860b,折騰了半天,自己的 re 功力太差,寫的 pattern 不好,都沒 match 到。後來就想,直接拿 “\u” 來 split 就行了,於是:
input_string = "\\u860b\\u679c" output = ''.join([chr(int(n, 16)) for n in s.split("\\u")[1:]])
Posts
Python absolute_import
在網路上看到 from __future__ import absolute_import ,不懂什麼意思,就研究一下,看是怎麼一回事。 主要定義在 PEP 328 http://legacy.python.org/dev/peps/pep-0328/
用例子來看 absolute_import 會比較清楚,這部份我是參考 http://bytes.com/topic/python/answers/596703-__future__-import-absolute_import 來試驗。
這次實驗需要的檔案比較多,一共7個。
# bar/__init__.py # Empty # bar/foo.py print("inside bar") # bar/absolute.py from __future__ import absolute_import import foo # bar/relative.py import foo # foo.py print("toplevel") # main for testing absolute_import import bar.absolute # main for testing without absolute_import import bar.relative 目錄架構是這樣的: * main_with_absolute_import.py * main_without_absolute_import.py * foo.py * bar * __init__.
Posts
Python feedparser
feedparser 是一個可以用來解析 RSS/ATOM feed 的模組,是目前最常見也最常用的模組。用 pip search 時,有發現相似的模組 speedparser,號稱比 feedparser 更快,有機會再來試用看看。
from __future__ import print_function import sys import feedparser # 會自動去抓取指定網址的 RSS/ATOM 並進行解析 d = feedparser.parse("http://your_site/rss.xml") # 主要的條目都在 entries 裡 if 'entries' not in d: print("No entries") sys.exit(-1) for entry in d['entries']: print("url:" + entry['link']) # 文章的網址 print("title: " + entry['title'].encode('utf-8')) # 文章標題
Posts
Python 多重繼承
在 Facebook 上看到有人問,所以就來試驗看看。原 PO 的問題是問,當多重繼承時,在子類別的 ctor() 使用 super() 去呼叫父類別的 ctor(),為什麼只有呼叫到左邊父類別的 ctor()。好吧,其實我不知道為什麼,這可能要看 super() 是如何實作的,但我試驗以後,認為是要利用bases來處理,bases 會傳回所有的父類別,以下面的例子來說,C.bases 就會是 (A, B),如此一來,就可以利用它來呼叫到每個父類別的 ctor()。
# -*- coding: UTF8 -*- class A(object): def __init__(self, parent=None): print('init A class') class B(object): def __init__(self, parent=None): print('init B class') class C(A, B): def __init__(self, parent=None): for clazz in self.__class__.__bases__: # 改用 __bases__ clazz.__init__(self, parent) #super(self.__class__, self).__init__(parent) # 只呼叫了 A.__init__() print('init C class') c = C()
Posts
Java constructor
純粹是驗證,雖然已經知道結果,還是動手確認一下。
// Activity.java class Activity extends Context { } // BrowserActivity.java class BrowserActivity extends Activity { BrowserActivity() { Controller controller = new Controller(this); } } // Context.java public class Context { } // Controller.java import static java.lang.System.*; class Controller { Controller(Context ctx) { out.println("Context"); } Controller(Activity act) { out.println("Activity"); } } // Hello.java // 這是主程式 import static java.lang.System.*; public class Hello { public static void main(String[] args) { out.
Posts
Part of Android CTS SimpleDateFormatTest in Jython
同事問我為什麼會測試不過,就想說用 jython 試試看 PC 上的行為。 SimpleDateFormat(“EEEE”, Locale.ENGLISH).parseDate(“Tuesday”) 會得到 Tue Jan 06 00:00:00 CST 1970 ,用 UTC calendar 去取星期幾時,會得到 2 - Monday,而測試預期是得到 3 - Tuesday。 為什麼 Android 裡的測試會預期得到 3 呢?? 而 PC 上得到的結果是一樣的呢??
from java.text import SimpleDateFormat from java.text import ParsePosition from java.util import Locale from java.util import TimeZone from java.util import Calendar def parseDate(locale, fmt, value): sdf = SimpleDateFormat(fmt, locale) pp = ParsePosition(0) d = sdf.parse(value, pp) if not d: return None c = Calendar.
Posts
Python imp
蠻好奇 Python 怎麼實現 Plugin,在 Stackflow 上找到 Building a minimal plugin architecture in Python - Stack Overflow ,得知可以使用 imp 模組。 PyMOTW 有 imp 的範例:imp – Interface to module import mechanism. - Python Module of the Week 這是 imp module 的說明文件:30.1. imp — Access the import internals — Python v2.7.5 documentation
如果你的 plugin 放在目錄下,最快的方法是把 plugin 目錄加到 sys.path 裡,這樣 find_module 就可以找到。
import sys import os import imp sys.path.insert(1, os.path.join(os.getcwd(), 'plugins')) f, fn, desc = imp.
Posts
Python URL 組合與分拆
Python 2 裡是用 urlparse
# 組合 from urlparse import urljoin from urllib import urlencode base_url = "http://something.com" users_url = urljoin(base_url, "users") # 得到 http://something.com/users params = {"_id": 0, "name": "Guest"} print urljoin(users_url, '?' + urlencode(params)) # 這個 '?' 得自己加,參考資料 3 裡有不錯的函式可以參考 # 分拆 from urlparse import urlparse, parse_qs url = 'http://something.com?blah=1&x=2' print urlparse(url).query # 得到'blah=1&x=2' print parse_qs(urlparse(url).query) # 得到 {'blah': ['1'], 'x': ['2']} 到了 3.0 ,得改用 urllib.parse 模組,使用方法大同小異,就是 import 的地方要修改
Posts
Python ast (1)
使用 ast.parse() 得到的 ast tree,一定都會包在 ast.Module 裡;之後重新丟回 compile 去編譯時,一樣也是要有 ast.Module 才行。 ast.FunctionDef 裡的 name, args, body, decorator_list 必填,args 可以填 ast.arguments(args=[], vararg=None, kwarg=None, defaults=[]) ,decorator_list 可以填空的 [] ast.dump 是好朋友,可以多加利用,看 Python 組出的 AST tree。
import ast p_node = ast.Print(values=[ast.Str(s='Hello')], nl=True) # Print 是一個特別的 node,Python 3 裡應該是不一樣的了。 f_node = ast.FunctionDef(name='foo', args=ast.arguments(args=[], vararg=None, kwarg=None, defaults=[]), body=[p_node], decorator_list=[]) # 定義函式 e_node = ast.Expr(value=ast.Call(func=ast.Name(id='foo', ctx=ast.Load()), args=[], keywords=[], starargs=None, kwargs=None)) # 呼叫函式 m_node = ast.Module(body=[f_node, e_node]) # 放到 module 的 body 裡,body 裡是一個 list fixed = ast.
Posts
Python NodeTransformer
透過 ast.NodeTransformer 可以動態的把程式裡的字串換掉,利用 compile() 再執行。 主要的說明就放在程式裡。
# transformer.py from __future__ import print_function import ast class MyTransformer(ast.NodeTransformer): def visit_Str(self, node): # 如果訪問到的 node 是 Str if node.s.startswith('Hello'): # Str 的內容以 'Hello' 起始 s = node.s.replace('Hello', 'World') # 換掉!! new_node = ast.copy_location(ast.Str(s=s), node) # 透過 copy_location 複製資訊給新的 Str else: new_node = node # 傳回原來的 return new_node if __name__ == "__main__": myprog = """ for i in range(10): print 'Hello {0}'.format(i) """ # 程式 a = ast.
Posts
Pypy make_proxy
在 What PyPy can do for your objects — PyPy 2.1.0 documentation 看到 make_proxy 的範例:
from tputil import make_proxy history = [] def recorder(operation): history.append(operation) return operation.delegate() >>>> l = make_proxy(recorder, obj=[]) >>>> type(l) list >>>> l.append(3) >>>> len(l) 1 >>>> len(history) 2 但實際卻會發生:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/pypy/lib_pypy/tputil.py", line 29, in make_proxy tp = tproxy(type, perform) TypeError: 'list' object could not be wrapped 參考 pypy 對 make_proxy 的測試,增加類別 A,並修改為
Posts
Python list comprehension / map / multiprocess pool.map 比較
# 使用 for def main(): result = [] for i in range(400): result.append(foo(i)) # 使用 list comprehension def main(): result = [foo(i) for i in range(400)] # 使用 map def main(): result = map(foo, range(400)) 使用 timeit 執行 1000000 次的結果:
for list comprehension map 96.8263 75.3605 77.5310 這裡的結果很奇妙,list comprehension 居然比較快。
把 range(400) 改為 range(1000000),增加 multiprocessing ,並改用 cProfile 測試。
Posts
Python function annotation
在 Python cookbook 7.3 看到 Function annotation ,在 Python 2 上卻不行,後來想到在 Python 3 上面試,果然就可以了。
def foo(i: int) -> int: return i*2 foo(2) 這是被規範在 PEP 3107 – Function Annotations ,我想目前用的人應該不多吧,在未來一兩年內應該也不多,畢竟大家多少還是考慮到跟 Python 2 的相容性,相信等到 Python 3 普及以後,這會被大量使用到。
參考資料: * A powerful unused feature of Python: function annotations. | Manuel Cerón
Posts
Classic ASP Security Project
Classic ASP Security Project 這裡有針對 ASP 安全寫的一些 Library,主要有兩個: * SingerASP : 這個主要是檢查 request 用的,主要概念是透過 regex 。假定你的 default.asp 需要輸入某欄位,那麼就在 rules 下新增 default.svdl.asp ,在裡面寫規則,含括 stinger.asp 的 default.asp 再寫上:
Dim validator set validator = new Stinger 'Send Javascript Code for better user experience, pass form name as parameter response.write validator.getJavaScript ("form") 就可以自動檢查輸入的欄位。rules/regex.xml 還看不出來在那邊使用到,裡面是寫了一堆 regex 的定義。 * ClassicASP ESAPI : 這個則是一個用 C# 2005 寫的 COM 元件,給 ASP 呼叫用,呼叫的範例是 ClassicASP Default.asp。這個就比較包山包海,功能比較齊全。
這都有原始碼可以參考。
微軟自家也有 ASP 安全中心,也有專文介紹一定要檢查使用者的輸入:Validating User Input to Avoid Attacks
Posts
VBScript include/import
VBScript 沒有提供 include/import 的語法,難道就只能複製貼上了嗎?
Google 了一下,找到兩種解: * 利用 WSF :WSF 是一個 XML 檔案,裡面描述會引用到哪些 script 檔案,執行這個 WSF 檔案,WScript 會幫你引用這些指定的 script 檔案。好處是可以同時含括 JScript 跟 VBScript 的檔案。 * 利用 ExecuteGlobal 敘述:先把檔案內容都讀進來,再使用這個敘述去執行。這就僅限於 VBScript 了。
參考資料: * How do I include a common file in VBScript (similar to C #include)? - Stack Overflow * How to include a file from within a VBScript script
Posts
VBScript isNumeric 跟你想的不一樣
原本以為 isNumeric 是可以信賴的,豈知 Google 以後,發現真的是有問題:Don’t trust a string based on TryParse or IsNumeric result! (.Net/VBScript) | Computer Security Is My Interest!
但實驗結果跟該文章的結果不同:
1 True $10 False 1,,2,,,3,, True -10 True -10 True 10- True 1.00E+02 True %20%091 False 1%20%00%00 False %26hff False %0B%09%20-0001,,,,2.8e0002%09%20%0C%00%00 False %0B$%09%20(0001,,,,2.8e0002%09%20)%0C%00%00 False 看起來微軟也許有修正了,由於沒辦法比較作者的 VBScript 版本跟我的 VBScript 版本,我想還是自己用 regular expression 來擋會比較保險了。
驗證用程式:
' Please use cscript to run. dim strs, result strs = array( _ "1", _ "$10", _ "1,,2,,,3,,", _ "-10", _ "-10", _ "10-", _ "1.
Posts
C# Parallel.For / Python multiprocess
Parallel 可以並行處理,並無法跟 map() 畫上等號。這跟 Python 的 multiprocess 比較相似。
// c# Parallel.For example. using System; using System.Threading.Tasks; public class Program { public static void Main(string[] args) { Parallel.For(0, 5, i=> { // 表示從 0~4,共五次。 Console.WriteLine(i.ToString()); }); } } # Python multiprocess example. import multiprocessing def foo(i): print(i) if __name__ == '__main__': pool = Pool() result = pool.map(foo, range(4)) 參考資料: * Parallel Class (System.Threading.Tasks)”) * HOW TO:撰寫簡單的 Parallel.For 迴圈 * [C#]隨筆手扎 - Parallel & Lock - 非非碼不可- 點部落 * Python multiprocess
Posts
C# Select / Python map
c# 的 LINQ select 大略等同於 Python 的 map ,用法稍嫌麻煩。
using System; using System.Linq; using System.Collections.Generic; public class Proram { public static void Main(string[] args) { IEnumerable<int> values = new List<int>() {0, 1, 2, 3, 4}; var x = values.Select(i => { Console.WriteLine(i); return i; // 一定要傳回整數 }); foreach(var i in x) {} // 因為 Select 後的結果是 lazy 的,意即只有在真正去 iterate 時才會執行。 } } # Python map example. # 這邊使用了 __future__ ,因為在 Python 2 裡,print 是敘述,無法在 lambda 裡使用。 # 但在 Python 3 裡,print 是函式,因此可以 from __future__ import print_function values = range(5) map(lambda i: print(i), values) 參考資料: * 2.