| perl (1987) | python (1991) |
基础 |
模块导入 | use strict; | import os, re, sys |
版本查看 | $ perl -v | $ python -V |
执行脚本 | $ perl foo.pl | $ python foo.py |
交互模式 | $ perl -de 0 | $ python |
执行语句 | $ perl -e 'print("hi\n")' | $ python -c "print('hi')" |
语句分隔 | ; | \n (newline) or ; |
语句块 | {} | Indent |
注释 | # comment | # comment |
多行注释 | =for comment line another line =cut | use triple quote string literal: '''comment line another line''' |
变量和操作符 |
赋值 | $v = 1; | v = 1 |
赋值 | ($x, $y, $z) = (1, 2, 3); # 3 is discarded: ($x, $y) = (1, 2, 3); # $z set to undef: ($x, $y, $z) = (1, 2); | x, y, z = 1, 2, 3 # raises ValueError: x, y = 1, 2, 3 # raises ValueError: x, y, z = 1, 2 |
交换 | ($x, $y) = ($y, $x); | x, y = y, x |
操作符 | += -= *= none /= %= **= .= x= &&= ||= ^= <<= >>= &= |= ^= | # do not return values: += -= *= /= //= %= **= += *= &= |= ^= <<= >>= &= |= ^= |
自增 | my $x = 1; my $y = ++$x; my $z = --$y; | none |
局部变量 | my $v; my (@a, %d); my $x = 1; my ($y, $z) = (2, 3); | # in function body: v = None a, d = [], {} x = 1 y, z = 2, 3 |
全局变量 | our ($g1, $g2) = (7, 8); sub swap_globals { ($g1, $g2) = ($g2, $g1); } | g1, g2 = 7, 8 def swap_globals(): global g1, g2 g1, g2 = g2, g1 |
常量 | use constant PI => 3.14; | # uppercase identifiers # constant by convention PI = 3.14 |
空 | undef | None |
空测试 | ! defined $v | v == None v is None |
访问未定义变量 | error under use strict; otherwise undef | raises NameError |
真假 | 1 "" | True False |
假 | undef 0 0.0 "" "0" () | False None 0 0.0 '' [] {} |
逻辑运算 | && || ! lower precedence: and or xor not | and or not |
条件 | $x > 0 ? $x : -$x | x if x > 0 else -x |
比较 | numbers only: == != > < >= <= strings: eq ne gt lt ge le | comparison operators are chainable: == != > < >= <= |
数学运算 |
类型转化 | 7 + "12" 73.9 + ".037" "value: " . 8 | 7 + int('12') 73.9 + float('.037') 'value: ' + str(8) |
算术运算 | + - * / none % ** | + - * / // % ** |
取余 | int ( 13 / 5 ) none | 13 // 5 q, r = divmod(13, 5) |
浮点除法 | 13 / 5 | float(13) / 5 # Python 3: 13 / 5 |
数学函数 | use Math::Trig qw( tan asin acos atan); sqrt exp log sin cos tan asin acos atan atan2 | from math import sqrt, exp, log, \ sin, cos, tan, asin, acos, atan, atan2 |
四舍五入 | # cpan -i Number::Format use Number::Format 'round'; use POSIX qw(ceil floor); int($x) round($x, 0) ceil($x) floor($x) abs($x) | import math int(x) int(round(x)) math.ceil(x) math.floor(x) abs(x) |
最大最小 | use List::Util qw(min max); min(1,2,3); max(1,2,3); @a = (1,2,3); min(@a); max(@a); | min(1,2,3) max(1,2,3) min([1,2,3]) max([1,2,3]) |
除0 | error | raises ZeroDivisionError |
大整数 | converted to float; use Math::BigInt to create arbitrary length integers | becomes arbitrary length integer of type long |
大浮点数 | inf | raises OverflowError |
随机数 | int(rand() * 100) rand() none | import random random.randint(0,99) random.random() random.gauss(0,1) |
随机数 | srand 17; my $sd = srand; srand($sd); | import random random.seed(17) sd = random.getstate() random.setstate(sd) |
位操作 | << >> & | ^ ~ | << >> & | ^ ~ |
其他进制 | 0b101010 052 0x2a | 0b101010 052 0x2a |
字符串操作 |
字符串 | "don't say \"no\"" 'don\'t say "no"' | 'don\'t say "no"' "don't say \"no\"" "don't " 'say "no"' '''don't say "no"''' """don't say "no\"""" |
多行字符串 | yes | triple quote literals only |
转义 | double quoted: \a \b \cx \e \f \n \r \t \xhh \x{hhhh} \ooo Perl 5.14: \o{ooo} single quoted: \' \\ | single and double quoted: \newline \\ \' \" \a \b \f \n \r \t \v \ooo \xhh Python 3: \uhhhh \Uhhhhhhhh |
变量替换 | my $count = 3; my $item = "ball"; print "$count ${item}s\n"; | count = 3 item = 'ball' print(‘%s %s’ % (count, item)) |
sprintf | my $fmt = "lorem %s %d %f"; sprintf($fmt, "ipsum", 13, 3.7) | 'lorem %s %d %f' % ('ipsum', 13, 3.7) fmt = 'lorem {0} {1} {2}' fmt.format('ipsum', 13, 3.7) |
here document | $word = "amet"; $s = <<EOF; lorem ipsum dolor sit $word EOF | ‘’’ ‘’’ |
字符串连接 | my $s = "Hello, "; my $s2 = $s . "World!"; | s = 'Hello, ' s2 = s + 'World!' juxtaposition can be used to concatenate literals: s2 = 'Hello, ' "World!" |
字符串复制 | my $hbar = "-" x 80; | hbar = '-' * 80 |
字符串分隔 | split(/\s+/, "do re mi fa") split(/\s+/, "do re mi fa", 2) split(/(\s+)/, "do re mi fa"); split(//, "abcd") | 'do re mi fa'.split() 'do re mi fa'.split(None, 1) re.split('(\s+)', 'do re mi fa') list('abcd') |
字符串连接 | join(" ", qw(do re mi fa)) | ' '.join(['do', 're', 'mi', 'fa']) |
字符串大小写 | uc("lorem") lc("LOREM") ucfirst("lorem") | 'lorem'.upper() 'LOREM'.lower() 'lorem'.capitalize() |
字符串strip | # cpan -i Text::Trim use Text::Trim; trim " lorem " ltrim " lorem" rtrim "lorem " | ' lorem '.strip() ' lorem'.lstrip() 'lorem '.rstrip() |
字符串格式化 | sprintf("%-10s", "lorem") sprintf("%10s", "lorem") | 'lorem'.ljust(10) 'lorem'.rjust(10) |
字符串长度 | length("lorem") | len('lorem') |
字符串index | index("lorem ipsum", "ipsum") rindex("do re re", "re") return -1 if not found | 'do re re'.index('re') 'do re re'.rindex('re') raise ValueError if not found |
子字符串 | substr("lorem ipsum", 6, 5) | 'lorem ipsum'[6:11] |
访问字符串中字母 | can't use index notation with strings: substr("lorem ipsum", 6, 1) | 'lorem ipsum'[6] |
字母数字转化 | chr(65) ord("A") | chr(65) ord('A') |
正则表达式 |
字符串或 | /lorem|ipsum/ qr(/etc/hosts) | re.compile('lorem|ipsum') none |
特殊字符 | char class abbrevs: . \d \D \h \H \s \S \v \V \w \W anchors: ^ $ \A \b \B \z \Z | char class abbrevs: . \d \D \s \S \w \W anchors: ^ $ \A \b \B \Z |
正则表达式匹配 | if ($s =~ /1999/) { print "party!\n"; } | if re.search('1999', s): print('party!') |
忽略大小写 | "Lorem" =~ /lorem/i | re.search('lorem', 'Lorem', re.I) |
选项 | i m s p x | re.I re.M re.S re.X |
替换 | my $s = "do re mi mi mi"; $s =~ s/mi/ma/g; | s = 'do re mi mi mi' s = re.compile('mi').sub('ma', s) |
group | $rx = qr/(\d{4})-(\d{2})-(\d{2})/; "2010-06-03" =~ $rx; ($yr, $mo, $dy) = ($1, $2, $3); | rx = '(\d{4})-(\d{2})-(\d{2})' m = re.search(rx, '2010-06-03') yr, mo, dy = m.groups() |
findall | my $s = "dolor sit amet"; @a = $s =~ m/\w+/g; | s = 'dolor sit amet' a = re.findall('\w+', s) |
匹配引用 | "do do" =~ /(\w+) \1/ my $s = "do re"; $s =~ s/(\w+) (\w+)/$2 $1/; | none rx = re.compile('(\w+) (\w+)') rx.sub(r'\2 \1', 'do re') |
日期时间 |
日期时间类型 | Time::Piece if use Time::Piece in effect, otherwise tm array | datetime.datetime |
当前日期时间 | use Time::Piece; my $t = localtime(time); my $utc = gmtime(time); | import datetime t = datetime.datetime.now() utc = datetime.datetime.utcnow() |
与epoch转化 | use Time::Local; use Time::Piece; my $epoch = timelocal($t); my $t2 = localtime(1304442000); | from datetime import datetime as dt epoch = int(t.strftime("%s")) t2 = dt.fromtimestamp(1304442000) |
当前epoch | $epoch = time; | import datetime t = datetime.datetime.now() epoch = int(t.strftime("%s")) |
strftime | use Time::Piece; $t = localtime(time); $fmt = "%Y-%m-%d %H:%M:%S"; print $t->strftime($fmt); | t.strftime('%Y-%m-%d %H:%M:%S') |
默认格式 | Tue Aug 23 19:35:19 2011 | 2011-08-23 19:35:59.411135 |
字符串转为时间strptime | use Time::Local; use Time::Piece; $s = "2011-05-03 10:00:00"; $fmt = "%Y-%m-%d %H:%M:%S"; $t = Time::Piece->strptime($s,$fmt); | from datetime import datetime s = '2011-05-03 10:00:00' fmt = '%Y-%m-%d %H:%M:%S' t = datetime.strptime(s, fmt) |
解析日期 | # cpan -i Date::Parse use Date::Parse; $epoch = str2time("July 7, 1999"); | # pip install python-dateutil import dateutil.parser s = 'July 7, 1999' t = dateutil.parser.parse(s) |
时间差 | Time::Seconds object if use Time::Piece in effect; not meaningful to subtract tm arrays | datetime.timedelta object |
时间运算 | use Time::Seconds; $now = localtime(time); $now += 10 * ONE_MINUTE() + 3; | import datetime delta = datetime.timedelta( minutes=10, seconds=3) t = datetime.datetime.now() + delta |
时区 | Time::Piece has local timezone if created withlocaltime and UTC timezone if created with gmtime; tm arrays have no timezone or offset info | a datetime object has no timezone information unless a tzinfo object is provided when it is created |
timezone name; offset from UTC; 是否夏令时 | # cpan -i DateTime use DateTime; use DateTime::TimeZone; $dt = DateTime->now(); $tz = DateTime::TimeZone->new( name=>"local"); $tz->name; $tz->offset_for_datetime($dt) / 3600; $tz->is_dst_for_datetime($dt); | import time tm = time.localtime() time.tzname[tm.tm_isdst] (time.timezone / -3600) + tm.tm_isdst tm.tm_isdst |
microseconds | use Time::HiRes qw(gettimeofday); ($sec, $usec) = gettimeofday; | t.microsecond |
sleep | a float argument will be truncated to an integer: sleep 1; | import time time.sleep(0.5) |
timeout | eval { $SIG{ALRM}= sub {die "timeout!";}; alarm 5; sleep 10; }; alarm 0; | import signal, time class Timeout(Exception): pass def timeout_handler(signo, fm): raise Timeout() signal.signal(signal.SIGALRM, timeout_handler) try: signal.alarm(5) time.sleep(10) except Timeout: pass signal.alarm(0) |
数组 |
定义 | @a = (1, 2, 3, 4); | a = [1, 2, 3, 4] |
quote words | @a = qw(do re mi); | none |
长度 | $#a + 1 or scalar(@a) | len(a) |
空测试 | !@a | not a |
使用 | $a[0] | a[0] |
更新 | $a[0] = "lorem"; | a[0] = 'lorem' |
越界访问 | @a = (); evaluates as undef: $a[10]; increases array size to 11: $a[10] = "lorem"; | a = [] raises IndexError: a[10] raises IndexError: a[10] = 'lorem' |
index | use List::Util 'first'; @a = qw(x y z w); $i = first {$a[$_] eq "y"} (0..$#a); | a = ['x', 'y', 'z', 'w'] i = a.index('y') |
子数组 | select 3rd and 4th elements: @a[2..3] splice(@a, 2, 2) | select 3rd and 4th elements: a[2:4] none |
子数组 | @a[1..$#a] | a[1:] |
添加删除 | @a = (6,7,8); push @a, 9; pop @a; | a = [6,7,8] a.append(9) a.pop() |
插入删除 | @a = (6,7,8); unshift @a, 5; shift @a; | a = [6,7,8] a.insert(0,5) a.pop(0) |
数组连接 | @a = (1,2,3); @a2 = (@a,(4,5,6)); push @a, (4,5,6); | a = [1,2,3] a2 = a + [4,5,6] a.extend([4,5,6]) |
初始化 | @a = (undef) x 10; | a = [None] * 10 a = [None for i in range(0, 10)] |
浅拷贝深拷贝 | use Storable 'dclone' my @a = (1,2,[3,4]); my $a2 = \@a; my @a3 = @a; my @a4 = @{dclone(\@a)}; | import copy a = [1,2,[3,4]] a2 = a a3 = list(a) a4 = copy.deepcopy(a) |
数组作为函数参数 | each element passed as separate argument; use reference to pass array as single argument | parameter contains address copy |
遍历 | for $i (1, 2, 3) { print "$i\n" } | for i in [1,2,3]: print(i) |
遍历 | none; use range iteration from 0 to $#a and use index to look up value in the loop body | a = ['do', 're', 'mi', 'fa'] for i, s in enumerate(a): print('%s at index %d' % (s, i)) |
range | for $i (1..1_000_000) { code } | range replaces xrange in Python 3: for i in xrange(1, 1000001): code |
range数组 | @a = 1..10; | a = range(1, 11) Python 3: a = list(range(1, 11)) |
翻转 | @a = (1,2,3); reverse @a; @a = reverse @a; | a = [1,2,3] a[::-1] a.reverse() |
排序 | @a = qw(b A a B); sort @a; @a = sort @a; sort { lc($a) cmp lc($b) } @a; | a = ['b', 'A', 'a', 'B'] sorted(a) a.sort() a.sort(key=str.lower) |
去重复 | use List::MoreUtils 'uniq'; my @a = (1,2,2,3); my @a2 = uniq @a; @a = uniq @a; | a = [1,2,2,3] a2 = list(set(a)) a = list(set(a)) |
是否存在于数组 | 7 ~~ @a | 7 in a |
集合交集 | | {1,2} & {2,3,4} |
集合或 | | {1,2} | {2,3,4} |
集合运算 | | {1,2,3} - {2} {1,2} ^ {2,3,4} |
map | map { $_ * $_ } (1,2,3) | map(lambda x: x * x, [1,2,3]) # or use list comprehension: [x*x for x in [1,2,3]] |
filter | grep { $_ > 1 } (1,2,3) | filter(lambda x: x > 1, [1,2,3]) # or use list comprehension: [x for x in [1,2,3] if x > 1] |
reduce | use List::Util 'reduce'; reduce { $x + $y } 0, (1,2,3) | # import needed in Python 3 only from functools import reduce reduce(lambda x, y: x+y, [1,2,3], 0) |
All/any | # cpan -i List::MoreUtils use List::MoreUtils qw(all any); all { $_ % 2 == 0 } (1,2,3,4) any { $_ % 2 == 0 } (1,2,3,4) | all(i%2 == 0 for i in [1,2,3,4]) any(i%2 == 0 for i in [1,2,3,4]) |
shuffle and sample | use List::Util 'shuffle'; @a = (1, 2, 3, 4); shuffle(@a); none | from random import shuffle, sample a = [1, 2, 3, 4] shuffle(a) sample(a, 2) |
zip | # cpan -i List::MoreUtils use List::MoreUtils 'zip'; @nums = (1, 2, 3); @lets = qw(a b c); # flat array of 6 elements: @a = zip @nums, @lets; | # array of 3 pairs: a = zip([1,2,3], ['a', 'b', 'c']) |
字典对象 |
定义 | %d = ( t => 1, f => 0 ); | d = { 't':1, 'f':0 } |
size | scalar(keys %d) | len(d) |
lookup | $d{"t"} | d['t'] |
out-of-bounds behavior | %d = (); evaluates as undef: $d{"lorem"}; adds key/value pair: $d{"lorem"} = "ipsum"; | d = {} raises KeyError: d['lorem'] adds key/value pair: d['lorem'] = 'ipsum' |
is key present | exists $d{"y"} | 'y' in d |
delete entry | %d = ( 1 => "t", 0 => "f" ); delete $d{1}; | d = {1: True, 0: False} del d[1] |
from array of pairs, from even length array | @a = (1,"a",2,"b",3,"c"); %d = @a; | a = [[1,'a'], [2,'b'], [3,'c']] d = dict(a) a = [1,'a',2,'b',3,'c'] d = dict(zip(a[::2], a[1::2])) |
merge | %d1 = (a=>1, b=>2); %d2 = (b=>3, c=>4); %d1 = (%d1, %d2); | d1 = {'a':1, 'b':2} d2 = {'b':3, 'c':4} d1.update(d2) # {'a': 1, 'c': 4, 'b': 3} |
invert | %to_num = (t=>1, f=>0); %to_let = reverse %to_num; | to_num = {'t':1, 'f':0} # dict comprehensions added in 2.7: to_let = {v:k for k, v in to_num.items()} |
iteration | while ( ($k, $v) = each %d ) { code } | for k, v in d.iteritems(): code Python 3: for k, v in d.items(): code |
keys and values as arrays | keys %d values %d | d.keys() d.values() Python 3: list(d.keys()) list(d.values()) |
default value, computed value | my %counts; $counts{'foo'} += 1 define a tied hash for computed values and defaults other than zero or empty string | from collections import defaultdict counts = defaultdict(lambda: 0) counts['foo'] += 1 class Factorial(dict): def __missing__(self, k): if k > 1: return k * self[k-1] else: return 1 factorial = Factorial() |
函数 |
函数申明 | sub add { $_[0] + $_[1] } sub add { my ($a, $b) = @_; $a + $b; } | def add(a, b): return a+b |
函数调用 | add(1, 2); parens are optional: add 1, 2; | add(1, 2) |
参数丢失 | set to undef | raises TypeError |
参数默认值 | sub my_log { my $x = shift; my $base = shift // 10; log($x)/log($base); } my_log(42); my_log(42, exp(1)); | import math def my_log(x, base=10): return math.log(x)/math.log(base) my_log(42) my_log(42, math.e) |
变长参数 | sub foo { if ( @_ >= 1 ) { print "first: $_[0]\n"; } if ( @_ >= 2 ) { print "last: $_[-1]\n"; } } | def foo(*a): if len(a) >= 1: print('first: ' + str(a[0])) if len(a) >= 2: print('last: ' + str(a[-1])) |
命名参数 | none | def fequal(x, y, **opts): eps = opts.get('eps') or 0.01 return abs(x - y) < eps fequal(1.0, 1.001) fequal(1.0, 1.001, eps=0.1**10) |
pass number or string by reference | sub foo { $_[0] += 1; $_[1] .= "ly"; } my $n = 7; my $s = "hard"; foo($n, $s); | not possible |
pass array or dictionary by reference | sub foo { $_[0][2] = 5; $_[1]{"f"} = -1; } my @a = (1,2,3); my %d = ("t"=> 1, "f" => 0); foo(\@a, \%d); | def foo(x, y): x[2] = 5 y['f'] = -1 a = [1,2,3] d = {'t':1, 'f':0} foo(a, d) |
return value | return arg or last expression evaluated | return arg or None |
multiple return values | sub first_and_second { return ($_[0], $_[1]); } @a = (1,2,3); ($x, $y) = first_and_second(@a); | def first_and_second(a): return a[0], a[1] x, y = first_and_second([1,2,3]) |
lambda declaration | $sqr = sub { $_[0] * $_[0] } | body must be an expression: sqr = lambda x: x * x |
lambda invocation | $sqr->(2) | sqr(2) |
function reference | my $func = \&add; | func = add |
function with private state | use feature state; sub counter { state $i = 0; ++$i; } print counter() . "\n"; | # state not private: def counter(): counter.i += 1 return counter.i counter.i = 0 print(counter()) |
closure | sub make_counter { my $i = 0; return sub { ++$i }; } my $nays = make_counter; print $nays->() . "\n"; | # Python 3: def make_counter(): i = 0 def counter(): nonlocal i i += 1 return i return counter nays = make_counter() |
generator | none | def make_counter(): i = 0 while True: i += 1 yield i nays = make_counter() print(nays.next()) |
decorator | | def logcall(f): def wrapper(*a, **opts): print('calling ' + f.__name__) f(*a, **opts) print('called ' + f.__name__) return wrapper @logcall def square(x): return x * x square(5) |
流程控制 |
if | if ( 0 == $n ) { print "no hits\n" } elsif ( 1 == $n ) { print "one hit\n" } else { print "$n hits\n" } | if 0 == n: print('no hits') elif 1 == n: print('one hit') else: print(str(n) + ' hits') |
switch | use feature 'switch'; given ($n) { when (0) { print "no hits\n"; } when (1) { print "one hit\n"; } default { print "$n hits\n"; } } | none |
while | while ( $i < 100 ) { $i++ } | while i < 100: i += 1 |
c-style for | for ( $i=0; $i <= 10; $i++ ) { print "$i\n"; } | none |
Foreach | @a = (1..5); foreach (@a) { print "$_\n"; } @a = (1..5); for (@a) { print "$_\n" } | a = ['do', 're', 'mi', 'fa'] for i, s in enumerate(a): print('%s at index %d' % (s, i)) for i in [1,2,3]: print(i) |
break, continue, redo | last next redo | break continue none |
control structure keywords | do else elsif for foreach goto if unless until while | elif else for if while |
what do does | executes following block and returns value of last statement executed | raises NameError unless a value was assigned to it |
statement modifiers | print "positive\n" if $i > 0; print "nonzero\n" unless $i == 0; | none |
raise exception | die "bad arg"; | raise Exception('bad arg') |
catch exception | eval { risky }; if ($@) { print "risky failed: $@\n"; } | try: risky() except: print('risky failed') |
global variable for last exception | $EVAL_ERROR: $@ $OS_ERROR: $! $CHILD_ERROR: $? | last exception: sys.exc_info()[1] |
define exception | none | class Bam(Exception): def __init__(self): super(Bam, self).__init__('bam!') |
catch exception by type | none | try: raise Bam() except Bam as e: print(e) |
finally/ensure | none | acquire_resource() try: risky() finally: release_resource() |
start thread | use threads; $func = sub { sleep 10 }; $thr = threads->new($func); | class sleep10(threading.Thread): def run(self): time.sleep(10) thr = sleep10() thr.start() |
wait on thread | $thr->join; | thr.join() |
文件和输出 |
print to standard output | print "Hello, World!\n"; | print('Hello, World!') |
read from standard input | $line = <STDIN>; | line = sys.stdin.readline() |
standard file handles | STDIN STDOUT STDERR | sys.stdin sys.stdout sys.stderr |
open file | open my $f, "/etc/hosts"; or open FILE, "/etc/hosts"; | f = open('/etc/hosts') |
open file for writing | open my $f, ">/tmp/perl_test"; or open FILE, ">/tmp/perl_test"; | f = open('/tmp/test', 'w') |
open file for append | | with open('/tmp/test') as f: f.write('lorem ipsum\n') |
close file | close $f; or close FILE; | f.close() |
read line | $line = <$f>; or $line = <FILE>; | f.readline() |
iterate over file by line | while ($line = <$f>) { | for line in f: |
chomp | chomp $line; | line = line.rstrip('\r\n') |
read entire file into array or string | @a = <$f>; $s = do { local $/; <$f> }; | a = f.readlines() s = f.read() |
write to file | print $f "lorem ipsum"; | f.write('lorem ipsum') |
flush file handle | use IO::Handle; $f->flush(); | f.flush() |
file test, regular file test | If (-e "/etc/hosts") {print exist;} -f "/etc/hosts" | os.path.exists('/etc/hosts') os.path.isfile('/etc/hosts') |
copy file, remove file, rename file | use File::Copy; copy("/tmp/foo", "/tmp/bar"); unlink "/tmp/foo"; move("/tmp/bar", "/tmp/foo"); unlink(); | import shutil shutil.copy('/tmp/foo', '/tmp/bar') os.remove('/tmp/foo') shutil.move('/tmp/bar', '/tmp/foo') os.remove() |
set file permissions | chmod 0755, "/tmp/foo"; | os.chmod('/tmp/foo', 0755) |
temporary file | use File::Temp; $f = File::Temp->new(); print $f "lorem ipsum\n"; close $f; print "tmp file: "; print $f->filename . "\n"; | import tempfile f = tempfile.NamedTemporaryFile( prefix='foo') f.write('lorem ipsum\n') f.close() print("tmp file: %s" % f.name) |
in memory file | my ($f, $s); open($f, ">", \$s); print $f "lorem ipsum\n"; $s; | from StringIO import StringIO f = StringIO() f.write('lorem ipsum\n') s = f.getvalue() Python 3 moved StringIO to the io module |
目录操作 |
build pathname | use File::Spec; File::Spec->catfile("/etc", "hosts") | os.path.join('/etc', 'hosts') |
dirname and basename | use File::Basename; print dirname("/etc/hosts"); print basename("/etc/hosts"); | os.path.dirname('/etc/hosts') os.path.basename('/etc/hosts') |
absolute pathname | use Cwd; Cwd::abs_path("..") | os.path.abspath('..') |
iterate over directory by file | use File::Basename; while ( </etc/*> ) { print basename($_) . "\n"; } | for filename in os.listdir('/etc'): print(filename) |
make directory | use File::Path 'make_path'; make_path "/tmp/foo/bar"; | dirname = '/tmp/foo/bar' if not os.path.isdir(dirname): os.makedirs(dirname) |
recursive copy | # cpan -i File::Copy::Recursive use File::Copy::Recursive 'dircopy'; dircopy "/tmp/foodir", "/tmp/bardir"; | import shutil shutil.copytree('/tmp/foodir', '/tmp/bardir') |
remove empty directory | rmdir "/tmp/foodir"; | os.rmdir('/tmp/foodir') |
remove directory and contents | use File::Path 'remove_tree'; remove_tree "/tmp/foodir"; | import shutil shutil.rmtree('/tmp/foodir') |
directory test | -d "/tmp" | os.path.isdir('/tmp') |
命令行操作 |
command line args, script name | scalar(@ARGV) $ARGV[0] $ARGV[1] etc $0 | len(sys.argv)-1 sys.argv[1] sys.argv[2] etc sys.argv[0] |
getopt | use Getopt::Long; my ($src, $help); sub usage { print "usage: $0 --f SRC\n"; exit -1; } GetOptions("file=s" => \$src, "help" => \$help); usage if $help; | import argparse parser = argparse.ArgumentParser() parser.add_argument('--file', '-f', dest='file') args = parser.parse_args() src = args.file |
get and set environment variable | $ENV{"HOME"} $ENV{"PATH") = "/bin"; | os.getenv('HOME') os.environ['PATH'] = '/bin' |
exit | exit 0; | sys.exit(0) |
set signal handller | $SIG{INT} = sub { die "exiting…\n"; }; | import signal def handler(signo, frame): print('exiting…') exit -1 signal.signal(signal.SIGINT, handler) |
executable test | -x "/bin/ls" | os.access('/bin/ls', os.X_OK) |
external command | system("ls -l /tmp") == 0 or die "ls failed"; | if os.system('ls -l /tmp'): raise Exception('ls failed') |
escaped external command | $path = <>; chomp($path); system("ls", "-l", $path) == 0 or die "ls failed"; | import subprocess cmd = ['ls', '-l', '/tmp'] if subprocess.call(cmd): raise Exception('ls failed') |
backticks | my $files = `ls -l /tmp`; or my $files = qx(ls); | import subprocess cmd = ['ls', '-l', '/tmp'] files = subprocess.check_output(cmd) |
__________________________________________ |