Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
简单的Python异步。预编译器?_Python_Compiler Construction_Syntax_Asynchronous - Fatal编程技术网

简单的Python异步。预编译器?

简单的Python异步。预编译器?,python,compiler-construction,syntax,asynchronous,Python,Compiler Construction,Syntax,Asynchronous,假设您有一个io繁重的函数,如下所示: def getMd5Sum(path): with open(path) as f: return md5(f.read()).hexdigest() def someGuiCallback_1(filebutton): ... path = filebutton.getPath() Thread(target=someGuiCallback_2, args=(path,)).start() def so

假设您有一个io繁重的函数,如下所示:

def getMd5Sum(path):
    with open(path) as f:
        return md5(f.read()).hexdigest()
def someGuiCallback_1(filebutton):
    ...
    path = filebutton.getPath()
    Thread(target=someGuiCallback_2, args=(path,)).start()

def someGuiCallback_2(path):
    md5sum = getMd5Sum(path)
    glib.idle_add(someGuiCallback_3, md5sum)

def someGuiCallback_3(md5sum):
    showNotification("Md5Sum of file: %s" % md5sum)
    ...
def performAsync(asyncFunc, notifyFunc):
    def threadProc():
        retValue = asyncFunc()
        glib.idle_add(notifyFunc, retValue)
    Thread(target=threadProc).start()

def someGuiCallback(filebutton):
    path = filebutton.getPath()
    performAsync(
        lambda: getMd5Sum(path),
        lambda md5sum: showNotification("Md5Sum of file: %s" % md5sum)
    )
您认为Python是否足够灵活,允许这样的代码(注意$):

要执行这样的操作:

def getMd5Sum(path):
    with open(path) as f:
        return md5(f.read()).hexdigest()
def someGuiCallback_1(filebutton):
    ...
    path = filebutton.getPath()
    Thread(target=someGuiCallback_2, args=(path,)).start()

def someGuiCallback_2(path):
    md5sum = getMd5Sum(path)
    glib.idle_add(someGuiCallback_3, md5sum)

def someGuiCallback_3(md5sum):
    showNotification("Md5Sum of file: %s" % md5sum)
    ...
def performAsync(asyncFunc, notifyFunc):
    def threadProc():
        retValue = asyncFunc()
        glib.idle_add(notifyFunc, retValue)
    Thread(target=threadProc).start()

def someGuiCallback(filebutton):
    path = filebutton.getPath()
    performAsync(
        lambda: getMd5Sum(path),
        lambda md5sum: showNotification("Md5Sum of file: %s" % md5sum)
    )
(glib.idle_add只是将函数推送到主线程的队列上)

我考虑过使用decorator,但它们不允许我在调用后访问函数的“内容”。(显示通知部分)

我想我可以在执行前编写一个“编译器”来更改代码,但它不像最佳解决方案


您对如何执行上述操作有何想法?

您可以使用导入挂钩来实现此目标

。。。但我个人认为这有点恶心

如果你想沿着这条路走下去,基本上你要做的是:

  • 为扩展添加一个导入钩子(例如“.thpy”)
  • 然后,导入钩子负责(本质上)作为导入的结果传递一些有效代码
  • 为有效代码提供的参数有效地与要导入的文件相关
  • 这意味着您的预编译器可以在输入源代码的过程中执行您喜欢的任何转换
不利方面:

  • 虽然以这种方式使用导入钩子是可行的,但它会让任何维护人员或您的代码大吃一惊。(坏主意)
  • 您执行此操作的方式依赖于—在python 3.0中已删除—这意味着以这种方式编写的代码的生命周期有限
就我个人而言我不会去那个里,但若你们去了,会有一个问题,就是在哪里做这类事情会有一些细节,我建议找一本后面的书来读一下。(Paul McGuire撰写,2009年4月号,可能以PDF格式提供)


具体来说,它使用和pyparsing作为示例,但原理是相同的。

类似这样的东西怎么样:

def getMd5Sum(path):
    with open(path) as f:
        return md5(f.read()).hexdigest()
def someGuiCallback_1(filebutton):
    ...
    path = filebutton.getPath()
    Thread(target=someGuiCallback_2, args=(path,)).start()

def someGuiCallback_2(path):
    md5sum = getMd5Sum(path)
    glib.idle_add(someGuiCallback_3, md5sum)

def someGuiCallback_3(md5sum):
    showNotification("Md5Sum of file: %s" % md5sum)
    ...
def performAsync(asyncFunc, notifyFunc):
    def threadProc():
        retValue = asyncFunc()
        glib.idle_add(notifyFunc, retValue)
    Thread(target=threadProc).start()

def someGuiCallback(filebutton):
    path = filebutton.getPath()
    performAsync(
        lambda: getMd5Sum(path),
        lambda md5sum: showNotification("Md5Sum of file: %s" % md5sum)
    )

lambdas有点难看,但它很简单,可能比使用预编译器技巧更具可读性。

确保您可以从decorator访问函数代码(已编译),对其进行反汇编和破解。您甚至可以访问在其中定义的模块的源并重新编译它。但我认为这是没有必要的。下面是一个使用修饰生成器的示例,其中
yield
语句充当同步和异步部分之间的分隔符:

from threading import Thread
import hashlib

def async(gen):
    def func(*args, **kwargs):
        it = gen(*args, **kwargs)
        result = it.next()
        Thread(target=lambda: list(it)).start()
        return result
    return func

@async
def test(text):
    # synchronous part (empty in this example)
    yield # Use "yield value" if you need to return meaningful value
    # asynchronous part[s]
    digest = hashlib.md5(text).hexdigest()
    print digest

问题是“…”被展开的情况,也就是说,在得到答案后,你想做不止一行。如果Python有多行内联函数,那可能就可以了,尽管如果在同一个块中有两个$calls,即使这样也会变得非常混乱。使用生成器的好主意!我已经制作了一个可以随时打开和关闭主线程的版本:code.activestate.com/recipes/576952,由于某种原因,如果我使用glib,它会在随机位置死锁。我可能得问问他们:)