Python常用操作

多个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 )            # a3位数

['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()

 

猜你喜欢

转载自blog.csdn.net/u012138730/article/details/83010545