python 同步代码改成异步的

import numpy as np
import tushare as ts
import aiohttp
import asyncio
import time
codes = ['787819', '787317', '787317', '600320', '600191', '600191', '600967', '600765', '600238', '603650']
cvs_30 = []
start = time.time()
async def get_index(code):
all_data = ts.get_hist_data(code, start='2020-05-12', end='2020-12-28')
if all_data is None:
cv_30 = 0
# 加入相对应的列表
cvs_30.append(cv_30)
else:
data = all_data['close']
cv_30 = np.std(data.head(30)) / np.mean(data.head(30))
# 加入相对应的列表
cvs_30.append(cv_30 * 1000)
tasks = [asyncio.ensure_future(get_index(code)) for code in codes]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))
end = time.time()
print(end - start)

python 同步代码改成异步的:各位大佬,下面是我写的读取tushare股票价格的大码,因为有多只股票,写成异步的,但是我写的代码执行后的效果还是同步的效果,请哪位大佬帮我修改下。

操,异步编程的类必须有_await_方法。现在大部分模块都不支持异步。还是用多线程或者多进程吧。

get_hist_data是阻塞模式?

异步IO的关键是非阻塞代码。

调用第三方库的方法用来读取他们数据库中的股票信息,应该是阻塞吧??

你代码缩进调一下,重发一下,我给你改一下

import numpy as np
import tushare as ts
import aiohttp
import asyncio
import time

codes = ['787819', '787317', '787317', '600320', '600191', '600191', '600967', '600765', '600238', '603650']  # 股票代码列表

cvs_30 = []
start = time.time()


async def get_index(code):
    all_data = ts.get_hist_data(code, start='2020-05-12', end='2020-12-28')
    if all_data is None:

        cv_30 = 0
        # 加入相对应的列表
        cvs_30.append(cv_30)
    else:
        data = all_data['close']
        cv_30 = np.std(data.head(30)) / np.mean(data.head(30))

        # 加入相对应的列表
        cvs_30.append(cv_30 * 1000)


tasks = [asyncio.ensure_future(get_index(code)) for code in codes]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))
end = time.time()

print(end - start)

 

import numpy as np
import tushare as ts
import aiohttp
import asyncio
import time
codes = ['787819', '787317', '787317', '600320', '600191', '600191', '600967', '600765', '600238', '603650']  # 股票代码列表
cvs_30 = []
start = time.time()
async def get_index(code):
    all_data = ts.get_hist_data(code, start='2020-05-12', end='2020-12-28')
    if all_data is None:
        cv_30 = 0
        # 加入相对应的列表
        cvs_30.append(cv_30)
    else:
        data = all_data['close']
        cv_30 = np.std(data.head(30)) / np.mean(data.head(30))
        # 加入相对应的列表
        cvs_30.append(cv_30 * 1000)

tasks = []
for i in codes: 
    tasks.append(get_index(i))
loop = asyncio.new_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
end = time.time()
print(end - start)

试试看

不行,你的代码是  1.7 秒左右 。  我用   for 循环是1.5秒

import numpy as np
import tushare as ts
import aiohttp
import asyncio
import time

codes = ['787819', '787317', '787317', '600320', '600191', '600191', '600967', '600765', '600238', '603650']  # 股票代码列表
cvs_30 = []
start = time.time()

for code in codes:
    all_data = ts.get_hist_data(code, start='2020-05-12', end='2020-12-28')
    if all_data is None:
        cv_30 = 0
        # 加入相对应的列表
        cvs_30.append(cv_30)
    else:
        data = all_data['close']
        cv_30 = np.std(data.head(30)) / np.mean(data.head(30))
        # 加入相对应的列表
        cvs_30.append(cv_30 * 1000)

end = time.time()
print(end - start)


结果:
C:\Users\elmaj\AppData\Local\Programs\Python\Python36\python.exe C:/Users/elmaj/PycharmProjects/SONG/test.py

1.5166161060333252

Process finished with exit code 0

 

你光看时间的吗? 你可以打印看看,在异步函数里加10s睡眠看看。 

	
import numpy as np
import tushare as ts
import aiohttp
import asyncio
import time
 
codes = ['787819', '787317', '787317', '600320', '600191', '600191', '600967', '600765', '600238', '603650']  # 股票代码列表
 
cvs_30 = []
start = time.time()
 
 
async def get_index(code):
    # 就是这里
    await all_data = ts.get_hist_data(code, start='2020-05-12', end='2020-12-28')
    if all_data is None:
 
        cv_30 = 0
        # 加入相对应的列表
        cvs_30.append(cv_30)
    else:
        data = all_data['close']
        cv_30 = np.std(data.head(30)) / np.mean(data.head(30))
 
        # 加入相对应的列表
        cvs_30.append(cv_30 * 1000)
 
 
tasks = [asyncio.ensure_future(get_index(code)) for code in codes]
 
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))
end = time.time()
 
print(end - start)

我理解的异步就是给IO操作前面添加 await 标志。

浏览你的代码,只有一处地方是非本地的IO操作,本地IO操作没有,剩下的全是本地的计算,所以在哪个IO操作前面加上await就行了

 

我运行你修改后的代码是以下的结果。还有我理解的异步就是:一个任务运行需要3秒,当相似的100各任务运行时需要的时间应该大大的小于300秒。

我有1000多支股票代码,多线程或者多进程可以吗?

 

多线程只占用一个进程,消耗很小,但是是一个人排队干活,效率慢

多进程就看你电脑的能力啦。去年我开50进程爬小说,瞬间占满48G内存,电脑当时就卡顿了。

我的主力电脑一般只开5-10进程。3.6GHz 4核心8线程,48G内存。

你上面的代码,10个不到2秒钟,1000个也就不到200秒。

如果你有很多电脑,可以用celery分布式异步任务。一台电脑发任务,几台电脑抢任务。