python3 使用技巧

2021/8/2 pythonpython3

# 通用的package启动脚本

## 文件名称 Run.py

import os
import runpy
import sys

# 通用的启动路径
if __name__ == '__main__':
    path = os.path.dirname(sys.modules[__name__].__file__)
    path = os.path.join(path, '..')
    sys.path.insert(0, path)
    runpy.run_module('{0}.App'.format(os.getcwd().split(os.sep)[-1]), run_name="__main__", alter_sys=True)
1
2
3
4
5
6
7
8
9
10
11
12

# 下载依赖

pip install -i http://mirrors.aliyun.com/pypi/simple/  --trusted-host mirrors.aliyun.com pypiwin32
1

# pyinstaller 打包

pyinstaller -F -i icon/ideaCode.ico GetIdeaCode.py --exclude-module PyQt5 ^ --exclude-module pydoc
pyinstaller -D -p pycharts -i icon/analyzeInfo.ico analyzeNetworkDataSize/App.py
1
2
-F, –onefile 打包一个单个文件,如果你的代码都写在一个.py文件的话,可以用这个,如果是多个.py文件就别用 
-D, –onedir 打包多个文件,在dist中生成很多依赖文件,适合以框架形式编写工具代码,我个人比较推荐这样,代码易于维护 
-K, –tk 在部署时包含 TCL/TK -a, –ascii 不包含编码.在支持Unicode的python版本上默认包含所有的编码. 
-d, –debug 产生debug版本的可执行文件 
-w,–windowed,--noconsole 使用Windows子系统执行.当程序启动的时候不会打开命令行(只对Windows有效)
-c,–nowindowed,–console 使用控制台子系统执行(默认)(只对Windows有效)

pyinstaller -c xxxx.py 
pyinstaller xxxx.py --console

-s,–strip 可执行文件和共享库将run through strip.注意Cygwin的strip往往使普通的win32 Dll无法使用. 
-X, –upx 如果有UPX安装(执行Configure.py时检测),会压缩执行文件(Windows系统中的DLL也会)(参见note)
-o DIR, –out=DIR 指定spec文件的生成目录,如果没有指定,而且当前目录是PyInstaller的根目录,会自动创建一个用于输出(spec和生成的可执行文件)
的目录.如果没有指定,而当前目录不是PyInstaller的根目录,则会输出到当前的目录下. 
-p DIR, –path=DIR 设置导入路径(和使用PYTHONPATH效果相似).可以用路径分割符(Windows使用分号,Linux使用冒号)分割,指定多个目录.也可以使用多个-p参数来设置多个导入路径,让pyinstaller自己去找程序需要的资源 
–icon=<FILE.ICO>将file.ico添加为可执行文件的资源(只对Windows系统有效),改变程序的图标 
pyinstaller -i ico路径 xxxxx.py –icon=<FILE.EXE,N> 将file.exe的第n个图标添加为可执行文件的资源(只对Windows系统有效)
-v FILE, –version=FILE 将verfile作为可执行文件的版本资源(只对Windows系统有效)
-n NAME, –name=NAME 可选的项目(产生的spec的)名字.如果省略,第一个脚本的主文件名将作为spec的名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 通用的logger日志处理器

import logging
import os
import time
from logging import Handler, FileHandler, StreamHandler


class PathFileHandler(FileHandler):
    def __init__(self, path, filename, mode='a', encoding='utf-8', delay=False):
        if not os.path.exists(path):
            os.mkdir(path)
        self.baseFilename = os.path.join(path, filename)
        self.mode = mode
        self.encoding = encoding
        self.delay = delay
        if delay:
            Handler.__init__(self)
            self.stream = None
        else:
            StreamHandler.__init__(self, self._open())


class LoggerKit(object):
    # 日志级别关系映射
    level_relations = {
        'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING,
        'error': logging.ERROR, 'critical': logging.CRITICAL
    }

    def __init__(self, class_name=__name__, level='info', log_dir='log',
                 fmt='%(asctime)s.%(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
        self.logger = logging.getLogger(class_name)
        # 不传递给上级logger
        self.logger.propagate = 0
        self.logger.setLevel(self.level_relations.get(level))  # 设置日志级别
        self.directory = os.path.join(os.getcwd(), log_dir)
        format_str = logging.Formatter(fmt)  # 设置日志格式
        stream_handler = logging.StreamHandler()  # 往屏幕上输出
        stream_handler.setFormatter(format_str)
        file_handler = PathFileHandler(path=self.directory,
                                       filename='{date}.log'.format(
                                           date=time.strftime("deis_platform_api_%Y_%m_%d", time.localtime())),
                                       mode='a')
        file_handler.setFormatter(format_str)
        self.logger.addHandler(stream_handler)
        self.logger.addHandler(file_handler)

    def get_logger(self):
        return self.logger


LOGGER = LoggerKit()

if __name__ == "__main__":
    txt = "将信息打印到日志文件中......"
    log = LoggerKit(level='debug')
    log.logger.info(4)
    log.logger.info(5)
    log.logger.info(txt)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 通用的获取配置

import configparser

from ToolKit.kit.LoggerKit import LOGGER


class OptionKit:
    def __init__(self, *name):
        """获取基础配置"""
        self.default_file_name = 'config.ini'
        self.configKey = 'default'
        self.file_name = self.init_file_name(name)
        self.config = configparser.RawConfigParser()
        self.__init_read_file()

    def __init_read_file(self):
        self.config.read(self.file_name, encoding='utf-8-sig')
        # print(self.config.sections())

    def init_file_name(self, *name):
        if name is None or len(name) <= 1:
            return self.default_file_name
        else:
            return name[0]

    def get_conf(self, key, default=None):
        """获取某一个配置文件"""
        try:
            value = self.config.get(self.configKey, key)
            LOGGER.get_logger().info('get conf {0} value:{1}'.format(key, value))
            return value
        except configparser.NoSectionError as e:
            LOGGER.get_logger().info('get conf error: {0}  why: {1}'.format(key, e))
            return default
        except KeyError as e:
            LOGGER.get_logger().info('get conf error: {0}  why: {1}'.format(key, e))
            return default
        except configparser.NoOptionError as e:
            LOGGER.get_logger().info('get conf error: {0}  why: {1}'.format(key, e))
            return default

    def write_conf(self, key, value):
        """写入某一个配置文件"""
        self.config.set(self.configKey, key, value)

    def get_all_config_key(self):
        return self.config.items(self.configKey)

    def quote_config(self, value: str):
        """替换字符串中配置key的值到配置的值中"""
        items = self.get_all_config_key()
        for item in items:
            if len(value.split('%')) > 1 and item[0] in value:
                return value.replace('%{0}%'.format(item[0]), item[1])
        return value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
最后更新时间: 2024/7/9 15:11:02