是否可以在后台启动asyncio事件循环而不产生线程或进程?

时间:2017-04-16 12:46:11

标签: python-3.x python-asyncio

我在Python 3.5中实现了一项服务,应该定期通过网络加载文件。我想避免在加载时阻塞主线程。为了避免将线程和共享内存的复杂性引入我的应用程序,我想使用带有asyncio包的事件循环来检测它。

要运行事件循环,我找到了private void CreatePopup(Long id) { final LayoutInflater Manual = LayoutInflater.from(this); final View textEntryView = Manual.inflate(update, null); final EditText infoData = (EditText) textEntryView.findViewById(R.id.InfoData); final AlertDialog.Builder alert = new AlertDialog.Builder(this); final TextView TextSet = (TextView) textEntryView.findViewById(R.id.product); final Button Accept = (Button) textEntryView.findViewById(R.id.button); final Button Delete = (Button) textEntryView.findViewById(R.id.delete); final SQLite db = new SQLite(this); final Long _id = id; final SQLiteDatabase X = db.getReadableDatabase(); final Cursor c; c = X.rawQuery("SELECT Product FROM Inventory WHERE _id =" + _id, null); c.moveToFirst(); final String Data = c.getString(c.getColumnIndexOrThrow("Product")); TextSet.setText(Data); c.close(); Accept.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (infoData.length() != 0) { final Editable Data = infoData.getText(); db.UpdateRecord(Data, _id); db.close(); Snackbar.make(textEntryView, "Updated", Snackbar.LENGTH_LONG).setDuration(700).show(); } else { Toast toast = Toast.makeText(getApplicationContext(), "Input Quantity!", Toast.LENGTH_SHORT); toast.show(); } }}); Delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { db.DeleteRecord(_id); db.close(); Snackbar.make(textEntryView, "Removed", Snackbar.LENGTH_LONG).setDuration(700).show(); } }); alert.setTitle("Update Quantity").setView(textEntryView); alert.setPositiveButton("Done", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { CreateListView(); } }); alert.show(); } AbstractEventLoop.run_forever()方法,但两者似乎都在调用时阻塞主线程。我发现避免这种情况的唯一方法是在不同的线程中启动循环。但是如果我还在使用线程,那么使用事件循环是没有意义的。

所以我的问题是:是否可以在后台启动asyncio事件循环而不产生线程或进程?

3 个答案:

答案 0 :(得分:2)

如果您的整个程序在没有Future事件循环的情况下运行,则在新事件循环中仅运行一个任务并没有多大意义。相反,请尝试使用复杂程度较低的concurrent.futures库。任何被调用的任务都会立即返回.done()个实例,该实例具有.result()import time from concurrent.futures.thread import ThreadPoolExecutor def fetcher(): print("fetching...") time.sleep(2) print("got it!") return 42 with ThreadPoolExecutor(max_workers=10) as executor: fut = None for i in range(100): if i % 10 == 2: fut = executor.submit(fetcher) print(i, fut) if fut and fut.done(): result = fut.result() # can raise an error print("Done! Got:", result) fut = None time.sleep(0.5) 方法:

You+do+not+have+permission+to+get+these+payment+details

答案 1 :(得分:1)

您可以使用run_in_executor方法。使用此方法运行的每个函数都在自己的线程中运行(并行)。

  

AbstractEventLoop.run_in_executor()方法可以与线程池执行程序一起使用,以在不同的线程中执行回调,从而不阻塞事件循环的线程。

     

executor参数应该是Executor实例。如果执行程序为None,则使用默认执行程序。

例如:

import asyncio

def load_file_over_network(file_name):
    # do the file loading
    pass

loop = asyncio.get_event_loop()
file_name = 'FILE_NAME'

# load the file without blocking
loop.run_in_executor(None, load_file_over_network, file_name)

# do some other stuff in the main thread
# while the synchronous code above is running in other threads, the event loop
# can go do other things

# load the file again without blocking
loop.run_in_executor(None, load_file_over_network, file_name)

希望这有用:)

答案 2 :(得分:1)

嗯,Yuval Pruss's answer部分正确。实际上,loop.run_in_executor()的{​​{3}}参数可以是ThreadPoolExecutor(默认值)或ProcessPoolExecutor(现在在asyncio中已弃用)。

因此答案是否定的,您不能在所有其他代码都同步的情况下在后台运行asyncio Task。或者您重写您的应用程序,以便它对每个任务使用asyncio,或者您必须使用线程或进程。