Home  >  Article  >  Backend Development  >  Python asynchronously calls command line tools

Python asynchronously calls command line tools

伊谢尔伦
伊谢尔伦Original
2016-11-21 13:41:141358browse

 When you adopt an asynchronous programming method based on event loops in your own Python program, you will find yourself unconsciously attracted to it, not because this method is great, but because you have to think about it. The method ensures that no link in the program is blocked!

For example, the current scenario is to read every piece of unprocessed data from MongoDB, download and save the image information, and then update the contents of the database. The commonly used MongoDB asynchronous driver in Python is Motor:

Used in combination with asyncio as follows:  

import motor.motor_asyncio
  import asyncio
  client = motor.motor_asyncio.AsyncIOMotorClient()
  db = client.test_database
  async def run():
  async for mm in db.test_database.find({"status": 0}):
  print(mm['img_src'])
  # Download Image Here
  # dl_img(mm['img_src'])
  await db.test_database.update({"_id": mm['_id']}, {"$set": {"status":1}})
  loop = asyncio.get_event_loop()
  loop.run_until_complete(run())

At this time, if the operation at dl_img() is blocked, then asynchronous processing is meaningless. Of course, you can still use the asynchronous network request library aiohttp to achieve image downloading:

  async with session.get(img) as resp:
  with open(img.split("/")[-1], 'wb') as fd:
  while True:
  chunk = await resp.content.read(1024)
  if not chunk:
  break
  fd.write(chunk)

Of course, you can also directly call the system command line tool (such as wget) to complete the download task without downloading it yourself. Python implements system command calls through the subprocess standard library (replacing the old os.system (cmd)). To perform a download task, you only need:

import subprocess as sb
sb.run(['wget', img], shell=True)

However, this calling method cannot be used directly in the asyncio event loop, but asyncio provides the corresponding subprocess interface:

asyncio.create_subprocess_exec(*args, ...)
asyncio.create_subprocess_shell(cmd, ...)

Both methods return an asyncio.subprocess.Process instance, and its interface design completely imitates subprocess.Popen (the underlying implementation of subprocess.run() mentioned above ), so it is easy to transplant its usage into the event loop:  

async def dl_img(src):
  dl = await asyncio.create_subprocess_shell('wget {} -O {}'.format(src, src.split("/")[-1])
  await dl.wait()

In addition to the usage in the above scenario, you can also directly put the execution of the command line as a task into the event loop:

  loop = asyncio.get_event_loop()
  sb = asyncio.create_subprocess_shell('exit 7', loop=loop)
  proc = loop.run_until_complete(sb)
  exitcode = loop.run_until_complete(proc.wait())

Summary

The meaning of asynchronous programming in Python is not to let the CPU block IO, so you need to pay attention to using the correct asynchronous method in every blocking operation. Once these operations are encapsulated into asynchronous Tasks, There is no need to worry about subsequent scheduling execution.


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn