-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
183 lines (100 loc) · 72.4 KB
/
atom.xml
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Jack博客</title>
<icon>https://www.gravatar.com/avatar/95f3e37cb3152e52109b4fbb1cf72e17</icon>
<subtitle>Jack博客</subtitle>
<link href="https://jackgithubtest.github.io/atom.xml" rel="self"/>
<link href="https://jackgithubtest.github.io/"/>
<updated>2021-11-10T09:54:37.887Z</updated>
<id>https://jackgithubtest.github.io/</id>
<author>
<name>Jack</name>
<email>[email protected]</email>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>centos编译安装Git</title>
<link href="https://jackgithubtest.github.io/2021/11/10/centos%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85Git/"/>
<id>https://jackgithubtest.github.io/2021/11/10/centos%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85Git/</id>
<published>2021-11-10T09:49:42.000Z</published>
<updated>2021-11-10T09:54:37.887Z</updated>
<content type="html"><![CDATA[<p>centos安装Git有两种方式,一种通过源安装,通过如下命今,即可一键安装成功:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum -y install git</span><br></pre></td></tr></table></figure><p>但是通过源安装的Git,目前最高版本是1.7,想要使用更多新功能、更新版本的Git,就只能通过编译安装的方式来进行安装了,下面就来具体介绍这种安装过程。</p><h5 id="1、先安装依赖包"><a href="#1、先安装依赖包" class="headerlink" title="1、先安装依赖包"></a><strong>1、先安装依赖包</strong></h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel</span><br></pre></td></tr></table></figure><h5 id="2、下载Git源码包,并解压"><a href="#2、下载Git源码包,并解压" class="headerlink" title="2、下载Git源码包,并解压"></a><strong>2、下载Git源码包,并解压</strong></h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /usr/local/src</span><br><span class="line">wget https://github.com/git/git/archive/v1.9.5.tar.gz</span><br><span class="line">tar -zxvf git-1.9.5.tar.gz</span><br></pre></td></tr></table></figure><h5 id="3、编译并安装"><a href="#3、编译并安装" class="headerlink" title="3、编译并安装"></a><strong>3、编译并安装</strong></h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cd git-1.9.5</span><br><span class="line">make configure</span><br><span class="line">./configure --prefix=/usr/local/ --with-iconv=/usr/local/libiconv/</span><br><span class="line">make && make install</span><br></pre></td></tr></table></figure><p><strong>4、make过程中可能有如下错误</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">make configure</span><br><span class="line">GIT_VERSION = 1.9.5</span><br><span class="line"> GEN configure</span><br><span class="line">/bin/sh: autoconf: command not found</span><br><span class="line">make: *** [configure] Error 127</span><br><span class="line"><span class="meta">#</span><span class="bash"> 解决方案</span></span><br><span class="line">yum install install autoconf automake libtool</span><br></pre></td></tr></table></figure><h5 id="5、查看Git版本"><a href="#5、查看Git版本" class="headerlink" title="5、查看Git版本"></a><strong>5、查看Git版本</strong></h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git --version</span><br></pre></td></tr></table></figure><p><strong>问题</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Can't locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3.</span><br><span class="line">BEGIN failed--compilation aborted at Makefile.PL line 3.</span><br><span class="line">make[1]: *** [perl.mak] Error 2</span><br><span class="line">make: *** [perl/perl.mak] Error 2</span><br><span class="line"><span class="meta">#</span><span class="bash"> make可能会有如下报错,不需要管,只需要git --version能显示git版本就是成功</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>centos安装Git有两种方式,一种通过源安装,通过如下命今,即可一键安装成功:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</sp</summary>
</entry>
<entry>
<title></title>
<link href="https://jackgithubtest.github.io/2021/10/09/guanmai-%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E7%A8%8B%E6%89%80%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<id>https://jackgithubtest.github.io/2021/10/09/guanmai-%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E7%A8%8B%E6%89%80%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/</id>
<published>2021-10-09T02:32:14.943Z</published>
<updated>2021-10-09T09:02:45.195Z</updated>
<content type="html"><![CDATA[<p>1、参数化</p><p>2、断言</p><p>3、update更新数据</p><p>4、用例关联</p><p>5、cert证书</p><ul><li>cert证书升级,导致无法链接grpc服务</li><li>解决方案:</li></ul>]]></content>
<summary type="html"><p>1、参数化</p>
<p>2、断言</p>
<p>3、update更新数据</p>
<p>4、用例关联</p>
<p>5、cert证书</p>
<ul>
<li>cert证书升级,导致无法链接grpc服务</li>
<li>解决方案:</li>
</ul>
</summary>
</entry>
<entry>
<title>语雀配置钉钉和企业微信webhook</title>
<link href="https://jackgithubtest.github.io/2021/09/30/%E8%AF%AD%E9%9B%80%E9%85%8D%E7%BD%AE%E9%92%89%E9%92%89%E5%92%8C%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1webhook/"/>
<id>https://jackgithubtest.github.io/2021/09/30/%E8%AF%AD%E9%9B%80%E9%85%8D%E7%BD%AE%E9%92%89%E9%92%89%E5%92%8C%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1webhook/</id>
<published>2021-09-30T02:52:53.000Z</published>
<updated>2021-09-30T03:44:31.065Z</updated>
<content type="html"><![CDATA[<h2 id="语雀如何配置钉钉或者企业微信机器人教程和坑"><a href="#语雀如何配置钉钉或者企业微信机器人教程和坑" class="headerlink" title="语雀如何配置钉钉或者企业微信机器人教程和坑"></a>语雀如何配置钉钉或者企业微信机器人教程和坑</h2><h6 id="1、首先需要钉钉新建一个机器人,钉钉机器人选择关键字选项,不要选择签名选项,不然无法推送"><a href="#1、首先需要钉钉新建一个机器人,钉钉机器人选择关键字选项,不要选择签名选项,不然无法推送" class="headerlink" title="1、首先需要钉钉新建一个机器人,钉钉机器人选择关键字选项,不要选择签名选项,不然无法推送"></a>1、首先需要钉钉新建一个机器人,钉钉机器人选择关键字选项,不要选择签名选项,不然无法推送</h6><h5 id="2、语雀端设置-在知识库-gt-设置-gt-消息推送-gt-添加webhook-钉钉webhook选择钉钉选项,若其他渠道机器人请选择其他渠道,支持企业微信和微信机器人"><a href="#2、语雀端设置-在知识库-gt-设置-gt-消息推送-gt-添加webhook-钉钉webhook选择钉钉选项,若其他渠道机器人请选择其他渠道,支持企业微信和微信机器人" class="headerlink" title="2、语雀端设置 在知识库->设置->消息推送->添加webhook 钉钉webhook选择钉钉选项,若其他渠道机器人请选择其他渠道,支持企业微信和微信机器人"></a>2、语雀端设置 在知识库->设置->消息推送->添加webhook 钉钉webhook选择钉钉选项,若其他渠道机器人请选择其他渠道,支持企业微信和微信机器人</h5><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/70136_image-20210930110153975.png" alt="image-20210930110153975"></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/97397_image-20210930110106441.png" alt="image-20210930110106441"></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/77290_image-20210930110135762.png" alt="image-20210930110135762"></p><h5 id="3、语雀推送消息到企业微信-配置和钉钉是一致的,如果不知道如何添加企业微信机器人,可以自行百度"><a href="#3、语雀推送消息到企业微信-配置和钉钉是一致的,如果不知道如何添加企业微信机器人,可以自行百度" class="headerlink" title="3、语雀推送消息到企业微信 配置和钉钉是一致的,如果不知道如何添加企业微信机器人,可以自行百度"></a>3、语雀推送消息到企业微信 配置和钉钉是一致的,如果不知道如何添加企业微信机器人,可以自行百度</h5><p><a href="https://zhuanlan.zhihu.com/p/92349571">企业微信机器人的快捷制作 - 知乎 (zhihu.com)</a></p><p>填写机器人名字和webhook地址后,点击添加就ok</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/17083_image-20210930110620413.png" alt="image-20210930110620413"></p><h4 id="配置webhook所遇到的坑"><a href="#配置webhook所遇到的坑" class="headerlink" title="配置webhook所遇到的坑"></a>配置webhook所遇到的坑</h4><p>问题:配置了webhook为什么无法推送消息,但是点击测试却能通过消息能发送,但是更新文章或发布文章却无法推送?</p><p>原因:在语雀未发布【开启自动发布】这个功能的时候其实这个问题是不会出现的,但是因为这个功能上线,导致了无法推送消息,仔细看官方的这个功能介绍,找到了这个问题所在,哦原来开启了自动发布功能就不会发送动态或消息</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/39682_image-20210930111216521.png" alt="image-20210930111216521"></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/49450_image-20210930113854852.png" alt="image-20210930113854852"></p><p><a href="https://www.yuque.com/yuque/blog/nyb4v9">https://www.yuque.com/yuque/blog/nyb4v9</a></p><p>解决方案:关闭开启自动发布的功能,消息推送成功,注:企业微信的webhook点击测试是无反应的,需要自动更新文章或者发布文章触发</p><h4 id="最后效果:"><a href="#最后效果:" class="headerlink" title="最后效果:"></a>最后效果:</h4><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/42522_image-20210930111321412.png" alt="image-20210930111321412"></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/30/83308_image-20210930111344233.png" alt="image-20210930111344233"></p>]]></content>
<summary type="html"><h2 id="语雀如何配置钉钉或者企业微信机器人教程和坑"><a href="#语雀如何配置钉钉或者企业微信机器人教程和坑" class="headerlink" title="语雀如何配置钉钉或者企业微信机器人教程和坑"></a>语雀如何配置钉钉或者企业微信机器人教程和坑</</summary>
<category term="webhook" scheme="https://jackgithubtest.github.io/tags/webhook/"/>
</entry>
<entry>
<title>自动化多进程下问题</title>
<link href="https://jackgithubtest.github.io/2021/09/27/%E8%87%AA%E5%8A%A8%E5%8C%96%E5%A4%9A%E8%BF%9B%E7%A8%8B%E4%B8%8B%E9%97%AE%E9%A2%98/"/>
<id>https://jackgithubtest.github.io/2021/09/27/%E8%87%AA%E5%8A%A8%E5%8C%96%E5%A4%9A%E8%BF%9B%E7%A8%8B%E4%B8%8B%E9%97%AE%E9%A2%98/</id>
<published>2021-09-27T03:53:30.000Z</published>
<updated>2021-10-09T09:01:46.072Z</updated>
<content type="html"><![CDATA[<p>自动化痛点</p><ul><li>异步接口需要定时获取结果【未想到最优解决方式】</li><li>运行速度慢</li><li>容错性差,维护性差</li><li>不能很好的兼容多进程方式运行</li><li>多进程下运行session块被重复运行,初始化代码被多次初始化覆盖删除,多个session的文件锁</li><li>多进程下api层单例所遇问题</li><li>多进程下token的设计</li><li>多进程下数据共享问题</li></ul><p>解决:</p><p>1、运行速度慢,我们可以采用多进程方式下去执行自动化,有pytest提供的常用插件pytest-xsdit 插件,插件用法就是一条命令这里就不过多解释了</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pytest -n <span class="number">2</span> <span class="built_in">dir</span></span><br></pre></td></tr></table></figure><p>采用此插件就能很好的解决多进程吗?答案是肯定是不是的:相信大家都知道session是一个进程是一个会话,那多个进程相比是有多个会话了?我们来验证我们的想法</p><p>目录结构为</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">comm</span><br><span class="line">__init__.py</span><br><span class="line">testcase</span><br><span class="line">test_*.py</span><br><span class="line">export</span><br><span class="line">allure</span><br><span class="line">html</span><br><span class="line">conftest.py</span><br><span class="line">run.py</span><br></pre></td></tr></table></figure><p>conftest.py</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/93034_image-20210927143425947.png" alt="image-20210927143425947"></p><p>pytest-xdist自动分配了四个进程来执行我们的自动化,注:pytest-xdist的auto会根据电脑的内核自动分配进程【明明我的电脑是8核,明天就提刀去联想官方店,希望给我一个完美的解释】</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/36702_image-20210927143220236.png" alt="image-20210927143220236"></p><p>由此可见,我们session级别的conftest被执行多次,说明session确实会存在问题,那要如何解决呢?</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/70973_image-20210927144512429.png" alt="image-20210927144512429"></p><p>看到了pytest-xdist官方解决方案</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> pytest</span><br><span class="line"><span class="keyword">from</span> filelock <span class="keyword">import</span> FileLock</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@pytest.fixture(<span class="params">scope=<span class="string">"session"</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">session_data</span>(<span class="params">tmp_path_factory, worker_id</span>):</span></span><br><span class="line"> <span class="keyword">if</span> worker_id == <span class="string">"master"</span>:</span><br><span class="line"> <span class="comment"># not executing in with multiple workers, just produce the data and let</span></span><br><span class="line"> <span class="comment"># pytest's fixture caching do its job</span></span><br><span class="line"> <span class="keyword">return</span> produce_expensive_data()</span><br><span class="line"></span><br><span class="line"> <span class="comment"># get the temp directory shared by all workers</span></span><br><span class="line"> root_tmp_dir = tmp_path_factory.getbasetemp().parent</span><br><span class="line"></span><br><span class="line"> fn = root_tmp_dir / <span class="string">"data.json"</span></span><br><span class="line"> <span class="keyword">with</span> FileLock(<span class="built_in">str</span>(fn) + <span class="string">".lock"</span>):</span><br><span class="line"> <span class="keyword">if</span> fn.is_file():</span><br><span class="line"> data = json.loads(fn.read_text())</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> data = produce_expensive_data()</span><br><span class="line"> fn.write_text(json.dumps(data))</span><br><span class="line"> <span class="keyword">return</span> data</span><br></pre></td></tr></table></figure><p>看到官方给的解决方案其实是采用FileLock文件锁的方式进行解决,亲测,完全可以解决此问题</p><p>2、第二种多进程方案multprocessing Pool</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/52247_image-20210927145749854.png" alt="image-20210927145749854"></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/45210_image-20210927145740377.png" alt="image-20210927145740377"></p><p>自动化是按照模块进行多进程执行,有多少模块启动多少个进程</p><p>为什么要用apply_async呢?因为他是非阻塞异步的, 他不会等待子进程执行完毕, 主进程会继续执行, 他会根据系统调度来进行进程切换</p><p>有不懂的吗?</p><p>不懂的话自己去敲代码吧,算了解释一下吧,我们来看一个栗子【比较好吃的那种】</p><p>首先我们看一下apply()阻塞异步</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">doIt</span>(<span class="params">num</span>):</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"Process num is : %s"</span> % num)</span><br><span class="line"> time.sleep(<span class="number">1</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'process %s end'</span> % num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'mainProcess start'</span>)</span><br><span class="line"> <span class="comment"># 记录一下开始执行的时间</span></span><br><span class="line"> start_time = time.time()</span><br><span class="line"> <span class="comment"># 创建三个子进程</span></span><br><span class="line"> pool = Pool(<span class="number">3</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'Child start'</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>):</span><br><span class="line"> pool.apply(doIt, [i])</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'mainProcess done time:%s s'</span> % (time.time() - start_time))</span><br></pre></td></tr></table></figure><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/67631_image-20210927151339788.png" alt="image-20210927151339788"></p><p><strong>执行结果</strong> 我们可以看到, 主进程开始执行之后, 创建的三个子进程也随即开始执行, 主进程被阻塞, 这里跟上一篇文章介绍的<code>join()</code> 很类似, 而且接下来三个子进程是一个接一个按顺序地执行, 等到子进程全部执行完毕之后, 主进程就会继续执行, 打印出最后一句,</p><p>接下来我们看看apply_asyn()</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">doIt</span>(<span class="params">num</span>):</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"Process num is : %s"</span> % num)</span><br><span class="line"> time.sleep(<span class="number">1</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'process %s end'</span> % num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'mainProcess start'</span>)</span><br><span class="line"> <span class="comment"># 记录一下开始执行的时间</span></span><br><span class="line"> start_time = time.time()</span><br><span class="line"> <span class="comment"># 创建三个子进程</span></span><br><span class="line"> pool = Pool(<span class="number">3</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'Child start'</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>):</span><br><span class="line"> pool.apply_async(doIt, [i])</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'mainProcess done time:%s s'</span> % (time.time() - start_time))</span><br></pre></td></tr></table></figure><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/21256_image-20210927151549546.png" alt="image-20210927151549546"></p><p>OMG发生了什么,怎么之有一个主进程执行了?我的子进程呢?</p><p>我们来看看运行结果 , 可以看出来, 截图的第一句是上一个程序的执行消耗时间, 最后一句是使用<strong>apply_async()</strong> 所消耗的时间, 在这里, 主进程没有被阻塞, 验证了他是非阻塞的, 子进程没有执行, 验证了他是根据系统调度完成的, 为什么会这样呢?<br>原因是, 进程的切换时操作系统控制的, 我们首先运行的是主进程, 而CPU运行得又很快, 快到还没等系统调度到子线程, 主线程就已经运行完毕了, 并且退出程序. 所以子进程就没有运行了.</p><p>那我 调用了apply_async() 是不是就不能运行子进程了吗? 肯定可以呀!!小老弟,想啥呢??</p><p>还记得**join()**告诉主进程老子要运行子进程就好呀, 还记得 join()的作用吗, 他可以阻塞主进程, 等待所有子进程结束之后再运行, 我们在</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">print('mainProcess done time:%s s' % (time.time() - start_time))</span><br></pre></td></tr></table></figure><p> 执行之前加入两句代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pool.close()</span><br><span class="line">pool.join()</span><br></pre></td></tr></table></figure><p>我们先要 close()一下子进程, 而且要先在 join() 前运行它,不逼逼赖赖,上代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">doIt</span>(<span class="params">num</span>):</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"Process num is : %s"</span> % num)</span><br><span class="line"> time.sleep(<span class="number">1</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'process %s end'</span> % num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'mainProcess start'</span>)</span><br><span class="line"> <span class="comment"># 记录一下开始执行的时间</span></span><br><span class="line"> start_time = time.time()</span><br><span class="line"> <span class="comment"># 创建三个子进程</span></span><br><span class="line"> pool = Pool(<span class="number">3</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'Child start'</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>):</span><br><span class="line"> pool.apply_async(doIt, [i])</span><br><span class="line"> pool.close()</span><br><span class="line"> pool.join()</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'mainProcess done time:%s s'</span> % (time.time() - start_time))</span><br></pre></td></tr></table></figure><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/13250_image-20210927152537833.png" alt="image-20210927152537833"></p><p>这是什么速度,这也太快了,比**apply()**快了六倍?</p><p>我们看看加入这两句的运行结果, 首先我们可以看到即使是使用了非阻塞主进程的apply_async() 也能让子进程运行了, 在这里子进程按顺序交替运行了,<br>CPU在执行第一个子进程的时候, 还没等第一个子进程结束, 系统调度到了按顺序调度到了第二个子进程, 以此类推, 一直调度运行子进程, 一个接一个地结束子进程的运行, 最后运行主进程, 而且我们可以看到使用apply_async()的执行效力会更高, 你看一下他们各自执行结果最后一句的执行消耗时间就知道了, 这也是官方推荐我们使用apply_async()的主要原因吧</p><h4 id="还有一个非常重要的原因win上multprocessing和linux下的multprocessing的区别-相当于说为什么windows下需要freeze-support"><a href="#还有一个非常重要的原因win上multprocessing和linux下的multprocessing的区别-相当于说为什么windows下需要freeze-support" class="headerlink" title="还有一个非常重要的原因win上multprocessing和linux下的multprocessing的区别,相当于说为什么windows下需要freeze_support()"></a>还有一个非常重要的原因win上multprocessing和linux下的multprocessing的区别,相当于说为什么windows下需要freeze_support()</h4><p>Windows下面的multiprocessing跟Linux下面略有不同,Linux下面的multiprocessing基于fork,fork之后所有的本地变量都复制一份,因此可以使用任意的全局变量;<br>在Windows下面,多进程是通过启动新进程完成的,所有的全局变量都是重新初始化的,在运行过程中动态生成、修改过的全局变量是不能使用的。</p><p>multiprocessing内部使用pickling传递map的参数到不同的进程,当传递一个函数或类时,pickling将函数或者类用所在模块+函数/类名的方式表示,<br>如果对端的Python进程无法在对应的模块中找到相应的函数或者类,就会出错。<br>当你在Interactive Console当中创建函数的时候,这个函数是动态添加到__main__模块中的,在重新启动的新进程当中不存在,所以会出错。<br>当不在Console中,而是在独立Python文件中运行时,你会遇到另一个问题:由于你下面调用multiprocessing的代码没有保护,<br>在新进程加载这个模块的时候会重新执行这段代码,创建出新的multiprocessing池,无限调用下去。</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/34716_image-20210927153035952.png" alt="image-20210927153035952"></p><h5 id="好了扯了一大堆没有用的言归正传"><a href="#好了扯了一大堆没有用的言归正传" class="headerlink" title="好了扯了一大堆没有用的言归正传"></a>好了扯了一大堆没有用的言归正传</h5><p>那我们自己实现的多进程是不是也会有conftest的session问题呢?答案是肯定的,当然有了怎么会没有,自己去按照思路去实现一下吧</p><p>那既然官方解释是说通过FileLock来实现,那我们是不是也可以自己实现一个FileLock呢?最笨方法的那种,话不多说,说干就干</p><p><strong>conftest.py修改为</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> pytest</span><br><span class="line"><span class="keyword">from</span> loguru <span class="keyword">import</span> logger</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">log</span>():</span></span><br><span class="line"> logger.add(<span class="string">"aa.log"</span>, encoding=<span class="string">"UTF-8"</span>)</span><br><span class="line"> logger.info(<span class="string">"我是一个fixture,session级别的"</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@pytest.fixture(<span class="params">scope=<span class="string">"session"</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fixture_print</span>(<span class="params">request</span>):</span></span><br><span class="line"> <span class="keyword">import</span> inspect</span><br><span class="line"> call_name = inspect.stack()[<span class="number">1</span>].function</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"FileLock.lock"</span>, <span class="string">"r+"</span>, encoding=<span class="string">"UTF-8"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> <span class="keyword">if</span> call_name <span class="keyword">in</span> f.read():</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> f.write(call_name)</span><br><span class="line"> request.addfinalizer(log)</span><br><span class="line"> <span class="comment"># log()</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> pytest</span><br><span class="line"><span class="keyword">from</span> random <span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">from</span> filelock <span class="keyword">import</span> FileLock</span><br><span class="line"></span><br><span class="line"><span class="meta">@pytest.fixture(<span class="params">scope=<span class="string">"session"</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span>(<span class="params">tmp_path_factory, worker_id</span>):</span></span><br><span class="line"> <span class="comment"># 如果是单机运行 则运行这里的代码块【不可删除、修改】</span></span><br><span class="line"> <span class="keyword">if</span> worker_id == <span class="string">"master"</span>:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> 【自定义代码块】</span></span><br><span class="line"><span class="string"> 这里就写你要本身应该要做的操作,比如:登录请求、新增数据、清空数据库历史数据等等</span></span><br><span class="line"><span class="string"> """</span></span><br><span class="line"> token = <span class="built_in">str</span>(random())</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"fixture:请求登录接口,获取token"</span>, token)</span><br><span class="line"> os.environ[<span class="string">'token'</span>] = token</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 如果测试用例有需要,可以返回对应的数据,比如 token</span></span><br><span class="line"> <span class="keyword">return</span> token</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 如果是分布式运行</span></span><br><span class="line"> <span class="comment"># 获取所有子节点共享的临时目录,无需修改【不可删除、修改】</span></span><br><span class="line"> root_tmp_dir = tmp_path_factory.getbasetemp().parent</span><br><span class="line"> <span class="comment"># 【不可删除、修改】</span></span><br><span class="line"> fn = root_tmp_dir / <span class="string">"data.json"</span></span><br><span class="line"> <span class="comment"># 【不可删除、修改】</span></span><br><span class="line"> <span class="keyword">with</span> FileLock(<span class="built_in">str</span>(fn) + <span class="string">".lock"</span>):</span><br><span class="line"> <span class="comment"># 【不可删除、修改】</span></span><br><span class="line"> <span class="keyword">if</span> fn.is_file():</span><br><span class="line"> <span class="comment"># 缓存文件中读取数据,像登录操作的话就是 token 【不可删除、修改】</span></span><br><span class="line"> token = json.loads(fn.read_text())</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"读取缓存文件,token 是<span class="subst">{token}</span> "</span>)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> 【自定义代码块】</span></span><br><span class="line"><span class="string"> 跟上面 if 的代码块一样就行</span></span><br><span class="line"><span class="string"> """</span></span><br><span class="line"> token = <span class="built_in">str</span>(random())</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"fixture:请求登录接口,获取token"</span>, token)</span><br><span class="line"> <span class="comment"># 【不可删除、修改】</span></span><br><span class="line"> fn.write_text(json.dumps(token))</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"首次执行,token 是<span class="subst">{token}</span> "</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 最好将后续需要保留的数据存在某个地方,比如这里是 os 的环境变量</span></span><br><span class="line"> os.environ[<span class="string">'token'</span>] = token</span><br><span class="line"> <span class="keyword">return</span> token</span><br></pre></td></tr></table></figure><p>main.py修改为:</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/84579_image-20210927154156807.png" alt="image-20210927154308215"></p><p>结果:意外的惊喜,session只运行了一次</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/74105_image-20210927154802299.png" alt="image-20210927154802299"></p><p>注:我们只需要限制pytest的hook函数执行conftest的session,千万不能限制自定义的函数去调用session,否在会出现异常</p><h4 id="session问题二:如果我有多个session呢?你看这代码,得到pytest的hook都是call-fixture-func啊这要怎么搞?"><a href="#session问题二:如果我有多个session呢?你看这代码,得到pytest的hook都是call-fixture-func啊这要怎么搞?" class="headerlink" title="session问题二:如果我有多个session呢?你看这代码,得到pytest的hook都是call_fixture_func啊这要怎么搞?"></a>session问题二:如果我有多个session呢?你看这代码,得到pytest的hook都是call_fixture_func啊这要怎么搞?</h4><p>call_fixture_limit.py限制一下就好了啊,<strong>注:采用a+方式去写入文件的时候,需要调整指针</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">call_limit</span>():</span></span><br><span class="line"> <span class="string">"""限制多进程下fixture重复调用"""</span></span><br><span class="line"> <span class="keyword">import</span> inspect</span><br><span class="line"> call_name = inspect.stack()[<span class="number">1</span>].function</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"FileLock.lock"</span>, <span class="string">"a+"</span>, encoding=<span class="string">"UTF-8"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> f.seek(<span class="number">0</span>)</span><br><span class="line"> CALL_LIST = f.read().split(<span class="string">","</span>)</span><br><span class="line"> <span class="keyword">if</span> call_name <span class="keyword">in</span> CALL_LIST:</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> f.seek(<span class="number">2</span>)</span><br><span class="line"> f.write(<span class="string">f"<span class="subst">{call_name}</span>,"</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/49993_image-20210927173555822.png" alt="image-20210927173555822"></p><h4 id="问题三:多进程下执行失败会出现Cache问题,如何解决呢?不要慌,不是在报错就是在报错的路上"><a href="#问题三:多进程下执行失败会出现Cache问题,如何解决呢?不要慌,不是在报错就是在报错的路上" class="headerlink" title="问题三:多进程下执行失败会出现Cache问题,如何解决呢?不要慌,不是在报错就是在报错的路上"></a>问题三:多进程下执行失败会出现Cache问题,如何解决呢?不要慌,不是在报错就是在报错的路上</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">run</span>(<span class="params">index</span>):</span></span><br><span class="line"> <span class="keyword">import</span> time</span><br><span class="line"> pytest.main([<span class="string">"-v"</span>, <span class="string">f"<span class="subst">{index}</span>"</span>, <span class="string">"--cache-clear"</span>, <span class="string">"--alluredir=reports/allure"</span>])</span><br><span class="line"> time.sleep(<span class="number">1</span>)</span><br></pre></td></tr></table></figure><p>官方提供了专门的清除缓存的命令,是不是很银杏,但是用了这个命令又有问题了,有人就问了,这会有什么问题,怎么那么多问题,是的不要慌</p><p>采用了–cache-clear后呢会出现–lf命令的问题,因为lf失败重跑他是在缓存中去收集的,现在你把我缓存清掉了我怎么跑是吧,就很头疼了,所以呢可以提供一种解决思路,那就是手动去控制是否需要清除,如果不重跑呢?就清除,如果重跑呢?就不清除了,当然了有更好的解决方案可以提供一下给我</p><h4 id="问题四:多进程下多个session级别的fixtures文件之间互相调用问题,都说了不是在报错就是在报错的路上"><a href="#问题四:多进程下多个session级别的fixtures文件之间互相调用问题,都说了不是在报错就是在报错的路上" class="headerlink" title="问题四:多进程下多个session级别的fixtures文件之间互相调用问题,都说了不是在报错就是在报错的路上"></a>问题四:多进程下多个session级别的fixtures文件之间互相调用问题,都说了不是在报错就是在报错的路上</h4><p>问题:多个session级别的fixtures下会存在拿不到已经调用的fixtures文件的result,导致了获取不到值直接报错</p><p>解决方案:可以采用os.envircon来进行数据共享,记住,os.envircon只能设置字符串,一定要进行解析</p><h4 id="问题五:多进程下数据共享问题,会导致数据共享反射无法生效"><a href="#问题五:多进程下数据共享问题,会导致数据共享反射无法生效" class="headerlink" title="问题五:多进程下数据共享问题,会导致数据共享反射无法生效"></a>问题五:多进程下数据共享问题,会导致数据共享反射无法生效</h4><p>问题:参数化反射无法生效</p><p>解决方案:</p><p>可以写入整个系统的环境变量,例如os.environ[key]=value</p><p>思路就是重写object对象和metaclass元类的__setattr__魔术方法和__getattribute__方法</p><p>话不多说,完整代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ParamsPoolMetaClass</span>(<span class="params"><span class="built_in">type</span></span>):</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__new__</span>(<span class="params">cls, *args, **kwargs</span>):</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">super</span>().__new__(cls, *args, **kwargs)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getattribute__</span>(<span class="params">self, item</span>):</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> result = <span class="built_in">super</span>().__getattribute__(item)</span><br><span class="line"> <span class="keyword">except</span> (AttributeError, RecursionError) <span class="keyword">as</span> AE:</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> result = <span class="built_in">eval</span>(os.environ.get(item.upper()))</span><br><span class="line"> <span class="keyword">except</span> (SyntaxError, TypeError) <span class="keyword">as</span> SE:</span><br><span class="line"> result = os.environ.get(item.upper())</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__setattr__</span>(<span class="params">self, key, value</span>):</span></span><br><span class="line"> <span class="built_in">super</span>().__setattr__(key, value)</span><br><span class="line"> os.environ[key] = <span class="built_in">str</span>(value)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestParamsPool</span>(<span class="params">metaclass=ParamsPoolMetaClass</span>):</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getattribute__</span>(<span class="params">self, item</span>):</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> result = <span class="built_in">super</span>().__getattribute__(item)</span><br><span class="line"> <span class="keyword">except</span> (AttributeError, RecursionError) <span class="keyword">as</span> AE:</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> result = <span class="built_in">eval</span>(os.environ.get(item.upper()))</span><br><span class="line"> <span class="keyword">except</span> (SyntaxError, TypeError) <span class="keyword">as</span> SE:</span><br><span class="line"> result = os.environ.get(item.upper())</span><br><span class="line"> <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__setattr__</span>(<span class="params">self, key: <span class="built_in">str</span>, value</span>):</span></span><br><span class="line"> <span class="built_in">super</span>().__setattr__(key, value)</span><br><span class="line"> os.environ[key.upper()] = <span class="built_in">str</span>(value)</span><br></pre></td></tr></table></figure><h2 id="多进程下API层单例问题"><a href="#多进程下API层单例问题" class="headerlink" title="多进程下API层单例问题"></a>多进程下API层单例问题</h2><p>疑问:不就是多进程吗?我直接一个multprocessing.Pool()一顿操作就好了,不就是把我的代码给不同得人一起跑吗?还会有那么多花里胡哨的问题?你搁这搁这搁这呢?</p><p>如你所愿啊,多进程下单例确实会有问题,虽然是单例,但是在多进程下单例是无法挡住的,会重新申请开辟地址并且返回对象,啊这么神奇</p><p>那么如何解决呢?当然是加锁了,铐起来,叉出去,获取了枷锁是不是就跑不了了。【又不是人人都是武松,只是想不想的问题】</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">synchronized</span>(<span class="params">func</span>):</span></span><br><span class="line"> func.__lock__ = threading.Lock()</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">lock_func</span>(<span class="params">*args, **kwargs</span>):</span></span><br><span class="line"> <span class="keyword">with</span> func.__lock__:</span><br><span class="line"> <span class="keyword">return</span> func(*args, **kwargs)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> lock_func</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line"> isstance = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"><span class="meta"> @synchronized</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__new__</span>(<span class="params">cls, *args, **kwargs</span>):</span></span><br><span class="line"> <span class="keyword">if</span> cls.isstance <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line"> cls.isstance = <span class="built_in">super</span>().__new__(cls)</span><br><span class="line"> <span class="keyword">return</span> cls.isstance</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">printf</span>(<span class="params">self</span>):</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="built_in">id</span>(self))</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> <span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool</span><br><span class="line"></span><br><span class="line"> p = Pool(<span class="number">4</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">4</span>):</span><br><span class="line"> p.apply_async(Singleton().printf)</span><br><span class="line"> p.close()</span><br><span class="line"> p.join()</span><br></pre></td></tr></table></figure><p>运行结果:发现id都一样,是不是就实现了单例,这玩意竟然那么神奇</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/27/55784_image-20210927161824853.png" alt="image-20210927161824853"></p><h2 id="3、多进程下Token的设计"><a href="#3、多进程下Token的设计" class="headerlink" title="3、多进程下Token的设计"></a>3、多进程下Token的设计</h2><p>还是可以基于单例的思想进行设计Token,Token类去继承单例类,实例化一个Token对象,这样在整个过程采用的Token都是相同不会出现Token问题</p><h2 id="4、用例执行过慢,维护性差"><a href="#4、用例执行过慢,维护性差" class="headerlink" title="4、用例执行过慢,维护性差"></a>4、用例执行过慢,维护性差</h2><h4 id="疑问:为什么要选择多进程,为什么不选择多线程呢?是不是大家都有这种疑问"><a href="#疑问:为什么要选择多进程,为什么不选择多线程呢?是不是大家都有这种疑问" class="headerlink" title="疑问:为什么要选择多进程,为什么不选择多线程呢?是不是大家都有这种疑问"></a>疑问:为什么要选择多进程,为什么不选择多线程呢?是不是大家都有这种疑问</h4><p>其实多进程和多线程都可以,问题是,多线程的bug无法解决啊,所以曲线救国,那就用高资源来换取bug吧</p>]]></content>
<summary type="html"><p>自动化痛点</p>
<ul>
<li>异步接口需要定时获取结果【未想到最优解决方式】</li>
<li>运行速度慢</li>
<li>容错性差,维护性差</li>
<li>不能很好的兼容多进程方式运行</li>
<li>多进程下运行session块被重复运行,初始化代码被多</summary>
<category term="work,工作" scheme="https://jackgithubtest.github.io/tags/work-%E5%B7%A5%E4%BD%9C/"/>
</entry>
<entry>
<title>数据库乐观锁和悲观锁</title>
<link href="https://jackgithubtest.github.io/2021/09/03/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B9%90%E8%A7%82%E9%94%81%E5%92%8C%E6%82%B2%E8%A7%82%E9%94%81/"/>
<id>https://jackgithubtest.github.io/2021/09/03/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B9%90%E8%A7%82%E9%94%81%E5%92%8C%E6%82%B2%E8%A7%82%E9%94%81/</id>
<published>2021-09-03T03:52:39.000Z</published>
<updated>2021-09-30T03:36:03.104Z</updated>
</entry>
<entry>
<title>hexo+github搭建博客教程</title>
<link href="https://jackgithubtest.github.io/2021/09/01/hexo-github%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%E6%95%99%E7%A8%8B/"/>
<id>https://jackgithubtest.github.io/2021/09/01/hexo-github%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%E6%95%99%E7%A8%8B/</id>
<published>2021-09-01T02:43:01.000Z</published>
<updated>2021-09-30T03:36:03.102Z</updated>
<content type="html"><![CDATA[<p>阅读须知:</p><h1 id="GitHub-Pages是什么?"><a href="#GitHub-Pages是什么?" class="headerlink" title="GitHub Pages是什么?"></a>GitHub Pages是什么?</h1><p>GitHub Pages 是由 GitHub 官方提供的一种免费的静态站点托管服务,让我们可以在 GitHub 仓库里托管和发布自己的静态网站页面。</p><h1 id="Hexo是什么"><a href="#Hexo是什么" class="headerlink" title="Hexo是什么"></a>Hexo是什么</h1><p>Hexo 是一个快速、简洁且高效的静态博客框架,它基于 Node.js 运行,可以将我们撰写的 Markdown 文档解析渲染成静态的 HTML 网页。</p><h1 id="Hexo-GitHub发布原理"><a href="#Hexo-GitHub发布原理" class="headerlink" title="Hexo + GitHub发布原理"></a>Hexo + GitHub发布原理</h1><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/01/73214_image-20210901110630384.png" alt="image-20210901110630384"></p><h1 id="优点和不足"><a href="#优点和不足" class="headerlink" title="优点和不足"></a>优点和不足</h1><p><strong>优点:</strong>完全免费;静态站点,轻量快速;可按需求自由定制改造;托管在 GitHub,安全省心;迁移方便……</p><p><strong>不足:</strong>发文不便,依赖于本地环境;更适合个人博客使用;GitHub 在国内访问速度有点不快。【可以采用hosts文件修改github.com dns解析到对应的ip加快访问速度,Google浏览器可以下载IGG谷歌访问助手插件免费代理】</p><h1 id="环境安装"><a href="#环境安装" class="headerlink" title="环境安装"></a>环境安装</h1><p>Hexo 基于 Node.js,搭建过程中还需要使用 npm(Node.js 已带) 和 git,因此先搭建本地操作环境,安装 Node.js 和 Git。</p><ul><li>Node.js:<a href="https://link.zhihu.com/?target=https://nodejs.org/zh-cn">https://nodejs.org/zh-cn</a></li><li>Git:<a href="https://link.zhihu.com/?target=https://git-scm.com/downloads">https://git-scm.com/downloads</a></li></ul><p>下载 Node.js 和 Git 程序并安装,一路点 “下一步” 按默认配置完成安装。</p><p>进入cmd可以验证是否安装成功 node -v , npm -v 和git –version</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/09/01/22030_image-20210901111037848.png" alt="image-20210901111037848"></p><h2 id="Git链接GitHub"><a href="#Git链接GitHub" class="headerlink" title="Git链接GitHub"></a>Git链接GitHub</h2><p>使用邮箱注册GItHub 账户,选择免费账户,并完成邮件验证。</p><p>进入Git bash here</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name "GitHub 用户名"</span><br><span class="line">git config --global user.email "GitHub 邮箱"</span><br></pre></td></tr></table></figure><h5 id="创建SSH密钥:"><a href="#创建SSH密钥:" class="headerlink" title="创建SSH密钥:"></a>创建SSH密钥:</h5><p>ssh-keygen -t rsa -C “GitHub 邮箱” Github邮箱为你注册的邮箱</p><h5 id="添加密钥:"><a href="#添加密钥:" class="headerlink" title="添加密钥:"></a>添加密钥:</h5><p>进入你的家目录下找到隐藏文件.ssh把 id_rsa.pub 内容到 Key 中,点击 Add SSH key 完成添加。</p><h5 id="创建GitHub仓库"><a href="#创建GitHub仓库" class="headerlink" title="创建GitHub仓库"></a>创建GitHub仓库</h5><p>GitHub 主页右上角加号 -> New repository:</p><ul><li>Repository name 中输入 <code>用户名.github.io</code></li><li>勾选 “Initialize this repository with a README”</li><li>Description 选填</li></ul><p>填好后点击 Create repository 创建。</p>]]></content>
<summary type="html"><p>阅读须知:</p>
<h1 id="GitHub-Pages是什么?"><a href="#GitHub-Pages是什么?" class="headerlink" title="GitHub Pages是什么?"></a>GitHub Pages是什么?</h1><p>G</summary>
<category term="hexo+github" scheme="https://jackgithubtest.github.io/tags/hexo-github/"/>
</entry>
<entry>
<title>解决github.io无法打开的经历</title>
<link href="https://jackgithubtest.github.io/2021/08/30/%E8%A7%A3%E5%86%B3github-io%E6%97%A0%E6%B3%95%E6%89%93%E5%BC%80%E7%9A%84%E7%BB%8F%E5%8E%86/"/>
<id>https://jackgithubtest.github.io/2021/08/30/%E8%A7%A3%E5%86%B3github-io%E6%97%A0%E6%B3%95%E6%89%93%E5%BC%80%E7%9A%84%E7%BB%8F%E5%8E%86/</id>
<published>2021-08-30T06:13:31.000Z</published>
<updated>2021-09-30T03:36:03.108Z</updated>
<content type="html"><![CDATA[<p>记得之前有 github.com 打不开或者打开很慢的解决方案,现在轮到了 github.io,哈哈。我的 github.io 很久开始就打不开了,当时从网上试了几种方法没成功就放弃了,今天查资料需要打开 github.io,又有点时间,所以主要针对这个解决了一下。从本文您可以了解到:</p><ol><li><p>碰到这种dns的问题该怎么排查?</p></li><li><p>怎么解决打不开github.io的问题?</p><p>ping命令其实很强大,不仅可以知道能不能链接,延时是多少,还可以知道dns解析的ip地址是多少,例如我们ping <a href="http://www.github.com/">www.github.com</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">ping www.github.com</span><br><span class="line"></span><br><span class="line">正在 Ping github.com [52.74.223.119] 具有 32 字节的数据:</span><br><span class="line">来自 52.74.223.119 的回复: 字节=32 时间=208ms TTL=42</span><br><span class="line">来自 52.74.223.119 的回复: 字节=32 时间=198ms TTL=42</span><br><span class="line">来自 52.74.223.119 的回复: 字节=32 时间=202ms TTL=42</span><br><span class="line">来自 52.74.223.119 的回复: 字节=32 时间=207ms TTL=42</span><br><span class="line"></span><br><span class="line">52.74.223.119 的 Ping 统计信息:</span><br><span class="line"> 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),</span><br><span class="line">往返行程的估计时间(以毫秒为单位):</span><br><span class="line"> 最短 = 198ms,最长 = 208ms,平均 = 203ms</span><br></pre></td></tr></table></figure><p>可以看到,后面小括号里面的 52.74.223.119 就是 ip 地址了。</p></li></ol><p>ping github.io </p><blockquote><p>ping github.io</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">PING github.io (127.0.0.1): 56 data bytes</span><br><span class="line">64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.030 ms</span><br><span class="line">64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.105 ms</span><br><span class="line">64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.084 ms</span><br></pre></td></tr></table></figure><p>上面显示 ip 地址为<code>127.0.0.1</code>,这个就是本机地址嘛,然后我去<code>/etc/hosts</code>里面查看hosts文件有没有被意外修改过,没看到github.io被解析到<code>127.0.0.1</code>的记录,这就表示,<strong>电脑上的dns解析是完好的,但是远程的 dns 解析很可能惨遭网络运营商的污染了</strong>,从而导致解析的时候被解析到了<code>127.0.0.1</code>。</p><p>修改本机dns</p><p>修改dns的服务器地址,如下:如果【1】不行就试试【2】</p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/08/30/40194_image-20210830142139831.png" alt="image-20210830142139831"></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/08/30/89065_image-20210830142211754.png" alt="image-20210830142211754"></p><p>【1】修改dns为<code>114.114.114.114</code></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/08/30/60336_image-20210830142112590.png" alt="image-20210830142112590"></p><p>【2】修改dns为<code>223.5.5.5</code>与<code>223.6.6.6</code></p><p><img src="https://gitee.com/Jack_Gitee_Code/Ptoho_Iamge/raw/master/image/2021/08/30/34216_image-20210830142238446.png" alt="image-20210830142238446"></p><p>7、刷新DNS<br>【1】<code>win+r</code>:输入cmd,<br>【2】在命令提示符中键入<code>ipconfig/flushdns</code></p><p>8、即可访问地址中带<code>github.io</code>的网址。</p>]]></content>
<summary type="html"><p>记得之前有 github.com 打不开或者打开很慢的解决方案,现在轮到了 github.io,哈哈。我的 github.io 很久开始就打不开了,当时从网上试了几种方法没成功就放弃了,今天查资料需要打开 github.io,又有点时间,所以主要针对这个解决了一下。从本文您</summary>
<category term="碰到这种dns的问题该怎么排查?" scheme="https://jackgithubtest.github.io/categories/%E7%A2%B0%E5%88%B0%E8%BF%99%E7%A7%8Ddns%E7%9A%84%E9%97%AE%E9%A2%98%E8%AF%A5%E6%80%8E%E4%B9%88%E6%8E%92%E6%9F%A5%EF%BC%9F/"/>
<category term="怎么解决打不开github.io的问题?" scheme="https://jackgithubtest.github.io/categories/%E7%A2%B0%E5%88%B0%E8%BF%99%E7%A7%8Ddns%E7%9A%84%E9%97%AE%E9%A2%98%E8%AF%A5%E6%80%8E%E4%B9%88%E6%8E%92%E6%9F%A5%EF%BC%9F/%E6%80%8E%E4%B9%88%E8%A7%A3%E5%86%B3%E6%89%93%E4%B8%8D%E5%BC%80github-io%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%9F/"/>
<category term="GitHub" scheme="https://jackgithubtest.github.io/tags/GitHub/"/>
<category term="GitHub.io" scheme="https://jackgithubtest.github.io/tags/GitHub-io/"/>
</entry>
</feed>