多个python版本共存:把某一个版本的python.exe 和 pythonw.exe 重命名,后面加个数字。
一般在python文件开头写上这个:Python解释器会在解释文件的时候用,指定编码方式
#!/usr/bin/python
# -*- coding: utf-8 -*-
1. 文件和文件夹的操作
import os
#1. 复制文件
def copy_file(source_file, target_file):
if os.path.isfile(source_file):
# open函数返回file对象
# open完整参数有7个,一般都写上第一第二参数,后面需要的参数就用命名参数来指定
# 第一参数 文件名,第二参数 打开模式,后面比如命名参数encoding = '' 来指定编码格式。
# file对象的write写入字符串
# file对象的read读出字符串
open(target_file, "wb").write(open(source_file, "rb").read())
#2. 删除文件
def delete_file(filePath):
if os.path.isfile(filePath):
os.remove(filePath)
#3. 删除整个文件夹
def delete_dir(path):
if not os.path.exists(path):
return
if os.path.isfile(path):
return
for root, dirs, files in os.walk(path, topdown=False):
for f in files:
os.remove(os.path.join(root, f))
for folder in dirs:
os.rmdir(os.path.join(root, folder))
# os.rmdir() 方法用于删除指定路径的目录。仅当这文件夹是空的才可以, 否则, 抛出OSError。
os.rmdir(path)
#4. 合并文件夹 把source目录下的文件 合并到 target目录下。
def merge_dir(source_dir, target_dir):
# 列表遍历
for f in os.listdir(source_dir):
# f 有可能是文件也有可能是目录
# target_file 有可能存在,也有可能不存在
source_file = os.path.join(source_dir, f)
target_file = os.path.join(target_dir, f)
# 如果是文件,就拷贝
if os.path.isfile(source_file):
# 否定用not
if not os.path.exists(target_dir):
os.makedir(target_dir)
open(target_file, "wb").write(open(source_file, "rb").read())
# 如果是文件夹,继续递归
if os.path.isdir(source_file):
merge_dir(source_file, target_file)
#5. 返回类型以及文件名
def filetypeAndname(src):
if os.path.isfile(src):
index = src.rfind('\\')
if index == -1:
index = src.rfind('/')
return 'FILE', src[index+1:]
elif os.path.isdir(src):
return 'DIR', ''
#6. 移动文件 把source目录下以及子目录的文件 统一放到 target 根目录下。
#import shutil
def copy_files(source_dir, target_dir):
# 列表遍历
for f in os.listdir(source_dir):
# f 有可能是文件也有可能是目录
source_file = os.path.join(source_dir, f)
# 如果是文件,就拷贝
if os.path.isfile(source_file):
# 否定用not
if not os.path.exists(target_dir):
os.makedir(target_dir)
shutil.copy(source_file, target_dir)
# 如果是文件夹,继续递归
if os.path.isdir(source_file):
copy_files(source_file, target_dir)
ps: 对目录下的每个文件进行操作的常用模式,递归操作:
def dosomething_eachfile(dir):
for f in os.listdir(dir):
# f 有可能是文件也有可能是目录
file = os.path.join(dir, f)
# 如果是文件,就拷贝
if os.path.isfile(file):
#dosomething
# 如果是文件夹,继续递归
if os.path.isdir(file):
dosomething_eachfile(file)
2. shell命令
1.execute库
1)调用unity静态函数
from execute import execute_command
def build_unity_ios_assetBundle():
cmd = unity_execute_Path + " -batchmode -quit -logfile /dev/stdout -projectPath "\
+ unity_project_path + " -executeMethod CommandBuild.BuildiOSAssetBundle"
return execute_command(cmd, output_tag="Unity") == 0
-batchmode:命令行模式
-quit:关闭unityedtior当执行完命令
-logFile <pathname>:日志文件路径. If the path is ommitted, OSX and Linux will write output to the console. Windows uses the path %LOCALAPPDATA%\Unity\Editor\Editor.log as a default. (/dev/stdout 标准输出。shell中执行就是输出到shell窗口)
-projectPath <pathname>:unity工程路径
-executeMethod <ClassName.MethodName>:Editor文件夹下的静态函数,一打开Unity工程就执行
https://docs.unity3d.com/Manual/CommandLineArguments.html
2)增加文件执行权限
def update_xcode_other_file(path):
cmd = "chmod +x "+ path+ "/MapFileParser.sh"
if not execute_cmd(cmd):
print "chmod +x MapFileParser.sh fail"
cmd = "chmod +x "+ path+ "/MapFileParser"
if not execute_cmd(cmd):
print "chmod +x MapFileParser.sh fail"
权限对象 : 档案拥有者、群组、其他。u : 表示该档案的拥有者,g 表示与该档案的拥有者属于同一个群体(group)者,o 表示其他以外的人,a 表示这三者皆是。
权限种类: r读 w写 x执行
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=7。
权限设置符号:+ : 表示增加权限、- 表示取消权限、= 表示唯一设定权限。
chmod a=rwx file 相当于 chmod 777 file
chmod +x file 相当于 chmod a+x file
2.os库
os.system(),返回值为十进制数(分别对应一个16位的二进制数)。
该函数的返回值与 linux命令返回值两者的转换关系为:
转化成16二进制数,截取其高八位,然后转乘十进制数即为 linux命令返回值。(如果低位数是0的情况下,有关操作系统的错误码共 131个,所以低位都是零)
#jenkins调用脚本时需要先解锁钥匙串,此处为钥匙串密码
os.system("security unlock-keychain -p cc.com")
3.入口函数
def main():
#balabala
#balabala
#balabala
return True
if __name__ == '__main__':
main()
4.类:__getitem__ , __setitem__,__init__
__init__ 构造函数
class MyTime:
# 外面调用MyTime() 即调用这个函数
def __init__(self):
self.year = -1
self.month= -1
self.day = -1
self.hour = -1
def initWithList(self, list):
if len(list) == 4:
# 判断是不是int型
if type(list[0]) == type(1):
self.year = list[0]
self.month= list[1]
self.day = list[2]
self.hour = list[3]
def timeStamp(self):
timestr = [self.year,self.month,self.day,self.hour]
# 分隔符.join(列表) 把列表元素用分隔符连成字符串
return '-'.join(timestr)
5.判断是不是带BOM的utf-8格式
def IsUTF8WithBOM(file):
isWithBOM = false
BOM = b'\xef\xbb\xbf'
existBOM = lambda s: True if s == BOM else False
f = open(file, 'rb')
if existBOM (f.read(3)):
isWithBOM = true
f.close()
return isWithBOM
6.使用不同的编码方式打开文件
知道编码方式大部分都是utf16,个别文件是gbk。
如果想知道 提示的编码错误说某个位置,某个字节,用某种编码方式具体是个什么字符,可以用16进制编辑器打开文本查看。
def FileLines(file):
file_lines = []
try:
# file对象 readlines 返回列表
# 同理写入 file.writelines[列表]
file_lines = open(file, encoding = 'utf16').readlines()
except UnicodeDecodeError:
file_lines = open(file, encoding = 'gbk').readlines()
except:
file_lines = []
return file_lines
ps:try ....except...else 语句,当没有异常发生时,else中的语句将会被执行。
7.去除空行和注释
def RemoveComment(file_lines, filename):
f = open(filename, 'w')
for line in file_lines
# str.strip()去除前后的空格
line_tmp = line.strip()
# 1.len(str)字符串长度 2. str.startswith(ss)
# str.find(ss) 查找ss子串在不在str中,返回索引,找不到返回-1
if line_tmp.startswith('//') or not len(line_tmp)
continue
f.write(line)
f.close()
8.正则匹配Re模块
一些常用函数:
1.match( rule , targetString [,flag] ) 和 search( rule , targetString [,flag] ),返回一个MatchObject (如果匹配成功的话),如果匹配不成功,它们则返回一个NoneType。匹配到一个成功的,就不继续匹配了。所以在对匹配完的结果进行操作之前,你必需先判断一下是否匹配成功了。match从字符串的开头开始匹配,如果开头位置没有匹配成功,就算失败了;而search会跳过开头,继续向后寻找是否有匹配的字符串。
def findFirstSubName(filename):
file = open(filename).read()
# 1.不能是注释的 2.可以是GotoSub("XXX") 也可以是 Sub("XXX")
# 1.(?<!)前向非界定 2.*? 尽可能少的重复 3.使用括号()表示组
pattern1 = '(?<!\/\/)\s*?GotoSub\("(.*?)"\)'
pattern2 = '(?<!\/\/)\s*?Sub\("(.*?)"\)'
hasFound = re.search(pattern1, file)
# 判断是不是 NoneType 有没有找到
if hasFound:
# 用数字来取第一组 这里也只有一组
# group(0)代表整个匹配的子串;不填写参数时,返回group(0)
subname = hasFound.group(1)
else:
hasFound = re.search(pattern2, file)
if hasFound:
subname = hasFound.group(1)
else:
subname = None
return subname
2.split( rule , target [,maxsplit] ),切片函数。使用指定的正则规则在目标字符串中查找匹配的字符串,使用匹配字符串用作为分界,把字符串切片。
# 把文本内容解析成 subname 和 subcontent的字典 {subname:内容}
def BuildSubDict(filename):
file = open(filename).read()
# 按规则先切分内容(没有注释的文件了)
list_subcontent_raw = re.split('(?<!Goto)Sub\("(.*?)"\)\s*;\s*', file)
if len(list_subcontent_raw) <= 1:
return {}
# 列表从0开始索引,[1:]排除第0个 [-1]列表的最后一个元素
list_subcontent = list_subcontent_raw[1:]
# 找到所有的subname
pattern_subname = '(?<!Goto)Sub\("(.*?)"\)\s*;'
list_subname = re.findall(pattern_subname, file)
# 组成元组
subpair = zip(list_subname, list_subcontent )
# 组成字典
subdict = {name : content for(name,content) in subpair}
return subdict
findall(rule , target [,flag] ),返回一个列表,中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。
# {subname:内容中的其他sub名字的列表}
def BuildSubNameDict(subdict):
subnamedict = {}
# 遍历字典 subname是key
for subname in subdict
# str.split(seprate) 用seprate切分字符串
list_old = subdict[subname].split('\n')
list_new = []
list_pattern = ['GotoSub\(\s*"(.*?)"\s*\)',\
'SetSelectDlg\(\s*&.*?&\s*,\s*(.*?)\s*\)',\
'SetSelectDlgEx\(\s*&.*?&\s*,\s*(.*?)\s*,',\
'foreach\(.*?,\s*(.*?)\s*\)',\
'foreach_new\(.*?,\s*(.*?)\s*,']
# 遍历列表 line是列表元素
for line in list_old:
for pattern in list_pattern:
matched = re.findall(pattern, line)
# 空列表[] 空字典{} 都是False
if matched:
if matched [0] not in list_new:
list_new.append(matched [0])
break
subnamedict[subname] = list_new
在字符串找到第一组数字
def ReturnNumStr(source):
found = re.search('\d+', source)
if found:
numstr = found.group()
else:
numstr = ""
return numstr
一些分类:
功能字符 | ‘.’ ‘*’ ‘+’ ‘|’ ‘?’ ‘^’ ‘$’ ‘/’ 等 | 它们有特殊的功能含义。特别是’\’字符,它是转义引导符号,跟在它后面的字符一般有特殊的含义。 |
规则分界符 | ‘[‘ ‘]’ ‘(’ ‘)’ ‘{‘ ‘}’ 等 |
‘[‘ ‘]’ 字符集合设定符号,匹配包含在其中的任意一个字符 |
预定义转义字符集 | “\d” 数字 “\w”英文字母和数字 “\s”间隔符 等等 | 它们是以字符’\’开头,后面接一个特定字符的形式,用来指示一个预定义好的含义。一般大写就是小写的补集。 ps: \s = [ \r\n\t\v\f] 最前面有个空格。 \r : 回车CR (0D)。 \n:换行LF(0A)。 主流的操作系统一般使用CRLF或者LF作为其文本的换行符。其中,Windows 系统使用的是 CRLF, Unix系统(包括Linux, MacOS近些年的版本) 使用的是LF。 |
其它特殊功能字符 | ’#’ ‘!’ ‘:’ ‘-‘ 等 | 它们只在特定的情况下表示特殊的含义,比如(?# …)就表示一个注释,里面的内容会被忽略。 |
功能字符
| |
如果想限定它的有效范围,必需使用一个无捕获组 ‘(?: )’包起来。比如要匹配 ‘I have a dog’或’I have a cat’,需要写成r’I have a (?:dog|cat)’ ,而不能写成 r’I have a dog|cat’ |
* | 0或多次匹配:表示匹配前面的规则0次或多次。 |
+ | 1次或多次匹配:表示匹配前面的规则至少1次,可以多次匹配 |
? | 0或1次匹配:只匹配前面的规则0次或1次。 +? *? 尽可能少的重复匹配 >>> s= 'abbbaa' >>> re.findall( r'a.*?a' , s) ['abbba', 'aa'] >>> re.findall( r'a.*a' , s) ['abbbaa'] |
. | 匹配任意字符,除了换行符。 >>> s=’1 \n4 \n7’ >>> re.findall(r‘.’,s) ['1',' ','4',' ','7'] |
‘^’和’$’ | 匹配字符串开头和结尾,多行模式下匹配每行的开头和结尾。 >>> s= '12 34\n56 78\n90' >>> re.findall( r'^\d+' , s , re.M ) #匹配每行位于行首的数字,re.M多行模式 ['12', '56', '90'] >>> re.findall( r'\d+$' , s , re.M ) #匹配位于行尾的数字 ['34', '78', '90'] |
规则分界符以及其它特殊功能字符
(?<!) | 前向非界定:希望前面的字符串不是... 的内容时候才匹配。 |
(?:) | 无捕获组:当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时,你需要将这部分规则用’(?:’ ‘)’把它包围起来。 |
{m,n} | 匹配最少m次,最多n次。{m} 精确匹配m次 ,{m,} 大于等于m次{,n}, 小于等于n次 >>> s= ‘ 1 22 333 4444 55555 666666 ‘ >>> re.findall( r’\b\d{3}\b’ , s ) # a:3位数 ['333'] |
() |
分组 () 无命名组,只返回了包含在’()’中的内容。 (?P<name>…)’命名组,(?P=name) 通过名字调用已匹配的命名组 。 (/number) 通过序号调用已匹配的组。 >>> s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg' >>> re.findall( r'([a-z]+)\d+([a-z]+)' , s ) #无命名组,列表元素为元组 [('aaa', 'aaa'), ('fff', 'ggg')] >>> re.findall( r '(?P<g1>[a-z]+)/d+(?P=g1)' , s ) #找出被中间夹有数字的前后同样的字母 ['aaa'] |
{} |
预定义转义字符集
‘\A’和’\Z’ | 匹配字符串开头和结尾,在’M’模式下,它也不会匹配其它行的首尾。 |
\b (\B匹配非边界) |
它匹配一个单词的边界,比如空格等,不过它是一个‘0’长度字符,它匹配完的字符串不会包括那个分界的字符。 >>> s = 'abc abcde bc bcd' >>> re.findall( r’\bbc\b’ , s ) #匹配一个单独的单词 ‘bc’ ,而当它是其它单词的一部分的时候不匹配 ['bc'] #只找到了那个单独的’bc’ >>> re.findall( r’\sbc\s’ , s ) #匹配一个单独的单词 ‘bc’ [' bc '] # 只找到那个单独的’bc’,不过注意前后有两个空格,可能有点看不清楚 |
https://blog.csdn.net/smilelance/article/details/6529950
9.图搜索
图用字典存,key为某个node,value为这个node可以到达的其他node。
给出一个起始点node,和指定另外一个node,判断这个指定的那个node,能不能通过起始点node达到,如果能的话,给出路径即可,不需要最短。
def find_path(graphdict, extrance, target, path[]):
# 1.+:两个列表相加合并 2.[]字符串变列表
path = path + [extrance]
if extrance == target:
return path
# 判断key在不在字典中 判断子串在不在字符串中也可以用in, if substr in str
if target not in graphdict:
return None
# 遍历列表中的元素
for node in graphdict[extrance]:
if path and node not in path:
newpath = find_path(graphdict, node, target, path)
if newpath:
return newpath
return None
10. 重定向输出到文件
输出到文件中,后面使用print打印就都是输出到文件中了
# a是追加
f_handler = open(filename, 'w')
sys.stdout = f_handler
ps: windows console把标准输出重定向到一个文件中 command > filename
11.读入参数
1.命令行参数
import sys
#命令行输入: python 文件名 argv1 argv2 argv3
# 输入参数有4个,第0个参数是文件名
print('参数个数为:' + len(sys.argv) + '个参数。')
print('参数列表:' + str(sys.argv))
ps:读入的最后一个参数可能带有回车换行符号,所以在进行读取对比的时候进行strip()转换一下。
2.configparser库 配置文件
test.conf文件
[para1]
key1 = value1
key2 = value2
key3 = value3
[para2]
key1 = value1
key2 = value2
key3 = value3
读取文件
import configparser
cf = configparser.ConfigParser()
cf.read("test.conf")
var1 = cf.get("para1", "key1")
3.plistlib库 配置文件
test.plist文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ChannelList</key>
<array>
<string>IOSAppstore-dev-test</string>
<string>IOSAppstore-dev-official</string>
</array>
<key>ChannelConfig</key>
<dict>
<key>IOSAppstore-dev-test</key>
<dict>
<key>SettingFlags</key>
<dict>
<key>GCC_ENABLE_OBJC_EXCEPTIONS</key>
<string>YES</string>
</dict>
<key>BuildFlags</key>
<dict>
<key>ENABLE_BITCODE</key>
<string>NO</string>
<key>ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME</key>
<string>LaunchImage_dj</string>
</dict>
<key>OtherLDFlags</key>
<array>
<string>-ObjC</string>
<string>-lc++.1</string>
<string>-liconv</string>
<string>-lz</string>
</array>
<key>dylibs</key>
<array>
<string>libz</string>
<string>libstdc++.6.0.9</string>
<string>libsqlite3.0</string>
</array>
<key>Frameworks</key>
<array>
<string>Security</string>
<string>SystemConfiguration</string>
<string>JavaScriptCore</string>
<string>MobileCoreServices</string>
<string>CoreTelephony</string>
<string>CoreAudio</string>
<string>WebKit</string>
</array>
</dict>
<key>IOSAppstore-dev-official</key>
<dict>
<key>DependenceChannel</key>
<string>IOSAppstore-dev-test</string>
</dict>
</dict>
</dict>
</plist>
读取文件
global plistConfig
global dic_channel_config
global unity_build_lasttype
global current_channel_name
def read_plistConfig():
#读取配置文件
global plistConfig
global dic_channel_config
# 返回的是一个字典
plistConfig = plistlib.readPlist('test.plist')
return len(plistConfig) > 0
def build_channel():
# for element in list列表,plist中是array类型
for current_buildchannel in plistConfig["ChannelList"]:
global dic_channel_config
global current_channel_name
current_channel_name = current_buildchannel
# 可以返回多个参数
isFindChannel, dic_channel_config = getBuildingChannelConfig(current_buildchannel, {})
# buildchannelDic 不一定是空
# 因为有"DependenceChannel"这一项 如果找不到也算是没有找到
def getBuildingChannelConfig(buildchannel, buildchannelDic):
if buildchannel in plistConfig["ChannelConfig"]:
dic_channel_config = plistConfig["ChannelConfig"][current_channel]
if len(dic_channel_config) > 0:
for currentItem in dic_channel_config:
if currentItem not in buildchannelDic:
buildchannelDic[currentItem] = dic_channel_config[currentItem]
if "DependenceChannel" in dic_channel_config:
if dic_channel_config["DependenceChannel"] == buildchannel:
break;
return getBuildingChannelConfig(dic_channel_config["DependenceChannel"], buildchannelDic)
else:
return True, buildchannelDic
else:
break
return False, buildchannelDic
ps:
如果函数内需要修改全局变量var,需要在函数内先申明一下 global var。否则就是创建了一个 内部的局部变量var了。
python如果想使用作用域之外的全局变量,可以不加global,修改一定要先声明一下是 global。
12.一些内置函数:
1.range生成一个数值序列
13.一些常用库
1.time 时间相关
import time
def get_timestamp():
# time.localtime返回struct_time对象
# %Y 四位数的年份表示(000-9999)
# %m 月份(01-12)
# %d 月内中的一天(0-31)
# %H 24小时制小时数(0-23)
# %M 分钟数(00-59)
# %S 秒(00-59)
return time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))
2.压缩库 zipfile
import zipfile
def zip_dir(dirname, zipfilename):
filelist = []
if os.path.isfile(dirname):
filelist.append(dirname)
else :
for root, dirs, files in os.walk(dirname):
for name in files:
filelist.append(os.path.join(root, name))
zf = zipfile.ZipFile(zipfilename, "w", zipfile.zlib.DEFLATED)
for file in filelist:
# 取相对路径
arcname = file[len(dirname):]
zf.write(tar,arcname)
zf.close()