目录
一、Python3 AI编程助手
在VSCode中使用Fitten Code插件
二、如何正确执行windows下的命令并不出乱码
windows下默认是gbk编码命令行字符串。
import subprocess
# 定义要运行的命令
command = "date /T"
# 使用subprocess模块运行命令
process = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
# 获取命令的输出结果
output, error = process.communicate()
# 打印输出结果
print(output.decode("gbk")) # 根据命令行编码进行解码
# 打印错误信息
if error:
print(error.decode("gbk")) # 根据命令行编码进行解码
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
三、批量启动并发任务
python建议:
- 使用多线程处理I/O等待
- 使用多进程处理CPU受限
使用concurrent.futures来批量启动并发任务——通过进程/线程池。
1. 等待进程/线程池中的任务全部完成再返回
from concurrent import futures
import math
import time
def calc(val):
time.sleep(1)
result = math.sqrt(float(val))
print(val, "sqrt:", result)
return result
def use_threads(num, values):
t1 = time.time()
with futures.ThreadPoolExecutor(num) as tex:
results = tex.map(calc, values)
for res in results:
print("threads:", res)
t2 = time.time()
return t2 - t1
def use_processes(num, values):
t1 = time.time()
with futures.ProcessPoolExecutor(num) as pex:
results = pex.map(calc, values)
for res in results:
print("processes:", res)
t2 = time.time()
return t2 - t1
def main(workers, values):
print(f"Using {workers} workers for {len(values)} values")
t_sec = use_threads(workers, values)
print(f"Threads took {t_sec:.4f} seconds")
p_sec = use_processes(workers, values)
print(f"Processes took {p_sec:.4f} seconds")
if __name__ == "__main__":
v = input("workers: ")
workers = int(v)
values = list(range(1, 6)) # 1 .. 5
main(workers, values)
- 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.
2. 不等待并第一时间返回
from concurrent import futures
import math
def calc(val):
result = math.sqrt(float(val))
return val, result
def use_threads(num, values):
with futures.ThreadPoolExecutor(num) as tex:
tasks = [tex.submit(calc, value) for value in values]
for f in futures.as_completed(tasks):
yield f.result()
def use_processes(num, values):
with futures.ProcessPoolExecutor(num) as pex:
tasks = [pex.submit(calc, value) for value in values]
for f in futures.as_completed(tasks):
yield f.result()
def main(workers, values):
print(f"Using {workers} workers for {len(values)} values")
print("Using threads:")
for val, result in use_threads(workers, values):
print(f"{val} {result:.4f}")
print("Using processes:")
for val, result in use_processes(workers, values):
print(f"{val} {result:.4f}")
if __name__ == "__main__":
v = input("workers: ")
workers = int(v)
values = list(range(1, 6)) # 1 .. 5
main(workers, values)
- 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.
yield用于第一时间返回结果。
四、事件驱动的异步执行
借助于gevent实现。安装gevent:
使用gevent版本的socket
使用猴子补丁的socket
使用gevent实现的ping——借助于gevent.socket的相关函数
import gevent.time
from gevent.socket import gethostbyname, create_connection
def ping(host, count=1, timeout=2):
"""
Ping a host count times, with a given timeout.
:param host: The host to ping.
:param count: The number of times to ping.
:param timeout: The timeout in seconds.
:return: A list of floats representing the ping times in seconds.
"""
ip = gethostbyname(host)
ping_times = []
for _ in range(count):
start = gevent.time.time()
try:
create_connection((ip, 80), timeout=timeout).close()
end = gevent.time.time()
ping_times.append(end - start)
except gevent.timeout.Timeout:
ping_times.append("Request timed out.")
return ping_times
# 使用示例
if __name__ == "__main__":
host = "www.sina.com"
ping_times = ping(host, count=4, timeout=2)
for ping_time in ping_times:
print(ping_time)
- 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.
使用gevent的猴子补丁来实现windows下的批量ping
import gevent
from gevent.monkey import patch_all
patch_all() # 打猴子补丁
import subprocess
ping_cmd = "ping -n 1 "
def ping(host):
"""
发送ping命令并等待响应
这里shell=True表示要通过shell来发送命令,此时命令部分使用的是字符串。
如果不使用shell=True,则表示不使用shell来发送命令,此时命令部分要使用列表,比如:
['ping', '-c', '1', host]
"""
p = subprocess.Popen(
ping_cmd + host, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
stdout, stderr = p.communicate()
if "往返行程的估计时间(以毫秒为单位):" in stdout.decode("gbk"):
print(f"{host} is alive")
hosts = ["192.168.53." + str(i) for i in range(1, 255)] # 生成IP地址列表
jobs = [gevent.spawn(ping, host) for host in hosts] # 创建gevent任务列表
gevent.joinall(jobs, timeout=60) # 等待所有任务结束,最多等待60秒
- 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.
不论是gevent版本的函数,还是猴子补丁(monkey-patching)都只对Python代码起效,对C编写的库无效。
五、异步时间驱动网络框架twisted
twisted官网: https://twisted.org/
### knock_server.py
from twisted.internet import protocol, reactor
class Knock(protocol.Protocol):
def dataReceived(self, data):
r_data = str(data, encoding="utf-8")
print("Client:", r_data)
if r_data.startswith("Knock knock"):
response = "Who's there?"
else:
response = r_data + " who?"
print("Server:", response)
self.transport.write(bytes(response, encoding="utf-8"))
class KnockFactory(protocol.Factory):
def buildProtocol(self, addr):
return Knock()
reactor.listenTCP(8000, KnockFactory())
reactor.run()
### knock_client.py
from twisted.internet import reactor, protocol
class KnockClient(protocol.Protocol):
def connectionMade(self):
data = bytes("Knock knock", encoding="utf-8")
self.transport.write(data)
def dataReceived(self, data):
r_data = str(data, encoding="utf-8")
if r_data.startswith("Who's there?"):
response = bytes("Disappearing client", encoding="utf-8")
self.transport.write(response)
else:
self.transport.loseConnection()
reactor.stop()
class KnockFactory(protocol.ClientFactory):
protocol = KnockClient
def main():
f = KnockFactory()
reactor.connectTCP("localhost", 8000, f)
reactor.run()
if __name__ == "__main__":
main()
- 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.