no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Previous revisionLast revision | |||
— | devwiki:python [2024/03/21 08:53] – [Online Python run] ying | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | |||
+ | |||
+ | ====== Modern Python Practice ====== | ||
+ | |||
+ | * nowaday, now one use python 2.x anymore, use python 3 standard, use this | ||
+ | * use pathlib instead of os.path | ||
+ | * use f" | ||
+ | |||
+ | |||
+ | ====== Online Python run ====== | ||
+ | |||
+ | * https:// | ||
+ | * to install locally: < | ||
+ | |||
+ | ====== Install related ====== | ||
+ | ===== install Python3 on mac ===== | ||
+ | |||
+ | * Mac has its own python install, very old, only for basic usage | ||
+ | * to install Python3 from official python website, | ||
+ | - download python 3 for mac installer | ||
+ | - install as usual and done | ||
+ | - run python3 in cmd | ||
+ | - then it pops: " | ||
+ | - if you already install XCode (the developer suite for mac), then no need; if not, you can just install the smaller " | ||
+ | - go Apple developer downloads page, search command line tools for xcode, download that and install | ||
+ | |||
+ | ===== Manage and handle multiple versions of python case ===== | ||
+ | |||
+ | Situation: | ||
+ | * sometimes, you may have to keep both python 2.7, python 3.x | ||
+ | * and sometimes you want to try python with AI, and AI need to install tons of AI related python modules | ||
+ | * sometimes you just to keep python module in the min form to test something | ||
+ | |||
+ | Solution: | ||
+ | * for those case, when install python, never add python to system path | ||
+ | * just download and make python folder a portable folder (you can install and copy the python whole folder to other machine as a portable app, better zip to copy, faster) | ||
+ | * then your computer cmd never know where is python and won't random get your python from somewhere | ||
+ | * then, dynamically set python into python in cmd session or batch file, or use full path to python.exe to run your script | ||
+ | * session based method (win as example) <code dos>SET PATH=D: | ||
+ | * batch file method <code dos test.batch> | ||
+ | @echo off | ||
+ | SetLocal EnableDelayedExpansion | ||
+ | set CustPython=D: | ||
+ | call !CustPython!python.exe my_script.py | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====== Python 3 Changes and How to Make 2.7 Code Works ====== | ||
+ | |||
+ | * make print "" | ||
+ | # in code editor, using Regular Expression to replace | ||
+ | find: (print)\s(.+) | ||
+ | replace: $1\($2\) or \1(\2) depending on your code editor | ||
+ | </ | ||
+ | * other stuff <code python> | ||
+ | # python 2 reload | ||
+ | reload(myModule) | ||
+ | # python 3 reload | ||
+ | from imp import reload | ||
+ | reload(myModule) | ||
+ | |||
+ | # python 2 execfile | ||
+ | execfile(" | ||
+ | # python 3 | ||
+ | exec(open(" | ||
+ | </ | ||
+ | |||
+ | * make compatible to python 3 <code python> | ||
+ | if sys.version_info[: | ||
+ | import importlib | ||
+ | reload = importlib.reload # add reload | ||
+ | raw_input = input # add raw_input | ||
+ | xrange = range # range | ||
+ | long = int # int | ||
+ | unicode = str # str | ||
+ | </ | ||
+ | |||
+ | * integer division difference in py3 vs py2, a/b | ||
+ | * ref: https:// | ||
+ | * for safe, use < | ||
+ | 35// | ||
+ | |||
+ | 35/60 = 0.583 #py3 | ||
+ | 35//60 = 0 # py3 | ||
+ | </ | ||
+ | |||
+ | ====== Python basics ====== | ||
+ | |||
+ | * online python code runner: https:// | ||
+ | * Python download: http:// | ||
+ | * a cool python shell: http:// | ||
+ | |||
+ | ** My Wiki Page related** | ||
+ | * how to publish Python script as standalone application: | ||
+ | * My App code share: [[devwiki: | ||
+ | * My Python GUI code template: [[devwiki: | ||
+ | |||
+ | ** to read: ** | ||
+ | * https:// | ||
+ | * Code Like a Pythonista: Idiomatic Python http:// | ||
+ | |||
+ | ===== Python vs . ===== | ||
+ | |||
+ | * Python vs Swift | ||
+ | * https:// | ||
+ | |||
+ | ===== Python Comment Tips ===== | ||
+ | |||
+ | * single line comment <code python># single comment</ | ||
+ | * multiple line comment <code python>''' | ||
+ | line 1 | ||
+ | line 2 | ||
+ | ''' | ||
+ | </ | ||
+ | * block, section, partition <code python> | ||
+ | |||
+ | ######################################## | ||
+ | # a major block of asset (40x#) | ||
+ | ######################################## | ||
+ | | ||
+ | # | ||
+ | # a function collection (30x-) | ||
+ | # | ||
+ | |||
+ | # ---- section comment ---- | ||
+ | |||
+ | # function section tip | ||
+ | def ________Loading_Functions________(): | ||
+ | # 8x_ | ||
+ | pass | ||
+ | </ | ||
+ | ===== Launch Python script ===== | ||
+ | |||
+ | * launch in windows command batch file next to it<code batch> | ||
+ | call python %~dp0\\MyPythonScript.py</ | ||
+ | * launch in Mac AppleScript file (wip)< | ||
+ | set myScriptPath to path to me | ||
+ | set myScriptFolderPath to POSIX path of (container of myScriptPath as string) -- in "/" | ||
+ | set myScriptName to name of myScriptPath | ||
+ | |||
+ | tell application " | ||
+ | do script with command " | ||
+ | end tell | ||
+ | </ | ||
+ | ===== OS system operation ===== | ||
+ | |||
+ | * get user/home folder <code python> | ||
+ | os.path.expanduser(' | ||
+ | os.getenv(" | ||
+ | os.getenv(" | ||
+ | </ | ||
+ | |||
+ | * make python code able to print unicode directly without .encode(' | ||
+ | import codecs | ||
+ | sys.stdout = codecs.getwriter(' | ||
+ | </ | ||
+ | * get python program path< | ||
+ | print(sys.executable) # the python cmd or app containing the python call path | ||
+ | </ | ||
+ | * get python module path <code python> | ||
+ | os.path.dirname(ModuleName.__file__) | ||
+ | </ | ||
+ | * get script path <code python> | ||
+ | * get class path but not its super class <code python> | ||
+ | self.location = os.path.realpath(sys.modules[self.__class__.__module__].__file__) | ||
+ | self.location = os.path.abspath(inspect.getfile(self.__class__)) | ||
+ | </ | ||
+ | * get class name <code python> | ||
+ | * get basename of folder and file <code python> | ||
+ | * get file name without extension <code python> | ||
+ | file_name = os.path.basename(file_path).rsplit(' | ||
+ | import pathlib | ||
+ | file_name_2 = pathlib.Path(file_path).stem | ||
+ | </ | ||
+ | * get expanded and un-symbolic path <code python> | ||
+ | os.path.abspath(__file__) | ||
+ | os.path.realpath(__file__) | ||
+ | </ | ||
+ | * path comparison <code python> | ||
+ | os.path.relpath(childPath, | ||
+ | os.path.commonprefix(list_of_paths) # get the common parent path of all input pathes | ||
+ | </ | ||
+ | * python code to detect platform, python version, bit <code python> | ||
+ | from sys import platform | ||
+ | |||
+ | def get_platform(): | ||
+ | if platform.startswith(' | ||
+ | return ' | ||
+ | elif platform.startswith(' | ||
+ | return ' | ||
+ | return ' | ||
+ | |||
+ | import sys | ||
+ | pyMode = ' | ||
+ | print(" | ||
+ | |||
+ | is_64bits = sys.maxsize > 2**32 | ||
+ | print(is_64bits) | ||
+ | </ | ||
+ | * check file and path exists< | ||
+ | * scan file and folder content with pattern filtering <code python> | ||
+ | result_list = [x for x in os.listdir(scanPath) if os.path.isdir(os.path.join(scanPath, | ||
+ | # isdir for folder, isfile for file | ||
+ | cur_pattern = re.compile(' | ||
+ | result_list = [x for x in result_list if cur_pattern.match(x)] | ||
+ | |||
+ | # jpg name example | ||
+ | jpg_list = [x.rsplit(' | ||
+ | </ | ||
+ | * rename file or folder <code python> | ||
+ | * move file (always use full path for safe, and always check source and target exist before operation)< | ||
+ | # file move within same drive | ||
+ | os.rename("/ | ||
+ | os.replace("/ | ||
+ | # work for folder and file and cross disk drive | ||
+ | shutil.move("/ | ||
+ | </ | ||
+ | |||
+ | * system cmds for each os<code python> | ||
+ | os.system(' | ||
+ | os.system(' | ||
+ | </ | ||
+ | * cross-platform delivery from source | ||
+ | * win: frozen | ||
+ | * mac: frozen | ||
+ | * lin: packaged | ||
+ | * <code python> | ||
+ | def getSetup(): | ||
+ | if hasattr(sys, | ||
+ | return ' | ||
+ | elif is_packaged(): | ||
+ | return ' | ||
+ | return ' | ||
+ | </ | ||
+ | * change file permission <code python> | ||
+ | # ref: http:// | ||
+ | import os | ||
+ | import stat | ||
+ | os.chmod(" | ||
+ | </ | ||
+ | * windows register operation <code python> | ||
+ | PS_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE," | ||
+ | PS_APP = _winreg.QueryValueEx(PS_key, | ||
+ | |||
+ | def ps_loc_win(): | ||
+ | import _winreg | ||
+ | regKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, | ||
+ | regPath = _winreg.QueryValueEx(regKey, | ||
+ | return regPath | ||
+ | </ | ||
+ | |||
+ | * windows set default playback device <code python> | ||
+ | |||
+ | * run python script itself as admin <code python> | ||
+ | import ctypes, sys | ||
+ | def is_admin(): | ||
+ | try: | ||
+ | return ctypes.windll.shell32.IsUserAnAdmin() | ||
+ | except: | ||
+ | return False | ||
+ | |||
+ | if is_admin(): | ||
+ | # Code of your program here | ||
+ | else: | ||
+ | # Re-run the program with admin rights | ||
+ | ctypes.windll.shell32.ShellExecuteW(None, | ||
+ | </ | ||
+ | * run cmd with admin (3rd party module) <code python> | ||
+ | # pywin32 : sourceforge.net/ | ||
+ | import win32com.shell.shell as shell | ||
+ | commands = 'echo hi' | ||
+ | shell.ShellExecuteEx(lpVerb=' | ||
+ | </ | ||
+ | |||
+ | * control, start, stop, restart service (3rd party module method) <code python> | ||
+ | import win32serviceutil | ||
+ | serviceName = " | ||
+ | win32serviceutil.RestartService(serviceName) | ||
+ | </ | ||
+ | |||
+ | ==== List File and sub-folders - the Correct Way ==== | ||
+ | |||
+ | * in Python 3.5, scandir module is part of python, also inside os.walk() internal instead of os.listdir() old way. | ||
+ | * so compare glob, python 2.7 os.walk() and scandir (also available as external module for previous python) | ||
+ | * scandir is at least 10x faster than old os.walk, glob is 2x faster than old os.walk by skipping dir/file type checking | ||
+ | * 132s (walk) / 62s (glob) / 12s (scandir) | ||
+ | |||
+ | <code python> | ||
+ | import glob | ||
+ | def getDirData(top, | ||
+ | res = [] | ||
+ | for d in range( 1, maxDepth+2 ): | ||
+ | maxGlob = "/" | ||
+ | topGlob = os.path.join( top, maxGlob ) | ||
+ | allFiles = glob.glob( topGlob ) | ||
+ | res.extend( allFiles ) | ||
+ | # | ||
+ | return res | ||
+ | |||
+ | import os | ||
+ | def getDirData( top, maxDepth=1): | ||
+ | # ref: https:// | ||
+ | # py3 option: better with scandir, | ||
+ | # py2 has: https:// | ||
+ | top = os.path.normpath(top) | ||
+ | res = [] | ||
+ | root_len = len(top) # | ||
+ | for root, | ||
+ | depth = root[root_len: | ||
+ | if depth < maxDepth: | ||
+ | res += [os.path.join(root, | ||
+ | res += [os.path.join(root, | ||
+ | elif depth == maxDepth: | ||
+ | res += [os.path.join(root, | ||
+ | res += [os.path.join(root, | ||
+ | dirs[:] = [] # Don't recurse any deeper | ||
+ | return res | ||
+ | |||
+ | # detail inf: https:// | ||
+ | # can use with maya 2017 by zip out _scandir.pyd and scandir.py: (scandir-1.10.0-cp27-cp27m-win_amd64.whl) https:// | ||
+ | tmp_path = r' | ||
+ | tmp_path in sys.path or sys.path.append(tmp_path) | ||
+ | import scandir | ||
+ | def getDirData(top, | ||
+ | # py3.5 has built in, only for 2.7 | ||
+ | # https:// | ||
+ | top = os.path.normpath(top) | ||
+ | res = [] | ||
+ | root_len = len(top)# | ||
+ | for root, | ||
+ | depth = root[root_len: | ||
+ | if depth < maxDepth: | ||
+ | res += [os.path.join(root, | ||
+ | res += [os.path.join(root, | ||
+ | elif depth == maxDepth: | ||
+ | res += [os.path.join(root, | ||
+ | res += [os.path.join(root, | ||
+ | dirs[:] = [] # Don't recurse any deeper | ||
+ | return res | ||
+ | | ||
+ | # test | ||
+ | import time | ||
+ | start = time.time() | ||
+ | result = getDirData(r' | ||
+ | end = time.time() | ||
+ | print(' | ||
+ | </ | ||
+ | * other module option: https:// | ||
+ | |||
+ | ==== Copy File - the Correct Way ==== | ||
+ | |||
+ | * speed on windows: SHFileOperation (8) > win32file (8.6) > os System (9) > shutil (18) | ||
+ | * ref: http:// | ||
+ | |||
+ | * use python shutil module copy, copyfile and copy2 function <code python> | ||
+ | import shutil | ||
+ | # copy: return target path, target can be file or folder | ||
+ | shutil.copy(' | ||
+ | shutil.copyfile(' | ||
+ | |||
+ | ''' | ||
+ | 02/ | ||
+ | 12/ | ||
+ | 12/ | ||
+ | ''' | ||
+ | |||
+ | shutil.copy2(' | ||
+ | ''' | ||
+ | 02/ | ||
+ | 02/ | ||
+ | ''' | ||
+ | </ | ||
+ | * copy folder and its content <code python> | ||
+ | import shutil, errno | ||
+ | |||
+ | def copyFolder(src, | ||
+ | try: | ||
+ | shutil.copytree(src, | ||
+ | except OSError as exc: # python >2.5 | ||
+ | if exc.errno == errno.ENOTDIR: | ||
+ | shutil.copy2(src, | ||
+ | else: raise | ||
+ | | ||
+ | # or use this | ||
+ | distutils.dir_util.copy_tree(src_folder, | ||
+ | </ | ||
+ | * python more complete version for copy folder and its content <code python> | ||
+ | # ref: http:// | ||
+ | # folder content to target folder content. created folders seams not same date, but file same date | ||
+ | import os | ||
+ | import shutil | ||
+ | def copy_tree(src, | ||
+ | names = os.listdir(src) | ||
+ | if not os.path.isdir(dst): | ||
+ | os.makedirs(dst) | ||
+ | errors = [] | ||
+ | for name in names: | ||
+ | srcname = os.path.join(src, | ||
+ | dstname = os.path.join(dst, | ||
+ | try: | ||
+ | if symlinks and os.path.islink(srcname): | ||
+ | linkto = os.readlink(srcname) | ||
+ | os.symlink(linkto, | ||
+ | elif os.path.isdir(srcname): | ||
+ | copy_tree(srcname, | ||
+ | else: | ||
+ | # perform overrides | ||
+ | if os.path.isdir(dstname): | ||
+ | os.rmdir(dstname) | ||
+ | elif os.path.isfile(dstname): | ||
+ | os.remove(dstname) | ||
+ | shutil.copy2(srcname, | ||
+ | # other case like: devices, sockets etc. | ||
+ | except (IOError, os.error) as why: | ||
+ | errors.append((srcname, | ||
+ | # catch the Error from the recursive copy_tree so that we can | ||
+ | # continue with other files | ||
+ | except OSError as err: | ||
+ | errors.extend(err.args[0]) | ||
+ | try: | ||
+ | shutil.copystat(src, | ||
+ | except WindowsError: | ||
+ | # can't copy file access times on Windows | ||
+ | pass | ||
+ | except OSError as why: | ||
+ | errors.extend((src, | ||
+ | if errors: | ||
+ | raise Error(errors) | ||
+ | |||
+ | copy_tree(' | ||
+ | </ | ||
+ | * use system command to copy <code python> | ||
+ | src = ' | ||
+ | tgt = ' | ||
+ | os.system(' | ||
+ | # normpath will change the slash for win from unix path | ||
+ | |||
+ | os.system (" | ||
+ | </ | ||
+ | * use system file manager to copy with system progress window (windows) <code python> | ||
+ | #ref: https:// | ||
+ | import pythoncom | ||
+ | from win32com.shell import shell, | ||
+ | |||
+ | def win_copy_process(src_files, | ||
+ | # win32com module | ||
+ | pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation, | ||
+ | # Respond with Yes to All for any dialog | ||
+ | # ref: http:// | ||
+ | pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION) | ||
+ | # Set the destionation folder | ||
+ | dst = shell.SHCreateItemFromParsingName(tgt_folder, | ||
+ | for f in src_files: | ||
+ | src = shell.SHCreateItemFromParsingName(f, | ||
+ | pfo.CopyItem(src, | ||
+ | # ref: http:// | ||
+ | success = pfo.PerformOperations() | ||
+ | # ref: sdn.microsoft.com/ | ||
+ | aborted = pfo.GetAnyOperationsAborted() | ||
+ | return success and not aborted | ||
+ | |||
+ | file_list = [r' | ||
+ | tgt_folder = r' | ||
+ | win_copy_process(file_list, | ||
+ | </ | ||
+ | * use system API (windows) <code python> | ||
+ | # | ||
+ | # win32 | ||
+ | from win32com.shell import shell, shellcon | ||
+ | win32file.CopyFile (filename1, filename2, 1) | ||
+ | |||
+ | # win32com : with windows copy dialog | ||
+ | shell.SHFileOperation ( (0, shellcon.FO_COPY, | ||
+ | # for the " | ||
+ | # shellcon.FOF_RENAMEONCOLLISION: | ||
+ | # shellcon.FOF_NOCONFIRMATION: | ||
+ | # shellcon.FOF_NOERRORUI: | ||
+ | # shellcon.FOF_SILENT: | ||
+ | # shellcon.FOF_NOCONFIRMMKDIR: | ||
+ | </ | ||
+ | |||
+ | ===== string operation ===== | ||
+ | |||
+ | * encode and decode Qt QString <code python> | ||
+ | unicode(myQStringObj) # unicode output | ||
+ | unicode(myQStringObj.toUtf8(), | ||
+ | </ | ||
+ | * ref: | ||
+ | * UTF-8 is an encoding used to translate numbers into binary data. | ||
+ | * Unicode is a character set used to translate characters into numbers. | ||
+ | * text block to clean row list <code python> | ||
+ | data_list = [row.strip() for row in source_txt.split(' | ||
+ | </ | ||
+ | |||
+ | * to use non-ascii character in python file, you need to put encoding in first line of code, or you will get " | ||
+ | # coding: utf-8 | ||
+ | my_special_string = u" | ||
+ | print(u" | ||
+ | </ | ||
+ | * remove extra space from a string, also remove end single space< | ||
+ | tidy_name = ' ' | ||
+ | |||
+ | # just remove extra space | ||
+ | tidy_name = re.sub(' | ||
+ | tidy_name = re.sub(' | ||
+ | </ | ||
+ | ===== control flow operation ===== | ||
+ | |||
+ | * define function <code python> | ||
+ | def my_fun(para1): | ||
+ | print para1 | ||
+ | </ | ||
+ | * logic and condition and loop operation <code python> | ||
+ | print tmpitem | ||
+ | |||
+ | if tmp > 0: | ||
+ | print ' | ||
+ | elif x == 0: | ||
+ | print ' | ||
+ | else: | ||
+ | print ' | ||
+ | |||
+ | # logic operation | ||
+ | x or y | ||
+ | x and y | ||
+ | not x | ||
+ | </ | ||
+ | * try operation, note try is not a block, variable is same scope before try <code python> | ||
+ | try: | ||
+ | val = test(A) | ||
+ | except: | ||
+ | pass | ||
+ | # ref: https:// | ||
+ | </ | ||
+ | ===== data operation ===== | ||
+ | |||
+ | * data type check <code python> | ||
+ | isinstance(Vehicle(), | ||
+ | type(Vehicle()) == Vehicle | ||
+ | isinstance(Truck(), | ||
+ | type(Truck()) == Vehicle | ||
+ | |||
+ | # check string, both python 2,3 | ||
+ | isinstance(my_data, | ||
+ | # check list | ||
+ | isinstance(my_data, | ||
+ | |||
+ | # check not None, note, None is its own type and has only one instance | ||
+ | my_vec != None # sometime, it may cause error when = try to read certain way | ||
+ | my_vec is not None # this way is preferred to be error free | ||
+ | isinstance(my_vec, | ||
+ | |||
+ | # compare type | ||
+ | if type(A) is type(B): | ||
+ | print(' | ||
+ | | ||
+ | # note : is for same object and like pointer comparision, | ||
+ | </ | ||
+ | |||
+ | * data type convertion <code python> | ||
+ | str(42) | ||
+ | </ | ||
+ | * get datetime date <code python> | ||
+ | * get processing time <code python> | ||
+ | import time | ||
+ | |||
+ | start = time.time() | ||
+ | print(" | ||
+ | end = time.time() | ||
+ | print(end - start) | ||
+ | </ | ||
+ | * wild char process <code python> | ||
+ | import glob | ||
+ | os.chdir(path) | ||
+ | for file in glob.glob(" | ||
+ | print file | ||
+ | | ||
+ | tmplist=glob.glob(' | ||
+ | |||
+ | # other method: fnmatch and re | ||
+ | </ | ||
+ | * string operation <code python> | ||
+ | name=" | ||
+ | print name[3: | ||
+ | |||
+ | len(str) # string length | ||
+ | |||
+ | "hello world" | ||
+ | 'Hello World' | ||
+ | |||
+ | # remove Whitespace on the both sides: | ||
+ | s = " | ||
+ | s = s.strip() | ||
+ | |||
+ | # remove Whitespace on the right side: | ||
+ | s = s.rstrip() | ||
+ | # remove Whitespace on the left side: | ||
+ | s = s.lstrip() | ||
+ | </ | ||
+ | |||
+ | Data Type | ||
+ | * Lists []: a list of values. Each one of them is numbered, starting from zero - the first one is numbered zero, the second 1, the third 2, etc. You can remove values from the list, and add new values to the end. Example: Your many cats' names. | ||
+ | * Tuples (): are just like lists, but you can't change their values. The values that you give it first up, are the values that you are stuck with for the rest of the program. Again, each value is numbered starting from zero, for easy reference. Example: the names of the months of the year. | ||
+ | * Dictionaries {'':'', | ||
+ | |||
+ | * list operation (so-called array) ([[http:// | ||
+ | [1,2,3] | ||
+ | len(arrayName) # size of list | ||
+ | |||
+ | # add value to all elements of list | ||
+ | my_list=[1, | ||
+ | new_list = [x+1 for x in my_list] # [2,4,6,8,9] | ||
+ | |||
+ | list.append(obj) | ||
+ | list.extend(list) | ||
+ | list.index(obj) | ||
+ | list.count(obj) # count appearance of obj | ||
+ | |||
+ | # array to string and string to array | ||
+ | sentence = [" | ||
+ | ' ' | ||
+ | |||
+ | list=[3.1, | ||
+ | ', ' | ||
+ | |||
+ | '3.1, 121.2, 34.1' | ||
+ | # 2nd number make how many split point | ||
+ | '3.1, 121.2, 34.1' | ||
+ | |||
+ | # list sort (modify itself) | ||
+ | versionList.sort(reverse=1) # higher to lower | ||
+ | versionList.sort() | ||
+ | |||
+ | str([-4, -2, 0, 2, 4]) # ' | ||
+ | bb_str =' | ||
+ | |||
+ | # list compare | ||
+ | [-4, -2, 0, 2, 4] == [-4, -2, 0, 2, 3] # false | ||
+ | |||
+ | # multiple list operation | ||
+ | |||
+ | wMap_zero_Jnt=[x for x in wMap_All_Jnt if x not in wMap_Jnt_tgt] # remove list from list | ||
+ | |||
+ | a = [1, 2, 3, 4, 5] | ||
+ | b = [9, 8, 7, 6, 5] | ||
+ | common = set(a) & set(b) #[5], no order applied | ||
+ | |||
+ | [i for i, j in zip(a, b) if i == j] # [5] for equal-sized lists, which order matters | ||
+ | |||
+ | version_list_prefix=[" | ||
+ | version_list_postfix=[" | ||
+ | version_list_color=[" | ||
+ | for each, | ||
+ | print(each+" | ||
+ | | ||
+ | # list slice operation | ||
+ | # n = len(L) | ||
+ | # item = L[index] | ||
+ | # seq = L[start: | ||
+ | # seq = L[start: | ||
+ | seq = L[::2] # get every other item, starting with the first | ||
+ | seq = L[1::2] # get every other item, starting with the second | ||
+ | |||
+ | seq=L[::-1] # reverse reading list | ||
+ | list(reversed(seq)) # generate a list reversed | ||
+ | L.reverse() # reverse list, it changed original list | ||
+ | seq=L[::-2] # reverse reading list, and get every other item | ||
+ | |||
+ | list=[1, | ||
+ | seq=list[:: | ||
+ | |||
+ | # list to pair list | ||
+ | info = [' | ||
+ | info_pair = zip(info[:: | ||
+ | # [(' | ||
+ | |||
+ | # list flatten, and remove duplicates | ||
+ | nestList = [[2, | ||
+ | flatList = set(sum(nestList, | ||
+ | |||
+ | # delete a element from list | ||
+ | a = [1,2,3,4] | ||
+ | del(a[2]) # [1,2,4] | ||
+ | |||
+ | # for large list | ||
+ | import itertools | ||
+ | flatList = set( list(itertools.chain.from_iterable(nestList)) ) # for same type element list, no mix of list and element like [[5],6], as it will error | ||
+ | |||
+ | import operator | ||
+ | flatList = set( reduce(operator.add, | ||
+ | |||
+ | # for any mix list | ||
+ | def flatFn(mainList): | ||
+ | newList = [] | ||
+ | for each in mainList: | ||
+ | if isinstance(each, | ||
+ | newList.extend( flatFn(each) ) | ||
+ | else: | ||
+ | newList.append(each) | ||
+ | return newList | ||
+ | | ||
+ | flatList = set( flatFn(nestList) ) | ||
+ | |||
+ | |||
+ | </ | ||
+ | * dictionary operation <code python> | ||
+ | # ref: http:// | ||
+ | dict.clear() | ||
+ | dict.get(key, | ||
+ | dict.has_key(key) | ||
+ | dict.items() # a list dict's (key, value) tuple pairs | ||
+ | dict.keys() # a list of keys | ||
+ | dict.values() # a list of values | ||
+ | len(dict) # size of dict | ||
+ | |||
+ | #example, obj property | ||
+ | dict = {' | ||
+ | |||
+ | #example, obj list | ||
+ | dict = {' | ||
+ | |||
+ | # delete key | ||
+ | my_dict.pop(key_name, | ||
+ | </ | ||
+ | * set operation <code python> | ||
+ | set( (" | ||
+ | # set([' | ||
+ | |||
+ | fib=set( [1, | ||
+ | prime=set( [2, | ||
+ | combine=fib | prime # set([1, 2, 3, 5, 7, 8, 11, 13]) | ||
+ | common=fib & prime #set([2, 3, 5, 13]) | ||
+ | diff = fib - prime # set([8, 1]) | ||
+ | fib ^ prime # combine - common #set([1, 7, 8, 11]) | ||
+ | |||
+ | # <, <=, >, >=, ==, !=, in, not in works in set | ||
+ | len(fib)=6 | ||
+ | max(fib)=13 | ||
+ | min(fib)=1 | ||
+ | sum(fib)=32 | ||
+ | any(set([false, | ||
+ | all(set([false, | ||
+ | set.add(new) | ||
+ | set.remove(old) | ||
+ | </ | ||
+ | |||
+ | * list attribute of a object <code python> | ||
+ | ===== turn a file into a module ===== | ||
+ | |||
+ | * a file can be a module like <code python> | ||
+ | import FileName | ||
+ | FileName.functionName() # call function side that file | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== turn a folder into a module ===== | ||
+ | |||
+ | * you can turn a list of python file under same folder into a module by create a empty file under the directory: < | ||
+ | * it will automatically turn the folder into a module so that you can call each file after import folder like <code python> | ||
+ | import FolderName | ||
+ | from FolderName import FileName | ||
+ | </ | ||
+ | * whenever you call import FolderName, the __init__py will be run-ed first, so you can put some code inside to do some pre-run task, or append the folder into python path <code python __init__.py> | ||
+ | import os, sys | ||
+ | my_path = os.path.dirname(__file__) | ||
+ | my_path in sys.path or sys.path.append(my_path) | ||
+ | </ | ||
+ | |||
+ | ===== check module installed ===== | ||
+ | |||
+ | * python code <code python> | ||
+ | dir(moduleName) | ||
+ | #import moduleName | ||
+ | #then type moduleName to show location | ||
+ | </ | ||
+ | * check module in shell command <code bash> | ||
+ | * change current working path< | ||
+ | </ | ||
+ | |||
+ | ===== cross python file reference===== | ||
+ | |||
+ | * import python function from another python file< | ||
+ | import sys | ||
+ | sys.path.append("/ | ||
+ | # method 1 | ||
+ | import sample | ||
+ | sample.abcd() | ||
+ | # method 2 | ||
+ | from sample import abcd | ||
+ | abcd() | ||
+ | #method 3 | ||
+ | from sample import * | ||
+ | abcd() | ||
+ | </ | ||
+ | * run another python script <code python> | ||
+ | execfile(" | ||
+ | # python 3, that one not work, use this one | ||
+ | exec(open(" | ||
+ | </ | ||
+ | * pass parameter to a python script (ref: http:// | ||
+ | # method 1: python myscript.py arg1 arg2 | ||
+ | import sys | ||
+ | |||
+ | print ' | ||
+ | print ' | ||
+ | |||
+ | # method 2 | ||
+ | import getopt, sys | ||
+ | </ | ||
+ | * example code for a mel file to html file process, in both module and app way | ||
+ | * run code <code bash> | ||
+ | * run in python <code python> | ||
+ | viewMel.viewMel_html(' | ||
+ | </ | ||
+ | * code <code python> | ||
+ | #view mel lib | ||
+ | #a python tool to view mel lib file functionts | ||
+ | import sys | ||
+ | |||
+ | def viewMel(file): | ||
+ | with open(file) as f: | ||
+ | for line in f: | ||
+ | lineClean=line.strip() | ||
+ | if lineClean.startswith('// | ||
+ | print lineClean.replace(' | ||
+ | | ||
+ | def viewMel_html(melFile, | ||
+ | h = open(htmlFile,' | ||
+ | with open(melFile) as f: | ||
+ | h.write('< | ||
+ | for line in f: | ||
+ | lineClean=line.strip() | ||
+ | if lineClean.startswith('// | ||
+ | h.write('< | ||
+ | elif lineClean.startswith(' | ||
+ | | ||
+ | elif lineClean.startswith('/ | ||
+ | | ||
+ | h.write('</ | ||
+ | h.close() | ||
+ | | ||
+ | if __name__==" | ||
+ | viewMel_html(sys.argv[1], | ||
+ | </ | ||
+ | |||
+ | ===== web link operation ===== | ||
+ | |||
+ | * open url in brower <code python> | ||
+ | webbrowser._browsers # list registered browsers | ||
+ | |||
+ | new = 2 # open in a new tab, if possible | ||
+ | # open a public URL, in this case, the webbrowser docs | ||
+ | url = " | ||
+ | webbrowser.open(url, | ||
+ | # for using firefox, note, firefox needs to be default or in the system environment path | ||
+ | webbrowser.get(' | ||
+ | # open an HTML file on my own (Windows) computer | ||
+ | url = " | ||
+ | webbrowser.open(url, | ||
+ | </ | ||
+ | |||
+ | ===== file operation ===== | ||
+ | * check file exists <code python> | ||
+ | * access file and folder< | ||
+ | # delete a file | ||
+ | os.remove(tmpitem) | ||
+ | |||
+ | # check exist of a file | ||
+ | if not os.path.exists(tmpJPG): | ||
+ | print tmpitem | ||
+ | |||
+ | # get file with a certain name pattern in a directory and all its sub-directories | ||
+ | scanDir = r' | ||
+ | my_list = [] | ||
+ | for (dirpath, dirnames, filenames) in os.walk(scanDir): | ||
+ | my_list.extend( [ os.path.join(dirpath, | ||
+ | |||
+ | # get file with a certain name pattern in a directory | ||
+ | [x for x in os.listdir(scanDir) if os.path.isfile(os.path.join(scanDir, | ||
+ | [x for x in glob.glob(os.path.join(scanDir,' | ||
+ | </ | ||
+ | * lines to array< | ||
+ | with open(fname) as f: | ||
+ | content = f.readlines() | ||
+ | |||
+ | with open(fname) as f: | ||
+ | for line in f: | ||
+ | #do something with line | ||
+ | </ | ||
+ | * remove any non-ascii words in file names <code python> | ||
+ | import os | ||
+ | import urllib | ||
+ | curdir = os.getcwd() | ||
+ | os.chdir(parentDir) | ||
+ | file_list_en = os.listdir(' | ||
+ | file_list_cn = os.listdir(u' | ||
+ | for i in xrange(len(file_list_en)): | ||
+ | itemName = file_list_en[i] | ||
+ | print(itemName) | ||
+ | if itemName.startswith(' | ||
+ | # convert %AA cn name to unicode | ||
+ | new_fixName1 = urllib.unquote(itemName).decode(' | ||
+ | # then remove cn chars | ||
+ | new_itemName2 = '' | ||
+ | if itemName != new_itemName2: | ||
+ | print([itemName, | ||
+ | os.rename(itemName, | ||
+ | else: | ||
+ | itemName = file_list_cn[i] # for non ascii names | ||
+ | # just remove cn chars | ||
+ | new_itemName = '' | ||
+ | if itemName != new_itemName: | ||
+ | print([itemName, | ||
+ | os.rename(itemName, | ||
+ | | ||
+ | os.chdir(curdir) | ||
+ | </ | ||
+ | * read line from a huge file by multiple process at the same time, without accident write operation< | ||
+ | import linecache | ||
+ | linecache.getline('/ | ||
+ | </ | ||
+ | * process line by line rewrite <code python> | ||
+ | import sys | ||
+ | import fileinput | ||
+ | |||
+ | for i, line in enumerate(fileinput.input(' | ||
+ | # | ||
+ | if line.find(' | ||
+ | color=line.split(';', | ||
+ | color=color.split(' | ||
+ | sys.stdout.write(line.replace('</ | ||
+ | else: | ||
+ | sys.stdout.write(line) | ||
+ | </ | ||
+ | * make sure directory is created before create file in defined path <code python> | ||
+ | my_filePath = '/ | ||
+ | # method 1: these 2 lines only create last leaf folder, won't deal all the inbetween folders | ||
+ | if not os.path.isdir(os.path.dirname(my_filePath)): | ||
+ | os.mkdir(os.path.dirname(my_filePath)) | ||
+ | | ||
+ | # method 2: these 2 lines create all the needed folders forming the path | ||
+ | try: | ||
+ | os.makedirs(os.path.dirname(my_filePath)) | ||
+ | except OSError: | ||
+ | pass | ||
+ | | ||
+ | # method 3: all in one check and create if needed, like method 2 but not need try and except since it will be ok for exist | ||
+ | os.makedirs(os.path.dirname(output_path), | ||
+ | </ | ||
+ | * write python data< | ||
+ | # write raw data and read raw data | ||
+ | os.getcwd() | ||
+ | |||
+ | import json | ||
+ | def writeDataFile(data, | ||
+ | with open(file, ' | ||
+ | json.dump(data, | ||
+ | | ||
+ | def readDataFile(file): | ||
+ | with open(file) as f: | ||
+ | data = json.load(f) | ||
+ | return data | ||
+ | | ||
+ | # write dictionary data and read dictionary data | ||
+ | import csv | ||
+ | def writeDictFile(dict, | ||
+ | w = csv.writer(open(" | ||
+ | for key, val in dict.items(): | ||
+ | w.writerow([key, | ||
+ | |||
+ | def readDictFile(file): | ||
+ | dict = {} | ||
+ | for key, val in csv.reader(open(file)): | ||
+ | dict[key] = val | ||
+ | return dict | ||
+ | </ | ||
+ | * UTF-8 unicode file write< | ||
+ | ############### | ||
+ | import codecs | ||
+ | txt=u"< | ||
+ | i=0 | ||
+ | for each in a: | ||
+ | i=i+1; | ||
+ | txt=txt+u"< | ||
+ | |||
+ | txt=txt+u'</ | ||
+ | |||
+ | with codecs.open(' | ||
+ | f.write(txt) | ||
+ | </ | ||
+ | * copy directory structure only <code python> | ||
+ | for dirpath, dirnames, filenames in os.walk(srcPath): | ||
+ | to_mkdir = os.path.join(tgtPath, | ||
+ | if not os.path.isdir(to_mkdir): | ||
+ | os.mkdir(to_mkdir) | ||
+ | os.startfile(tgtPath) # show result folder | ||
+ | </ | ||
+ | |||
+ | ===== thread operation ===== | ||
+ | |||
+ | * run a process or python service/app into another thread, so it wont block current interaction <code python> | ||
+ | def app(opt): | ||
+ | if opt == ' | ||
+ | import threading | ||
+ | th = threading.Thread(target = run_noter) | ||
+ | th.start() | ||
+ | def run_noter(): | ||
+ | import Noter | ||
+ | Noter.main() | ||
+ | </ | ||
+ | |||
+ | ====== module operation ====== | ||
+ | |||
+ | * How to install extra module automatically with pip | ||
+ | * download pip and use bellow method to manually install it, or run this line of command to get or update pip stuffs. <code python> | ||
+ | * once done, you can install rest modules with cmd <code bash> | ||
+ | * How to install wheel package <code dos>REM pip app is at PythonAppDir/ | ||
+ | REM make sure that wheel is in 32/64bit matching your python 32/64bit version | ||
+ | pip install C:/ | ||
+ | </ | ||
+ | * How to install extra module into seperate directory < | ||
+ | python.exe -m pip install --target=D: | ||
+ | </ | ||
+ | * How to install extra modules manually | ||
+ | - download the module source, | ||
+ | * if it has setup.py in its directory, run <code python> | ||
+ | * if it has no setup.py in its directory, or just a single folder or a python .py file, then just include its path in your python path under your system variable or run this command in python cmd line before you call <code python> | ||
+ | * **Ideally, if you put the Module Folder (not its parent distribution folder) under the Lib/ | ||
+ | * However, if you want your Python module to be at a specific location, then add it to python path environment variable. For windows advanced system setting > environment variable < | ||
+ | - distribute your python file with module, | ||
+ | * you can ask user to manually install those modules that used in your python program file | ||
+ | * or just put those dependent file or folder next to your python program file | ||
+ | |||
+ | * check with module info <code python> | ||
+ | # check whether a module has that attribute | ||
+ | if hasattr(QtGui, | ||
+ | print(" | ||
+ | |||
+ | # try get a function from a module and with fallback option | ||
+ | resultFunc = getattr(MyClass, | ||
+ | |||
+ | # check imported module name dictionary | ||
+ | if ' | ||
+ | print(' | ||
+ | </ | ||
+ | * work with module using variable names <code python> | ||
+ | # import PySide | ||
+ | __import__(' | ||
+ | |||
+ | # same as from PySide import QtNetwork as Net | ||
+ | qtModeList = (" | ||
+ | qtMode = 0 | ||
+ | Net = getattr( __import__(qtModeList[qtMode], | ||
+ | </ | ||
+ | * import module from its parent directory <code python> | ||
+ | import os,sys | ||
+ | os.path.join(sys.path[0], | ||
+ | import my_module_at_current_file_parent_dir | ||
+ | </ | ||
+ | ===== useful module list ===== | ||
+ | |||
+ | ==== useful HTML modules ==== | ||
+ | |||
+ | * [[devwiki: | ||
+ | * < | ||
+ | * BeautifulSoup [[http:// | ||
+ | * Mechanize [[http:// | ||
+ | * Scrapy [[http:// | ||
+ | * pyquery [[https:// | ||
+ | * dokuwiki: [[http:// | ||
+ | |||
+ | * embed code editor info: | ||
+ | * http:// | ||
+ | * https:// | ||
+ | * http:// | ||
+ | * http:// | ||
+ | * embed python console info: | ||
+ | * code module | ||
+ | * http:// | ||
+ | * http:// | ||
+ | * https:// | ||
+ | * http:// | ||
+ | * http:// | ||
+ | |||
+ | ==== useful automation modules ==== | ||
+ | |||
+ | * a online book related: https:// | ||
+ | * winsys: admin automation for windows | ||
+ | * ref: http:// | ||
+ | * pywinauto: https:// | ||
+ | * tutorial: | ||
+ | * DevNami - Python Pyautogui Take Screenshot : https:// | ||
+ | * SF Python - https:// | ||
+ | * https:// | ||
+ | * additional ref: | ||
+ | * https:// | ||
+ | * http:// | ||
+ | * selenium: web browser automation | ||
+ | * the doc: http:// | ||
+ | |||
+ | ==== useful Graphic modules ==== | ||
+ | |||
+ | * numpy : numerical python | ||
+ | * matplotlib : plot graphing tool (my note: [[devwiki: | ||
+ | * xlrd : excel read tool | ||
+ | * pandas : data structures and data analysis tools (loading datas and data operation like SQL) | ||
+ | * http:// | ||
+ | * PyQtGraph : plot graphing tool | ||
+ | * Gnuplot : plot tool | ||
+ | * ipython : interactive python and visualization tool | ||
+ | * OpenEXR | ||
+ | * IlmImf, a library that reads and writes OpenEXR images. | ||
+ | * Half, a C++ class for manipulating half values | ||
+ | * Imath, a math library with support for matrices, 2d- and 3d-transformations, | ||
+ | * exrdisplay, a sample application for viewing OpenEXR images at various exposure. | ||
+ | * wxPython : wx GUI | ||
+ | * PyQt/PySide : Qt GUI | ||
+ | * pysqlite/ | ||
+ | * Graph (node graph): https:// | ||
+ | * NetworkX (node graph big): http:// | ||
+ | |||
+ | ==== useful audio module ==== | ||
+ | |||
+ | * pyaudio <code python> | ||
+ | p = pyaudio.PyAudio() | ||
+ | for i in range(p.get_device_count()): | ||
+ | print p.get_device_info_by_index(i).get(' | ||
+ | </ | ||
+ | * useful Game building modules | ||
+ | * quick tutorial on python openGL game: http:// | ||
+ | |||
+ | ==== database and file modules ==== | ||
+ | |||
+ | * sqlite (built-in): | ||
+ | * additional desktop sqlite commandline tools: https:// | ||
+ | * json (built-in ascii out) | ||
+ | * cPickle (built-in binary out) | ||
+ | |||
+ | * encryption modules | ||
+ | * hashlib (built-in) <code python> | ||
+ | m = hashlib.md5() | ||
+ | m.update(user_input_text) | ||
+ | # a sample hash code example | ||
+ | if m.hexdigest() != ' | ||
+ | return | ||
+ | </ | ||
+ | |||
+ | * data hashing, like compress data into a string, good for big data compare and record | ||
+ | * hash (built-in, not need import) 64bit, take a object and get a int for quick compare | ||
+ | * hashlib (built-in, need import) 128bit+ and more option like md5, sha for more secure and digital signiture | ||
+ | ==== system info modules ==== | ||
+ | |||
+ | * getpass (built-in, user name) <code python> | ||
+ | * glob (built-in, wild char file list) <code python> | ||
+ | # get all file named prefix variable _v001 like ma/mb file</ | ||
+ | * stat (built-in, file permission) <code python> | ||
+ | # lock down file for user, group, other readonly | ||
+ | os.chmod(filePath, | ||
+ | * time (built-in, time related) <code python> | ||
+ | |||
+ | ==== system command modules ==== | ||
+ | |||
+ | * subprocess (built-in) | ||
+ | * subprocess.Popen don't block your main program | ||
+ | </ | ||
+ | * subprocess.call will block the main program till call finish, equals <code python> | ||
+ | subprocess.call(r' | ||
+ | subprocess.Popen([r' | ||
+ | os.system(r' | ||
+ | </ | ||
+ | * subprocess.check_call will raise an exception | ||
+ | * both return result | ||
+ | * Ask System to Open Folder <code python> | ||
+ | if os.path.isdir(folderPath): | ||
+ | if sys.platform == ' | ||
+ | try: | ||
+ | subprocess.check_call([' | ||
+ | except subprocess.CalledProcessError: | ||
+ | pass # handle errors in the called executable | ||
+ | except OSError: | ||
+ | pass # executable not found | ||
+ | elif sys.platform == ' | ||
+ | try: | ||
+ | subprocess.check_call([' | ||
+ | except subprocess.CalledProcessError: | ||
+ | pass # handle errors in the called executable | ||
+ | except OSError: | ||
+ | pass # executable not found | ||
+ | elif sys.platform in [' | ||
+ | try: | ||
+ | subprocess.check_call([' | ||
+ | except subprocess.CalledProcessError: | ||
+ | pass # handle errors in the called executable | ||
+ | except OSError: | ||
+ | pass # executable not found | ||
+ | </ | ||
+ | * check if a process is running <code python> | ||
+ | appName = ' | ||
+ | info=subprocess.Popen(' | ||
+ | out, err = info.communicate() | ||
+ | #out = str(out) # for py3 byte convert | ||
+ | out = out.decode(' | ||
+ | result = [ x for x in out.replace('"','' | ||
+ | if len(result)> | ||
+ | print(' | ||
+ | else: | ||
+ | subprocess.Popen([r' | ||
+ | </ | ||
+ | * ask System to open file <code python> | ||
+ | if sys.platform in [' | ||
+ | os.startfile(filePath) | ||
+ | elif sys.platform == ' | ||
+ | os.open(filePath) | ||
+ | elif sys.platform == ' | ||
+ | os.xdg-open(filePath) | ||
+ | </ | ||
+ | * launch a subprocess to run a Bat file or python file in desktop <code python> | ||
+ | subprocess.Popen([r' | ||
+ | subprocess.Popen([r' | ||
+ | # force it to open in new console window instead of inside parent console window | ||
+ | subprocess.Popen([r' | ||
+ | |||
+ | # if above method failed because PATH or PYTHONPATH issue, especially when call like above in a mixed python environment like Maya, | ||
+ | # you need to use a clean copy of environment, | ||
+ | env2={} | ||
+ | env2[' | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | ''' | ||
+ | env2[' | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | D: | ||
+ | ''' | ||
+ | |||
+ | subprocess.Popen([r' | ||
+ | subprocess.Popen([r' | ||
+ | </ | ||
+ | * subprocess a console app and get return, and optionally hide the pop up console when call <code python> | ||
+ | # hide popup console for win platform only | ||
+ | startupinfo = subprocess.STARTUPINFO() | ||
+ | startupinfo.dwFlags |= 1 # | ||
+ | # startupinfo.wShowWindow = subprocess.SW_HIDE #(optional) | ||
+ | |||
+ | info=subprocess.Popen( ' | ||
+ | out, err = info.communicate() | ||
+ | out = out.decode(' | ||
+ | </ | ||
+ | ==== string related ==== | ||
+ | |||
+ | * re (built-in, regular expression) <code python> | ||
+ | # capture group and non-capture group: | ||
+ | # http:// | ||
+ | re.findall(' | ||
+ | re.findall(' | ||
+ | # since we only need the prefix, the Msg group is to test exisits | ||
+ | </ | ||
+ | |||
+ | ==== compile and de-compile module ==== | ||
+ | |||
+ | **cx_Freeze**: | ||
+ | * After compile, the only files need to do partial update each time is (exe + library.zip) | ||
+ | |||
+ | **PyInstaller**: | ||
+ | |||
+ | < | ||
+ | # cmd install | ||
+ | python -m pip install pyinstaller | ||
+ | |||
+ | # compile, cd to your py file first, you may need copy your supporting folder to dist path after compile | ||
+ | python.exe -m PyInstaller MyApp.py | ||
+ | |||
+ | # no terminal version | ||
+ | python.exe -m PyInstaller MyApp.py --noconsole | ||
+ | # set app binary icon | ||
+ | python.exe -m PyInstaller MyApp.py --icon=icons/ | ||
+ | |||
+ | # exclude tk and tcl library | ||
+ | python.exe -m PyInstaller MyApp.py --icon=icons/ | ||
+ | |||
+ | # for mac, if failed to build on pyconfig.h | ||
+ | # - fix pyconfig.h; by cmd: sudo touch / | ||
+ | python.exe -m PyInstaller MyApp.py --icon=icons/ | ||
+ | |||
+ | python.exe -m PyInstaller MyApp.py --icon=icons/ | ||
+ | |||
+ | # cmd+i to check app info, and drag icns file to app/folder icon logo to set the icon | ||
+ | # manually turn folder into app, just add .app behind folder name, folder name must be same as main binary file | ||
+ | |||
+ | # when run result mac app on other computer, if security stop it run like "app is damaged", | ||
+ | xattr -cr "/ | ||
+ | </ | ||
+ | |||
+ | **uncompyle2**: | ||
+ | |||
+ | https:// | ||
+ | |||
+ | * code example <code python># in the init file | ||
+ | main('/ | ||
+ | </ | ||
+ | |||
+ | ====== Python Important Modules ====== | ||
+ | ===== pip ===== | ||
+ | |||
+ | * pip is a quick python module get and installer module for python, it can download module for your python library. | ||
+ | * check version < | ||
+ | * update it before install other module, make sure you already in python' | ||
+ | # or | ||
+ | python -m pip install --upgrade pip | ||
+ | </ | ||
+ | ===== re ===== | ||
+ | |||
+ | * regular expression pattern | ||
+ | |||
+ | ^ all data file | < | ||
+ | ^ all maya file | < | ||
+ | |||
+ | * variable name case conversion | ||
+ | * CamelCase to " | ||
+ | * code: <code python> | ||
+ | def convert(name, | ||
+ | s1 = re.sub(' | ||
+ | return re.sub(' | ||
+ | # | ||
+ | |||
+ | def convert2(name, | ||
+ | return re.sub(' | ||
+ | </ | ||
+ | ===== requests ===== | ||
+ | |||
+ | * 3rd party module, html get post request response operation library | ||
+ | * header list: https:// | ||
+ | |||
+ | * **Single Get web link content** <code python> | ||
+ | import requests | ||
+ | result = requests.get(' | ||
+ | print(result.text) | ||
+ | </ | ||
+ | * **Single post web link content with login info** <code python> | ||
+ | result = requests.post(' | ||
+ | print(result.text) | ||
+ | </ | ||
+ | * **one-time login with continue consistent header info for session operation** <code python> | ||
+ | with requests.Session() as session: | ||
+ | # first time login, | ||
+ | reply = session.post(' | ||
+ | print(reply.text) | ||
+ | # read rest login-required pages | ||
+ | reply = session.get(' | ||
+ | print(reply.text) | ||
+ | </ | ||
+ | * check send header and received header info <code python> | ||
+ | print(session_object.headers) # user sending header info | ||
+ | print(reply_object.headers) # server replying header info | ||
+ | </ | ||
+ | * more function explain <code python> | ||
+ | result.content # is html in bytes | ||
+ | result.text # is html in unicode text | ||
+ | </ | ||
+ | * disable non secure cert warning <code python> | ||
+ | ===== PIL and Pillow===== | ||
+ | |||
+ | * PIL, Python Imaging Library (Fork) = Pillow, install the lib < | ||
+ | * python code <code python> | ||
+ | from PIL import Image, ImageDraw, ImageOps | ||
+ | </ | ||
+ | |||
+ | ===== BeautifulSoup ===== | ||
+ | |||
+ | * a html info extractor, best works with another parser module " | ||
+ | * ref: https:// | ||
+ | * parser is a html interprater, | ||
+ | * example code <code python> | ||
+ | from bs4 import BeautifulSoup | ||
+ | soup = BeautifulSoup(html, | ||
+ | # find all title link text | ||
+ | link_list = soup.find_all(" | ||
+ | name_list = [x.string for x in link_list ] # text element extract | ||
+ | link_list[0].attrs[' | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== selenium ===== | ||
+ | |||
+ | * you need install 2 things to get it working: | ||
+ | - Python module: | ||
+ | - for py2.7: https:// | ||
+ | - for py3.x: https:// | ||
+ | - system platform dependent webdriver binary: http:// | ||
+ | - for chrome browser automate: go above link and find 3rd binding " | ||
+ | - then you can load that drive binary into python selenium module object to start <code python> | ||
+ | from selenium import webdriver | ||
+ | driver = webdriver.Chrome('/ | ||
+ | driver.get(' | ||
+ | driver.implicitly_wait(20) | ||
+ | driver.get_screenshot_as_file(r' | ||
+ | driver.quit() | ||
+ | </ | ||
+ | * get element <code python> | ||
+ | # get css selector by right click browser' | ||
+ | driver.find_element_by_css_selector(' | ||
+ | # path method | ||
+ | driver.find_element_by_xpath('// | ||
+ | </ | ||
+ | * element operation | ||
+ | * element.get_attribute(' | ||
+ | * element.get_attribute(' | ||
+ | * element.text | ||
+ | * element.click() | ||
+ | * element_input.send_keys() and webdriver.common.keys | ||
+ | * element_form.submit() | ||
+ | * driven_browser.back(), | ||
+ | |||
+ | * additional tool: | ||
+ | * selenium ide firefox - a all-in-one test tool for it: https:// | ||
+ | * tutorial: http:// | ||
+ | ===== PyAutoGUI ===== | ||
+ | |||
+ | * GUI cross-platform GUI interaction automation | ||
+ | * ref: https:// | ||
+ | * tutorial: https:// | ||
+ | * full list of library required in download page: https:// | ||
+ | |||
+ | * mouse control | ||
+ | * click(), doubleClick(), | ||
+ | * click([x, | ||
+ | * moveTo(x,y [, | ||
+ | * moveRel(x_offset, | ||
+ | * dragTo(x,y [, | ||
+ | * position(), size(), | ||
+ | * displayMousePosition() <code python> | ||
+ | # note, that displayMousePosition require 3rd party library | ||
+ | # * PIL (Py2.x only, adapted by Pillow) > PIL.ImageGrab > pyscreenze (edit line 309 with "from PIL import ImageGrab" | ||
+ | http:// | ||
+ | https:// | ||
+ | </ | ||
+ | |||
+ | * keyboard control | ||
+ | * typewrite(' | ||
+ | * press(' | ||
+ | * hotkey(' | ||
+ | * note: best work with time.sleep(5) to give 5 sec for pc to respond | ||
+ | |||
+ | * image recognition | ||
+ | * pixel(x,y) # return RGB | ||
+ | * screenshot([filename]) # return PIL,Pillow Image object [and save file] | ||
+ | * locateOnScreen(imageFilename) # returns (x,y, w, h) or None | ||
+ | * linux: scrot | ||
+ | * example code <code python> | ||
+ | import pyautogui as pui | ||
+ | pos = pui.locateOnScreen(' | ||
+ | pui.click( (pos[0]+pos[2]*0.5 , pos[1]+pos[3]*0.5) ) | ||
+ | </ | ||
+ | |||
+ | ===== SikuliX ===== | ||
+ | |||
+ | * SikuliX automates anything you see on the screen of your desktop computer running Windows, Mac or some Linux/Unix. Link: http:// | ||
+ | * tutorial: https:// | ||
+ | |||
+ | ===== pyautoit ===== | ||
+ | |||
+ | * a python binding for AutoIt tool, a windows only automation software | ||
+ | * https:// | ||
+ | * AutoIt home page: https:// | ||
+ | * API level interaction | ||
+ | |||
+ | |||
+ | ===== pywinauto ===== | ||
+ | |||
+ | * a mostly windows only GUI automation module, with mouse, keyboard support on linux | ||
+ | * API level interaction | ||
+ | |||
+ | ===== pywin32 - win32com ===== | ||
+ | |||
+ | * tip and ref: | ||
+ | * http:// | ||
+ | * http:// | ||
+ | * COMbrowser: win32com\client\combrowse.py | ||
+ | |||
+ | * install and restart computer to get dll reg refreshed < | ||
+ | https:// | ||
+ | (or) python -m pip install pypiwin32</ | ||
+ | |||
+ | * get windows explorer in taskbar order, return [(title, hwnd int, addressbar url, [top, | ||
+ | import win32com | ||
+ | from win32com import client | ||
+ | def get_explorer_list(): | ||
+ | # win32com: get folder windows in taskbar order; return [(title, hwnd int, addressbar url, [top, | ||
+ | shell = client.Dispatch(" | ||
+ | win_list = shell.Windows() | ||
+ | result_list = [] | ||
+ | for win in win_list: | ||
+ | info = [] | ||
+ | info.append(win.LocationName) # title name | ||
+ | info.append(win.hwnd) # handle value as int | ||
+ | info.append(win.LocationURL) # address bar url, eg. file:/// | ||
+ | info.append([win.Top, | ||
+ | info.append(win.visible) # visible | ||
+ | info.append(win) # com object | ||
+ | result_list.append(info) | ||
+ | return result_list | ||
+ | ''' | ||
+ | [' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ''' | ||
+ | </ | ||
+ | * get selected item in window explorer <code python> | ||
+ | # ref: | ||
+ | # https:// | ||
+ | # https:// | ||
+ | |||
+ | def get_selection_list(win): | ||
+ | # win32com: get selection item detail from win COM object | ||
+ | item_list = [] | ||
+ | folderItems = win.Document.SelectedItems() | ||
+ | for i in range(folderItems.Count): | ||
+ | tmp_info = [] | ||
+ | tmp_info.append(folderItems.Item(i).path) # C: | ||
+ | tmp_info.append(folderItems.Item(i).name) | ||
+ | tmp_info.append(folderItems.Item(i).isFolder) | ||
+ | tmp_info.append(folderItems.Item(i).size) | ||
+ | tmp_info.append(folderItems.Item(i).type) | ||
+ | item_list.append(tmp_info) | ||
+ | return item_list | ||
+ | </ | ||
+ | * explorer window COM object control <code python> | ||
+ | # control the window COM object to go to a location | ||
+ | win.Navigate(' | ||
+ | win.Busy # a check for still in processing | ||
+ | |||
+ | # check visibile and make full screen | ||
+ | win.FullScreen =1 # make first windows explorer full screen | ||
+ | </ | ||
+ | * system operation< | ||
+ | # get system dir and | ||
+ | oShell = win32com.client.Dispatch(" | ||
+ | print(oShell.SpecialFolders(" | ||
+ | |||
+ | # change drive letter | ||
+ | # ref: http:// | ||
+ | |||
+ | # create windows shortcut and read it | ||
+ | shortcut = shell.CreateShortCut(" | ||
+ | shortcut.Targetpath = " | ||
+ | shortcut.save() | ||
+ | |||
+ | shortcut = shell.CreateShortCut(" | ||
+ | print(shortcut.Targetpath) | ||
+ | |||
+ | # get single screen resolution and total screen | ||
+ | # ref: https:// | ||
+ | import win32api | ||
+ | w=win32api.GetSystemMetrics(0) # primary screen width | ||
+ | h=win32api.GetSystemMetrics(1) # primary screen height | ||
+ | vw = win32api.GetSystemMetrics(78) # total screen area width | ||
+ | vh = win32api.GetSystemMetrics(79) # total screen area height | ||
+ | print(' | ||
+ | print(' | ||
+ | </ | ||
+ | ===== ctypes ===== | ||
+ | |||
+ | * ctypes is an advanced ffi (Foreign Function Interface) package, ctypes allows to call functions in dlls/shared libraries and wrap libraries in pure Python. ctypes works cross-platform with libffi support. | ||
+ | * ref: http:// | ||
+ | * my doc on windows API and DLL functions [[devwiki: | ||
+ | * (method 1) get all windows explorer windows in Z order, return [(title, class, [x,y,w,h], hwnd int)] <code python> | ||
+ | def get_win_order_all(): | ||
+ | # ctype: grab folder windows in z order, return [(title, class, [x,y,w,h], hwnd int)] | ||
+ | from ctypes import wintypes | ||
+ | order_list = [] | ||
+ | result_list = [] | ||
+ | top = ctypes.windll.user32.GetTopWindow(None) | ||
+ | if not top: | ||
+ | return order_list | ||
+ | length = ctypes.windll.user32.GetWindowTextLengthW(top) | ||
+ | buff = ctypes.create_unicode_buffer(length + 1) | ||
+ | ctypes.windll.user32.GetWindowTextW(top, | ||
+ | class_name = ctypes.create_string_buffer(200) | ||
+ | ctypes.windll.user32.GetClassNameA(top, | ||
+ | r=ctypes.wintypes.RECT() | ||
+ | ctypes.windll.user32.GetWindowRect(top, | ||
+ | # class_name.value in py3 is byte, while py2 is string | ||
+ | if isinstance(class_name.value, | ||
+ | result_list.append( [buff.value, | ||
+ | else: | ||
+ | result_list.append( [buff.value, | ||
+ | order_list.append(top) | ||
+ | while True: | ||
+ | next = ctypes.windll.user32.GetWindow(order_list[-1], | ||
+ | if not next: | ||
+ | break | ||
+ | length = ctypes.windll.user32.GetWindowTextLengthW(next) | ||
+ | buff = ctypes.create_unicode_buffer(length + 1) | ||
+ | ctypes.windll.user32.GetWindowTextW(next, | ||
+ | class_name = ctypes.create_string_buffer(200) | ||
+ | ctypes.windll.user32.GetClassNameA(next, | ||
+ | r=ctypes.wintypes.RECT() | ||
+ | ctypes.windll.user32.GetWindowRect(next, | ||
+ | # class_name.value in py3 is byte, while py2 is string | ||
+ | if isinstance(class_name.value, | ||
+ | result_list.append( [buff.value, | ||
+ | else: | ||
+ | result_list.append( [buff.value, | ||
+ | order_list.append(next) | ||
+ | return result_list | ||
+ | |||
+ | full_list = get_win_order_all() | ||
+ | visible_list = [x for x in full_list if ctypes.windll.user32.IsWindowVisible(x[-1])] | ||
+ | # visible list is actually more useful, 10+ instead 100+ items | ||
+ | |||
+ | explorer_list = [x for x in visible if x[1]==' | ||
+ | firefox_list = [x for x in visible if x[1]==' | ||
+ | </ | ||
+ | * (method 2) get all (visible) (windows explorer) windows in Z order, return [(title, class, hwnd as pointer)]< | ||
+ | def get_win_order_v2(): | ||
+ | # ctypes | ||
+ | # ref: https:// | ||
+ | # info (title, class_name, hwnd) | ||
+ | window_list = [] | ||
+ | # propare windows list passing | ||
+ | def window_info_process(hwnd, | ||
+ | if ctypes.windll.user32.IsWindowVisible(hwnd): | ||
+ | length = ctypes.windll.user32.GetWindowTextLengthW(hwnd) | ||
+ | buff = ctypes.create_unicode_buffer(length + 1) | ||
+ | ctypes.windll.user32.GetWindowTextW(hwnd, | ||
+ | class_name = ctypes.create_string_buffer(200) | ||
+ | ctypes.windll.user32.GetClassNameA(hwnd, | ||
+ | t_class_name = class_name.value | ||
+ | if not isinstance(t_class_name, | ||
+ | t_class_name = class_name.value.decode(' | ||
+ | if t_class_name == ' | ||
+ | window_list.append( [ buff.value, t_class_name, | ||
+ | return True | ||
+ | procObj = ctypes.WINFUNCTYPE(ctypes.c_bool, | ||
+ | # execute it | ||
+ | ctypes.windll.user32.EnumWindows(procObj(window_info_process), | ||
+ | return window_list | ||
+ | </ | ||
+ | * (method 3) Break down ctypes hwnd, pid, process_handle into functions modules <code python> | ||
+ | ''' | ||
+ | ref: http:// | ||
+ | Window handle → process ID: GetWindowThreadProcessId | ||
+ | Process ID → process handle: OpenProcess | ||
+ | Process handle → executable path: QueryFullProcessImageName (compare this with your target) | ||
+ | Close the process handle: CloseHandle | ||
+ | ref: http:// | ||
+ | Windows 2000 = GetModuleFileName() | ||
+ | Windows XP x32 = GetProcessImageFileName() | ||
+ | Windows XP x64 = GetProcessImageFileName() | ||
+ | Windows Vista = QueryFullProcessImageName() | ||
+ | Windows 7 = QueryFullProcessImageName() | ||
+ | ref: | ||
+ | uisoup - utils : https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | ''' | ||
+ | |||
+ | def get_win_pid(hwnd): | ||
+ | cur_pid = ctypes.c_long() | ||
+ | ctypes.windll.user32.GetWindowThreadProcessId(hwnd, | ||
+ | return cur_pid | ||
+ | def get_process_path(pid): | ||
+ | PROCESS_QUERY_INFORMATION = 0x0400 | ||
+ | max_unicode_path = 32767 * 2 + 200 | ||
+ | file_path_buffer = ctypes.create_unicode_buffer(max_unicode_path) | ||
+ | length_path = ctypes.c_ulong(max_unicode_path) | ||
+ | pHandle = ctypes.windll.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, | ||
+ | retval = ctypes.windll.kernel32.QueryFullProcessImageNameW(pHandle, | ||
+ | if retval == 0: | ||
+ | raise Exception(' | ||
+ | # | ||
+ | return file_path_buffer.value | ||
+ | def get_win_path(hwnd): | ||
+ | return get_process_path(get_win_pid(hwnd)) | ||
+ | |||
+ | def get_win_rect(hwnd): | ||
+ | from ctypes import wintypes | ||
+ | r=ctypes.wintypes.RECT() | ||
+ | ctypes.windll.user32.GetWindowRect(hwnd, | ||
+ | return [r.left, | ||
+ | def get_win_title(hwnd): | ||
+ | length = ctypes.windll.user32.GetWindowTextLengthW(hwnd) | ||
+ | title_buffer = ctypes.create_unicode_buffer(length + 1) | ||
+ | ctypes.windll.user32.GetWindowTextW(hwnd, | ||
+ | return title_buffer.value | ||
+ | # AE CS6: AE_CApplication_11.0 | ||
+ | def get_win_class(hwnd): | ||
+ | class_name = ctypes.create_string_buffer(200) | ||
+ | ctypes.windll.user32.GetClassNameA(hwnd, | ||
+ | t_class_name = class_name.value | ||
+ | if not isinstance(t_class_name, | ||
+ | t_class_name = class_name.value.decode(' | ||
+ | return t_class_name | ||
+ | def is_win_top(hwnd): | ||
+ | top_hwnd = ctypes.windll.user32.GetTopWindow(None) | ||
+ | return hwnd == top_hwnd | ||
+ | |||
+ | def get_win_list(visible=1, | ||
+ | # both method get result | ||
+ | # orderMethod uses : ctypes.windll.user32.GetTopWindow | ||
+ | # callBackMethod uses: ctypes.windll.user32.EnumWindows | ||
+ | win_list = [] | ||
+ | if orderMethod: | ||
+ | order_list = [] | ||
+ | top = ctypes.windll.user32.GetTopWindow(None) | ||
+ | if not top: | ||
+ | return win_list | ||
+ | visible_info = ctypes.windll.user32.IsWindowVisible(top) | ||
+ | win_list.append( [ top, visible_info ]) | ||
+ | order_list.append(top) | ||
+ | while True: | ||
+ | next = ctypes.windll.user32.GetWindow(order_list[-1], | ||
+ | if not next: | ||
+ | break | ||
+ | visible_info = ctypes.windll.user32.IsWindowVisible(next) | ||
+ | win_list.append( [next, visible_info] ) # hwnd: as int | ||
+ | order_list.append(next) | ||
+ | else: | ||
+ | # propare windows list passing | ||
+ | def window_info_process(hwnd, | ||
+ | visible_info = ctypes.windll.user32.IsWindowVisible(hwnd) | ||
+ | win_list.append( [ hwnd, visible_info ]) #hwnd: as LP_c_long | ||
+ | return True | ||
+ | # ref: http:// | ||
+ | # function 1: this will get as LP_c_long as hwnd | ||
+ | #procObj = ctypes.WINFUNCTYPE(ctypes.c_bool, | ||
+ | # function 2: this will get int as hwnd like other win32api function | ||
+ | procObj = ctypes.WINFUNCTYPE(ctypes.c_bool, | ||
+ | # execute it | ||
+ | ctypes.windll.user32.EnumWindows(procObj(window_info_process), | ||
+ | if visible: | ||
+ | return [x for x in win_list if x[1]] | ||
+ | return win_list | ||
+ | </ | ||
+ | * ctypes window operation by hwnd< | ||
+ | # my_hwnd can be a int or a ctypes int pointer | ||
+ | # full function ref: http:// | ||
+ | |||
+ | # bring window to bring | ||
+ | ctypes.windll.user32.SetForegroundWindow(my_hwnd) | ||
+ | |||
+ | # close window | ||
+ | WM_CLOSE = 0x0010 | ||
+ | ctypes.windll.user32.PostMessageA(my_hwnd, | ||
+ | |||
+ | # get window x,y,w,h | ||
+ | from ctypes import wintypes | ||
+ | r=ctypes.wintypes.RECT() | ||
+ | ctypes.windll.user32.GetWindowRect(my_hwnd, | ||
+ | print( [r.left, | ||
+ | |||
+ | # move window by x,y,w,h and refresh | ||
+ | ctypes.windll.user32.MoveWindow(my_hwnd, | ||
+ | </ | ||
+ | * mouse, keyboard operation <code python> | ||
+ | # get mouse position | ||
+ | class POINT(ctypes.Structure): | ||
+ | _fields_ = [(" | ||
+ | pt = POINT() | ||
+ | ctypes.windll.user32.GetCursorPos(ctypes.byref(pt)) | ||
+ | print(' | ||
+ | |||
+ | ctypes.windll.user32.SetCursorPos(1200, | ||
+ | ctypes.windll.user32.mouse_event(2, | ||
+ | ctypes.windll.user32.mouse_event(4, | ||
+ | </ | ||
+ | * get and set wallpaper in windows <code python> | ||
+ | def getWallpaper(): | ||
+ | SPI_GETDESKWALLPAPER = 0x0000073 | ||
+ | # try: | ||
+ | # win32con.SPI_GETDESKWALLPAPER | ||
+ | # except AttributeError, | ||
+ | # raise WinDesktopError, | ||
+ | wallpaper = ctypes.c_buffer(" | ||
+ | ctypes.windll.user32.SystemParametersInfoA(SPI_GETDESKWALLPAPER, | ||
+ | return wallpaper.value | ||
+ | |||
+ | def setWallpaper(wallpaperPath, | ||
+ | # Convert to bitmap if necessary | ||
+ | wallpaperImage = Image.open(wallpaperPath) | ||
+ | if wallpaperImage.format != ' | ||
+ | conversionPath = conversionPath or os.getenv(' | ||
+ | wallpaperPath = os.path.join(conversionPath, | ||
+ | wallpaperImage.save(wallpaperPath) | ||
+ | # Set wallpaper | ||
+ | wallpaperPath = ctypes.c_buffer(wallpaperPath) | ||
+ | ctypes.windll.user32.SystemParametersInfoA(win32con.SPI_SETDESKWALLPAPER, | ||
+ | </ | ||
+ | * wallpaper set (win7) the simple version <code python> | ||
+ | import ctypes | ||
+ | SPI_SETDESKWALLPAPER=20 | ||
+ | ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, | ||
+ | </ | ||
+ | * set id <code python> | ||
+ | * get if user is admin <code python> | ||
+ | * system operation <code python> | ||
+ | # get screen count | ||
+ | screen_cnt = ctypes.windll.user32.GetSystemMetrics(80) | ||
+ | # get screen resolution | ||
+ | screen_x, screen_y = ( ctypes.windll.user32.GetSystemMetrics(78), | ||
+ | </ | ||
+ | |||
+ | **file and folder operation** | ||
+ | * show drive letter in use <code python> | ||
+ | drive_list_data = ctypes.cdll.msvcrt._getdrives() # binary mask in decimal format | ||
+ | mask_list = list( ' | ||
+ | A_code = 65 # ascii code of letter A | ||
+ | drive_letter_in_use = [ chr(A_code+i) for i in range(len(mask_list)) if mask_list[i]==' | ||
+ | </ | ||
+ | * show file and select file in explorer (return 42)<code python> | ||
+ | my_filePath = u' | ||
+ | ctypes.windll.shell32.ShellExecuteW(None, | ||
+ | * open file property window <code python> | ||
+ | import time | ||
+ | import ctypes | ||
+ | import ctypes.wintypes | ||
+ | |||
+ | SEE_MASK_NOCLOSEPROCESS = 0x00000040 | ||
+ | SEE_MASK_INVOKEIDLIST = 0x0000000C | ||
+ | |||
+ | class SHELLEXECUTEINFO(ctypes.Structure): | ||
+ | _fields_ = ( | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | (" | ||
+ | ) | ||
+ | |||
+ | ShellExecuteEx = ctypes.windll.shell32.ShellExecuteEx | ||
+ | ShellExecuteEx.restype = ctypes.wintypes.BOOL | ||
+ | |||
+ | sei = SHELLEXECUTEINFO() | ||
+ | sei.cbSize = ctypes.sizeof(sei) | ||
+ | sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_INVOKEIDLIST | ||
+ | sei.lpVerb = " | ||
+ | sei.lpFile = ' | ||
+ | sei.nShow = 1 | ||
+ | ShellExecuteEx(ctypes.byref(sei)) | ||
+ | time.sleep(5) | ||
+ | </ | ||
+ | |||
+ | * get clipboard data (ref: https:// | ||
+ | import ctypes | ||
+ | def get_clipboard_text(): | ||
+ | ctypes.windll.kernel32.GlobalLock.argtypes = [ctypes.c_void_p] | ||
+ | ctypes.windll.kernel32.GlobalLock.restype = ctypes.c_void_p | ||
+ | ctypes.windll.kernel32.GlobalUnlock.argtypes = [ctypes.c_void_p] | ||
+ | ctypes.windll.user32.GetClipboardData.restype = ctypes.c_void_p | ||
+ | |||
+ | ctypes.windll.user32.OpenClipboard(0) | ||
+ | try: | ||
+ | if ctypes.windll.user32.IsClipboardFormatAvailable(1): | ||
+ | data = ctypes.windll.user32.GetClipboardData(1) | ||
+ | data_locked = ctypes.windll.kernel32.GlobalLock(data) | ||
+ | text = ctypes.c_char_p(data_locked) | ||
+ | value = text.value | ||
+ | ctypes.windll.kernel32.GlobalUnlock(data_locked) | ||
+ | return value | ||
+ | finally: | ||
+ | ctypes.windll.user32.CloseClipboard() | ||
+ | # test | ||
+ | print(get_clipboard_text()) | ||
+ | </ | ||
+ | ===== twisted ===== | ||
+ | |||
+ | * network communication: | ||
+ | * old version with python 2.7 32bit wheel: https:// | ||
+ | |||
+ | ===== django ===== | ||
+ | |||
+ | * a python web server, install by < | ||
+ | |||
+ | ===== openpyxl===== | ||
+ | |||
+ | * a new excel reader, xlsx format, not old xls format, since now everyone use new excel version | ||
+ | * read excel as dictionary (1st key, rest data) <code python> | ||
+ | def excel2Dict(filename): | ||
+ | # import openpyxl | ||
+ | # max_row = sheet.max_row | ||
+ | # max_column = sheet.max_column | ||
+ | wb = openpyxl.load_workbook(filename=filename, | ||
+ | records = [] | ||
+ | for sheet in wb.worksheets: | ||
+ | count = 0 | ||
+ | keys = [] | ||
+ | | ||
+ | for row in sheet.rows: | ||
+ | temp = [] | ||
+ | for cell in row: | ||
+ | if count == 0: | ||
+ | keys.append(str(cell.value)) | ||
+ | else: | ||
+ | temp.append(str(cell.value)) | ||
+ | if count > 0: | ||
+ | records.append( dict(zip(keys, | ||
+ | else: | ||
+ | count += 1 | ||
+ | return records | ||
+ | </ | ||
+ | * read excel as row data wo empty cell. <code python> | ||
+ | def excel2Data(filename): | ||
+ | # import openpyxl | ||
+ | wb = openpyxl.load_workbook(filename=filename, | ||
+ | sheet_data = [] | ||
+ | for sheet in wb.worksheets: | ||
+ | table_data = [] | ||
+ | for row in sheet.values: | ||
+ | row_data = [] | ||
+ | for cell in row: | ||
+ | if cell is not None: | ||
+ | row_data.append(cell) | ||
+ | if len(row_data)> | ||
+ | table_data.append(row_data) | ||
+ | sheet_data.append(table_data) | ||
+ | return sheet_data | ||
+ | </ | ||
+ | ====== Python by Reference or by Value ====== | ||
+ | |||
+ | * my experience found: "pure = assignment will not change original holder' | ||
+ | * more study on Pointer vs Reference: http:// | ||
+ | * Python variable are all reference, so pass reference to a function, the inside function holds copy of the reference, nothing outside affected, but if inside function reference modify, outside will be affected, since they all store value at same memory location(reference to that location): http:// | ||
+ | * http:// | ||
+ | * and another clear explanation of python reference vs c++ reference from c++ user by code: https:// | ||
+ | * here is my study experiment <code python> | ||
+ | |||
+ | # | ||
+ | # Example 1 | ||
+ | dict = {} | ||
+ | dict[' | ||
+ | for each in 'aa bb cc dd' | ||
+ | dict[' | ||
+ | list_aa = dict[' | ||
+ | for i in [1, | ||
+ | list_aa.append(i) | ||
+ | print dict # affect both list_aa and dict | ||
+ | | ||
+ | temp_list = dict[' | ||
+ | temp_list.append(22) # you are not get a copy of dict entry, but affect orginal dict as well | ||
+ | print temp_list | ||
+ | print dict # changed ------- because it is a operation | ||
+ | |||
+ | # ref: http:// | ||
+ | temp_list2 = dict[' | ||
+ | temp_list2.append(55) | ||
+ | print temp_list2 | ||
+ | print dict # stay same | ||
+ | |||
+ | # | ||
+ | # Example 2 | ||
+ | locs = [ [1], [2] ] | ||
+ | for loc in locs: # passing by values !!! | ||
+ | loc = [] | ||
+ | print locs # stay same | ||
+ | |||
+ | for loc in locs: | ||
+ | loc[0] = loc[0] * 2 | ||
+ | print locs # changed ------- because it is a operation | ||
+ | |||
+ | # | ||
+ | # Example 3 | ||
+ | a=1 | ||
+ | b=a | ||
+ | b=2 | ||
+ | print a # stay the same | ||
+ | |||
+ | a=[1] | ||
+ | b=a | ||
+ | b=[2] | ||
+ | print a # stay the same | ||
+ | |||
+ | a=[1] | ||
+ | b=a | ||
+ | b.append(2) | ||
+ | print a # changed ------- because it is a operation | ||
+ | |||
+ | # thus: assignment will not change original one, but operation will change original one | ||
+ | |||
+ | a=[1,2,3] | ||
+ | b=a | ||
+ | c=[4,5,6] | ||
+ | b=c | ||
+ | print a # stay the same | ||
+ | |||
+ | a=[1,2, [3.1, | ||
+ | b=a[2] | ||
+ | c=[4,5,6] | ||
+ | b=c | ||
+ | print a # stay the same | ||
+ | |||
+ | a=[1,2, [3.1, | ||
+ | b=a[2] | ||
+ | b=[4,5,6] | ||
+ | print a # stay the same | ||
+ | |||
+ | a={' | ||
+ | b=a[' | ||
+ | b=[4,5,6] | ||
+ | print a # stay the same | ||
+ | |||
+ | a={' | ||
+ | b=a[' | ||
+ | b[0]=4 | ||
+ | print a # changed ------- because it is a operation | ||
+ | |||
+ | a=[1,2, [3.1, | ||
+ | b=a[2][:] # fast copy | ||
+ | c=[4,5,6] | ||
+ | b=c | ||
+ | print a # stay the same | ||
+ | |||
+ | # | ||
+ | # example 4: | ||
+ | # ref: http:// | ||
+ | # explain: http:// | ||
+ | def foo(a=[]): | ||
+ | a.append(5) | ||
+ | return a | ||
+ | foo() # changed every time | ||
+ | |||
+ | ######################################## | ||
+ | # reference | ||
+ | ''' | ||
+ | # ref: http:// | ||
+ | Everything in Python is passed and assigned by value (like Java) | ||
+ | Every value in Python is a reference (pointer) to an object. | ||
+ | Objects cannot be values. | ||
+ | Assignment always copies the value (which is a pointer); | ||
+ | two such pointers can thus point to the same object. | ||
+ | Objects are never copied unless you're doing something explicit to copy them. | ||
+ | # ref: http:// | ||
+ | ???? | ||
+ | ''' | ||
+ | </ | ||
+ | |||
+ | ====== Common Python syntax ====== | ||
+ | |||
+ | * python 101 - http:// | ||
+ | |||
+ | ^comment |# | | ||
+ | ^print |print | | ||
+ | ^string |var=" | ||
+ | ^long string |%%varL=''' | ||
+ | ^raw string |r"Any dangerous Character here" | | ||
+ | |||
+ | ^os navigation | ^file operation | ^string operation | ^lib | ^rename | | ||
+ | ^os.chdir('/ | ||
+ | ^os.getcwd() | ^tfile.write(' | ||
+ | ^os.ctermid() | ^tfile.close() | ^str1+str2 |concatenate ^re |regular expression ^end_remove_fixed | | ||
+ | ^os.uname() | ^tfile.read() | ^str(100) |string convert ^ | ^end_add_fixed | | ||
+ | ^os.listdir('/ | ||
+ | ^os.mkdir('/ | ||
+ | ^os.removedirs('/ | ||
+ | ^os.rename(src, | ||
+ | ^os.getenv(' | ||
+ | ^ | ^ | ^a? |may have one ^ | ^ | | ||
+ | ^ | ^ | ^a{1,3} |May 1~3 one ^ | ^ | | ||
+ | ^ | ^ | ^r”str” |raw string ^ | ^ | | ||
+ | ^regular expression | ^ | ^ | ^ | ^ | | ||
+ | ^ | ^ | ^ | ^ | ^ | | ||
+ | http:// | ||
+ | |||
+ | |||
+ | ====== Python based tool and application ====== | ||
+ | * [[http:// | ||
+ | |||
+ | * http:// | ||
+ | * Python documentation generator | ||
+ | |||
+ | * XML to PDF generation using Python | ||
+ | * http:// | ||
+ | |||
+ | * Python add-on and libs | ||
+ | * Python image library (PIL): http:// | ||
+ | * Python EXIF.py: http:// | ||
+ | * demo of usage: http:// | ||
+ | * minimal EXIF reader and writer: http:// | ||
+ | * 50 python lib list: http:// | ||
+ | |||
+ | * a Chinese blog on python usage: http:// | ||
+ | |||
+ | ** Python web applications ** | ||
+ | * https:// | ||
+ | * http:// | ||
+ | * http:// | ||
+ | ====== Python GUI ====== | ||
+ | * Python GUI option list: http:// | ||
+ | * web platform: PyJamas | ||
+ | * desktop platform: QT, wxWidget | ||
+ | |||
+ | * GUI design: | ||
+ | * wxGlade: http:// | ||
+ | * wxFormBuilder: | ||
+ | |||
+ | * IDE: | ||
+ | * Eric: http:// | ||
+ | |||
+ | ====== wxPython ====== | ||
+ | |||
+ | |||
+ | ===== wxPython GUI concept quick guide ===== | ||
+ | |||
+ | * main build block | ||
+ | * A Frame is a top-level window. | ||
+ | |||
+ | |||
+ | ===== wxWidget - wxPython ===== | ||
+ | |||
+ | * download: http:// | ||
+ | * youtube video tutorial: http:// | ||
+ | |||
+ | |||
+ | * basic wxPython widget syntax and codes <code python> | ||
+ | # get wxWidget frame work, | ||
+ | import wx | ||
+ | |||
+ | # create class, since you are doing a App or a script | ||
+ | |||
+ | # inheriate a python window (so-called frame) | ||
+ | class myApp(wx.Frame): | ||
+ | # constructor, | ||
+ | def __init__(self, | ||
+ | wx.Frame.__init__(self, | ||
+ | panel=wx.Panel(self) | ||
+ | | ||
+ | #bitmap button | ||
+ | pic=wx.Image(' | ||
+ | myBtn=wx.BitmapButton(panel, | ||
+ | self.Bind(wx.EVT_BUTTON, | ||
+ | myBtn.SetDefault() | ||
+ | | ||
+ | #slider | ||
+ | slider=wx.Slider(panel, | ||
+ | slider.SetTickFreq(5, | ||
+ | | ||
+ | # spinner | ||
+ | spinner=wx.SpinCtrl(panel, | ||
+ | spinner.SetRange(1, | ||
+ | spinner.SetValue(10) | ||
+ | | ||
+ | # checkbox | ||
+ | wx.CheckBox(panel, | ||
+ | wx.CheckBox(panel, | ||
+ | wx.CheckBox(panel, | ||
+ | |||
+ | # combo box | ||
+ | mylist=[' | ||
+ | cbox=wx.ListBox(panel, | ||
+ | cbox.SetSelection(0) | ||
+ | |||
+ | # event handlers | ||
+ | def btnAct(self, | ||
+ | self.Destroy() | ||
+ | |||
+ | if __name__==' | ||
+ | app=wx.PySimpleApp() # application obj | ||
+ | frame=myClass(parent=None, | ||
+ | frame.Show() # show frame | ||
+ | app.MainLoop() # start app | ||
+ | </ | ||
+ | * wxWidget binding for python tutorial: http:// | ||
+ | |||
+ | * 2 Panel App Flow | ||
+ | * http:// | ||
+ | |||
+ | ===== Common wxPython syntax ===== | ||
+ | |||
+ | * prompts <code python> | ||
+ | #import wx.lib.agw.multidirdialog as MDD | ||
+ | import multidirdialog as MDD | ||
+ | def showMsg(msg): | ||
+ | wx.MessageBox(msg, | ||
+ | wx.OK | wx.ICON_INFORMATION) | ||
+ | |||
+ | import wx.lib.dialogs | ||
+ | def showTxt(txt): | ||
+ | ask = wx.lib.dialogs.ScrolledMessageDialog(None, | ||
+ | ask.ShowModal() | ||
+ | ask.Destroy() | ||
+ | |||
+ | def getInput(): | ||
+ | tmpT="" | ||
+ | ask = wx.TextEntryDialog( | ||
+ | None, 'Your input:', | ||
+ | ' | ||
+ | if ask.ShowModal() == wx.ID_OK: | ||
+ | print " | ||
+ | tmpT = ask.GetValue() | ||
+ | ask.Destroy() | ||
+ | return tmpT | ||
+ | |||
+ | def getFolder(): | ||
+ | tmpPath="" | ||
+ | dialog = wx.DirDialog ( None, message = ' | ||
+ | if dialog.ShowModal() == wx.ID_OK: | ||
+ | print ' | ||
+ | tmpPath = dialog.GetPath() | ||
+ | else: | ||
+ | print 'No directory.' | ||
+ | dialog.Destroy() | ||
+ | return tmpPath | ||
+ | |||
+ | |||
+ | def getFolders(): | ||
+ | tmpPaths="" | ||
+ | ask = MDD.MultiDirDialog(None, | ||
+ | if ask.ShowModal() == wx.ID_OK: | ||
+ | tmpPaths = ask.GetPaths() | ||
+ | print "You chose the following file(s):" | ||
+ | for path in tmpPaths: | ||
+ | print path | ||
+ | ask.Destroy() | ||
+ | return tmpPaths | ||
+ | |||
+ | def getFile(): | ||
+ | tmpPaths="" | ||
+ | wildcard = " | ||
+ | ask = wx.FileDialog(None, | ||
+ | if ask.ShowModal() == wx.ID_OK: | ||
+ | tmpPaths = ask.GetPaths() | ||
+ | print " | ||
+ | for path in tmpPaths: | ||
+ | print path | ||
+ | ask.Destroy() | ||
+ | return tmpPaths | ||
+ | |||
+ | def saveFile(): | ||
+ | tmpPaths="" | ||
+ | wildcard = " | ||
+ | ask = wx.FileDialog(None, | ||
+ | if ask.ShowModal() == wx.ID_OK: | ||
+ | tmpPath = ask.GetPath() | ||
+ | print "Save file:", | ||
+ | ask.Destroy() | ||
+ | return tmpPath | ||
+ | | ||
+ | def getColor(): | ||
+ | ask = wx.ColourDialog(None) | ||
+ | ask.GetColourData().SetChooseFull(True) | ||
+ | if ask.ShowModal() == wx.ID_OK: | ||
+ | data = ask.GetColourData() | ||
+ | print 'You selected: %s\n' % str(data.GetColour().Get(includeAlpha=False)) | ||
+ | ask.Destroy() | ||
+ | return data.GetColour().Get(includeAlpha=False) | ||
+ | |||
+ | def getChoice(): | ||
+ | tmpC="" | ||
+ | ask = wx.SingleChoiceDialog( | ||
+ | None, " | ||
+ | [" | ||
+ | wx.CHOICEDLG_STYLE | ||
+ | ) | ||
+ | if ask.ShowModal() == wx.ID_OK: | ||
+ | tmpC = ask.GetStringSelection() | ||
+ | print ' | ||
+ | ask.Destroy() | ||
+ | return tmpC | ||
+ | |||
+ | def getChoices(): | ||
+ | tmpCs=[] | ||
+ | list = [" | ||
+ | ask = wx.MultiChoiceDialog( None, | ||
+ | " | ||
+ | " | ||
+ | |||
+ | if (ask.ShowModal() == wx.ID_OK): | ||
+ | selections = ask.GetSelections() | ||
+ | strings = [list[x] for x in selections] | ||
+ | print "You chose:" | ||
+ | tmpCs = strings | ||
+ | ask.Destroy() | ||
+ | return tmpCs | ||
+ | | ||
+ | application = wx.PySimpleApp() | ||
+ | </ | ||
+ | * all dialog reference: | ||
+ | * http:// | ||
+ | * http:// | ||
+ | |||
+ | |||
+ | |||
+ | ====== PyQt ====== | ||
+ | |||
+ | * check [[devwiki: | ||
+ | ====== Python Portable for Windows ====== | ||
+ | |||
+ | * since all mac and linux have python built-in | ||
+ | |||
+ | **Workflow on portable python** | ||
+ | |||
+ | - Prepare python 2.7/3.5, by download the official python exe, and install it to D drive | ||
+ | * https:// | ||
+ | * for Python3.5.2: | ||
+ | * for Python2.7.12: | ||
+ | - update: for PyQt and PySide, just cd to that python directory and .\python.exe -m pip install PySide or PyQt4 to install that module with pip or ./python for mac/linux | ||
+ | - < | ||
+ | * < | ||
+ | * < | ||
+ | * < | ||
+ | - other library: | ||
+ | * cx_Freeze | ||
+ | |||
+ | ====== Python Portable for Mac ====== | ||
+ | |||
+ | * Python 2.7 is built-in in Mac at / | ||
+ | * There are many articles on install latest python 2.7 and 3.x version with many methods, like homebrew and offical python site, while my idea is not touch any system path or system environment, | ||
+ | * the advantage is you choose which python to run the py script | ||
+ | * the disadvantage is you can't default python the_script.py in your command line, so you should always use a launch bash script to dynamically use which python path and open the script with it. | ||
+ | * check my App_V9.bat launch for windows: https:// | ||
+ | |||
+ | **Standard Install Python 3.8** | ||
+ | * download and install python3 installer | ||
+ | * download and install command line tools for xcode latest (use normal Apple acc to login) | ||
+ | * https:// | ||
+ | * install PySide2 (with user flag that fixes permission issue) <code bash> | ||
+ | * now python3 work in terminal app | ||
+ | * when first run, allow Access folder right. | ||
+ | * to make command extension file runable, do bash for the command extension launcher <code bash> | ||
+ | ====== Python Cool Tricks and Notes ====== | ||
+ | |||
+ | * start HTML and FILE server in current directory <code dos> | ||
+ | * decimal vs float for real life accounting usage: | ||
+ | * decimal wont have those float annoying issue with tons of 0s after . | ||
+ | * decimal deal number like human do instead of infinite computing accuracy | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * < | ||
+ | |||
+ | |||
+ | * python and whatsapp msg | ||
+ | * ref: https:// | ||
+ | * **pywhatkit**: | ||
+ | * because it use automation, so interaction with browser can be buggy, no quick repeat sending (since automate like human action, need wait response of other app update), send group chat may send to wrong group if you also interact with browser | ||
+ | * example< | ||
+ | import pywhatkit | ||
+ | pywhatkit.sendwhatmsg_instantly(" | ||
+ | # wait 10s to ui response, close tab true after 3s, | ||
+ | # you need to close tab as whatsapp web only allow 1 window active | ||
+ | </ | ||
+ | * **selenium**: | ||
+ | * example setup and login manually for first time <code python> | ||
+ | my_drive = None | ||
+ | def drive_setup(): | ||
+ | from selenium import webdriver | ||
+ | from selenium.webdriver.common.keys import Keys | ||
+ | from selenium.webdriver.common.by import By | ||
+ | | ||
+ | my_drive = webdriver.Chrome() | ||
+ | phone_no = " | ||
+ | my_drive.get(f' | ||
+ | |||
+ | def drive_msg(in_text): | ||
+ | from selenium.webdriver.common.by import By | ||
+ | if my_drive is None: | ||
+ | return | ||
+ | else: | ||
+ | chat_box = my_drive.find_element(by=By.XPATH, | ||
+ | chat_box.send_keys(in_text) | ||
+ | send_button = my_drive.find_element(by=By.CSS_SELECTOR, | ||
+ | send_button.click() | ||
+ | </ | ||
+ | |||
+ | ====== Python and interaction with other API ====== | ||
+ | |||
+ | Telegram | ||
+ | - search @BotFather on telegram | ||
+ | * manual: https:// | ||
+ | - in the chat, type /newbot, then type your bot " | ||
+ | - now, your bot api key will show up, copy and save it | ||
+ | - now search your bot " | ||
+ | - in python, use requests to get the chat from the bot, try one more time if no result <code python> | ||
+ | import requests | ||
+ | the_key = " | ||
+ | url = " | ||
+ | response = requests.get(url) | ||
+ | result = response.json() | ||
+ | print(result) | ||
+ | </ | ||
+ | - once you got result in json, you will find the chat id. <code python> | ||
+ | # the list of all chat spec your bot received, yours is likely the first one. | ||
+ | my_chat_info = result[' | ||
+ | my_msg_info = my_chat_info[0][' | ||
+ | # it got info of: chat, date, from, message_id, text | ||
+ | my_chat_id = my_msg_info[' | ||
+ | </ | ||
+ | - to send a text to that chat from your bot side <code python> | ||
+ | reply_text = 'hello world' | ||
+ | url = " | ||
+ | response = requests.get(url) | ||
+ | </ | ||
+ | - now, you should have got the reply from your bot <code python> | ||
+ | result = response.json() | ||
+ | send_state = result[' | ||
+ | send_result = result[' | ||
+ | # chat (first_name, | ||
+ | </ | ||