Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.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 运行Go异步操作并写入映射_Python_Asynchronous_Go_Google Cloud Platform_Goroutine - Fatal编程技术网

Python 运行Go异步操作并写入映射

Python 运行Go异步操作并写入映射,python,asynchronous,go,google-cloud-platform,goroutine,Python,Asynchronous,Go,Google Cloud Platform,Goroutine,我有一个在Go中同时运行无限大查询的程序。父项目都是Python。我需要能够跟踪查询结果,就像在地图中一样 Input: { 'reports_portal': 'select * from reports_portal', 'billing_portal': 'select * from billing_portal', } output: { 'reports_portal': [23, 123, 5234, 632], 'billing_portal': [23, 123,

我有一个在Go中同时运行无限大查询的程序。父项目都是Python。我需要能够跟踪查询结果,就像在地图中一样

Input:

{
 'reports_portal': 'select * from reports_portal',
 'billing_portal': 'select * from billing_portal',
}

output:

{
 'reports_portal': [23, 123, 5234, 632],
 'billing_portal': [23, 123, 5234, 632],
}
等等

这些大查询需要异步运行,因为它们非常慢(从UI的角度来看,SRE等待15-30秒的结果)

我首先尝试将项目异步写入映射:

package main

import (
    "fmt"
)


func add_to_map(m map[string] string, word string) map[string]string {
    added_word := word + " plus more letters"
    m[word] = added_word
    return m
}


func main() {
    words_map := make(map[string]string)
    words := []string{"giraffe", "cat", "dog", "turtle"}
    for _, this_word := range words {
        go add_to_map(words_map, this_word)
    }
    fmt.Println(words_map)
}
爆炸像:

$ go run try_asynchronous.go 
fatal error: concurrent map writes

goroutine 7 [running]:
runtime.throw(0x10b3b96, 0x15)
    /usr/local/Cellar/go/1.8.1/libexec/src/runtime/panic.go:596 +0x95 fp=0xc420032eb8 sp=0xc420032e98
runtime.mapassign(0x109ad20, 0xc420016270, 0xc420032fa0, 0x10b3268)
    /usr/local/Cellar/go/1.8.1/libexec/src/runtime/hashmap.go:499 +0x667 fp=0xc420032f58 sp=0xc420032eb8
main.add_to_map(0xc420016270, 0x10b1ba0, 0x3, 0x0)
    /tmp/golang-w-python/try_asynchronous.go:10 +0xa3 fp=0xc420032fc0 sp=0xc420032f58
runtime.goexit()
    /usr/local/Cellar/go/1.8.1/libexec/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc420032fc8 sp=0xc420032fc0
created by main.main
    /tmp/golang-w-python/try_asynchronous.go:19 +0xc8

goroutine 1 [runnable]:
fmt.(*pp).fmtString(0xc42001e0c0, 0x10b1f52, 0x7, 0x76)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:424 +0x1a2
fmt.(*pp).printValue(0xc42001e0c0, 0x10953c0, 0xc42000e260, 0x98, 0x76, 0x1)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:729 +0x27aa
fmt.(*pp).printValue(0xc42001e0c0, 0x109ad20, 0xc420016270, 0x15, 0x76, 0x0)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:750 +0x103d
fmt.(*pp).printArg(0xc42001e0c0, 0x109ad20, 0xc420016270, 0x76)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:682 +0x217
fmt.(*pp).doPrintln(0xc42001e0c0, 0xc420045f28, 0x1, 0x1)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:1138 +0xa1
fmt.Fprintln(0x1108140, 0xc42000c018, 0xc420045f28, 0x1, 0x1, 0xc420045ef0, 0xc420045ee0, 0x1087218)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:247 +0x5c
fmt.Println(0xc420045f28, 0x1, 0x1, 0x10b1e6f, 0x6, 0x0)
    /usr/local/Cellar/go/1.8.1/libexec/src/fmt/print.go:257 +0x57
main.main()
    /tmp/golang-w-python/try_asynchronous.go:21 +0x132
exit status 2
基于需要一次运行多个查询并试图按查询名称跟踪结果,我希望在异步过程中写入映射。但是
致命错误:并发映射写入
表示不能

我不明白

  • 为什么不呢
  • 我应该同时运行这些大查询
  • 编辑:

    我拥有的最接近的东西,即返回结果,不是异步的:

    package main
    
    import (
        "fmt"
        "math/rand"
        "sync"
        "time"
    )
    
    var mutex sync.Mutex
    var wg sync.WaitGroup
    
    func random_sleep() {
        r := rand.Intn(3000)
        time.Sleep(time.Duration(r) * time.Millisecond)
    }
    
    func add_to_map(m map[string] string, word string) {
        defer wg.Done()
        added_word := word + " plus more letters"
        mutex.Lock()
        defer mutex.Unlock()
        fmt.Println("Before sleep")
        random_sleep()
        m[word] = added_word
        fmt.Println("Added word %v", word)
    }
    
    
    func main() {
        words_map := make(map[string]string)
        words := []string{"giraffe", "cat", "dog", "turtle"}
        for _, this_word := range words {
            wg.Add(1)
            go add_to_map(words_map, this_word)
        }
        wg.Wait()
        fmt.Println(words_map)
    }
    
    结果是错误的:

    cchilders:~/work_projects/metricsportal/golang_integration (feature/golang-query) 
    $ go run try_async.go 
    Before sleep
    Added word %v turtle
    Before sleep
    Added word %v cat
    Before sleep
    Added word %v giraffe
    Before sleep
    Added word %v dog
    map[dog:dog plus more letters turtle:turtle plus more letters cat:cat plus more letters giraffe:giraffe plus more letters]
    
    cchilders:~/work_projects/metricsportal/golang_integration (feature/golang-query) 
    $ go run try_async.go 
    Before sleep
    Added word %v turtle
    Before sleep
    Added word %v cat
    Before sleep
    Added word %v giraffe
    Before sleep
    Added word %v dog
    map[dog:dog plus more letters turtle:turtle plus more letters cat:cat plus more letters giraffe:giraffe plus more letters]
    
    结果应该非常快,不超过3秒(我认为是随机数的最大值):


    代码中有两个不同的问题:

    1) 即使您总是向不同的键写入,如果不锁定地图,也无法同时执行此操作:

    因此,您需要确保在访问地图时以独占方式访问它

    2) 您需要在打印地图之前完成所有goroutine(这就是为什么在编辑的代码中会得到不一致的结果)

    根据您的示例,解决这两个问题的简单方法是:

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    var mutex sync.Mutex
    var wg sync.WaitGroup
    
    func add_to_map(m map[string] string, word string) {
        defer wg.Done()
        added_word := word + " plus more letters"
        mutex.Lock()
        defer mutex.Unlock()
        m[word] = added_word
    }
    
    
    func main() {
        words_map := make(map[string]string)
        words := []string{"giraffe", "cat", "dog", "turtle"}
        for _, this_word := range words {
            wg.Add(1)
            go add_to_map(words_map, this_word)
        }
        wg.Wait()
        fmt.Println(words_map)
    }
    

    好的,让我澄清一些事情并帮助你

    您不需要从这里返回修改后的地图,因为您的 函数获取映射的引用,而不是它的副本。(让我们忽略这个事实 您完全忽略了返回值)

    接下来,您需要同步对地图的访问。你可以用 为了这个

    import "sync"
    
    var mutex sync.Mutex //glabal variable but can be created as local also
    
    func add_to_map(m map[string] string, word string) {
        added_word := word + " plus more letters"
        // here you can do long to compute task and calculate result
        // calc here
        mutex.Lock() //result ready lock mutex
        defer mutex.Unlock() // unlock mutex when we return from function
        m[word] = added_word // result write to shared map
    }
    
    请注意,在Go 1.9中,将有一个类型

    编辑: 您需要等待所有go例程完成,因为您的
    main()
    现在比它们先完成。您可以使用

    (代表OP发布解决方案)

    我使用假延迟是错误的,两种解决方案都有效。谢谢各位:

    package main
    
    import (
        "fmt"
        "math/rand"
        "sync"
        "time"
    )
    
    var mutex sync.Mutex
    var wg sync.WaitGroup
    
    func random_sleep() {
        r := rand.Intn(3000)
        time.Sleep(time.Duration(r) * time.Millisecond)
    }
    
    
    func add_to_map(m map[string] string, word string) {
        defer wg.Done()
        added_word := word + " plus more letters"
        fmt.Println("Before sleep")
        random_sleep()
        mutex.Lock()
        defer mutex.Unlock()
        m[word] = added_word
        fmt.Println("Added word %v", word)
    }
    
    
    func main() {
        words_map := make(map[string]string)
        words := []string{"giraffe", "cat", "dog", "turtle"}
        for _, this_word := range words {
            wg.Add(1)
            go add_to_map(words_map, this_word)
        }
        wg.Wait()
        fmt.Println(words_map)
    }
    
    结果:

    $ go run try_async.go 
    Before sleep
    Before sleep
    Before sleep
    Before sleep
    Added word %v dog
    Added word %v giraffe
    Added word %v cat
    Added word %v turtle
    map[turtle:turtle plus more letters dog:dog plus more letters giraffe:giraffe plus more letters cat:cat plus more letters]
    

    Go中的任何类型对于并发写入或读写都是安全的,您始终需要同步。要扩展@JimB的注释,签出和同步是不够的,请参阅上面的注释。看来我需要频道,频道必须明确地说“等等”。我的问题是我不太理解Go,我不想花这么多时间,我的模块不能并发。我们最大的问题是尝试多线程,我需要使用通道吗?为什么在关键部分调用random_sleep()称它为beafore mutex.Lock(),因为你阻止了所有线程。哦,哈哈,好的,我会重构修复,看看编辑部分好的,我看到你使用了延迟,让我试试这个我试过了;如果您运行上面的示例,您将看到它不会同时运行(一次触发所有4个操作,然后在每个结果出现时将结果添加到映射)。这无助于加快我们的大查询速度,因为慢是因为等待每个查询运行并返回响应。不要在关键部分调用sleep调用beefore。(我假设睡眠模拟计算时间)。如果您的密码相互独立,则是安全的。@codyc4321:这与互斥无关,但与不等待go例程完成有关。。看我编辑过的答案虽然我很感激,但仍然不起作用。该模块的目标是一次触发所有4个查询,然后在完成后写入结果映射。以这种方式编写,它既不异步,也不比python更快。我又加了一个note@codyc4321:这确实是异步的,4个查询将在parallel@codyc4321:繁重的操作应该在Lock()之外完成,否则它将不异步。。
    package main
    
    import (
        "fmt"
        "sync"
    )
    
    var mutex sync.Mutex
    var wg sync.WaitGroup
    
    func add_to_map(m map[string] string, word string) {
        defer wg.Done()
        added_word := word + " plus more letters"
        // do heavy work here
        //
        mutex.Lock()
        defer mutex.Unlock()
        m[word] = added_word
    }
    
    
    func main() {
        words_map := make(map[string]string)
        words := []string{"giraffe", "cat", "dog", "turtle"}
        for _, this_word := range words {
            wg.Add(1)
            go add_to_map(words_map, this_word)
        }
        wg.Wait()
        fmt.Println(words_map)
    }
    
    package main
    
    import (
        "fmt"
        "math/rand"
        "sync"
        "time"
    )
    
    var mutex sync.Mutex
    var wg sync.WaitGroup
    
    func random_sleep() {
        r := rand.Intn(3000)
        time.Sleep(time.Duration(r) * time.Millisecond)
    }
    
    
    func add_to_map(m map[string] string, word string) {
        defer wg.Done()
        added_word := word + " plus more letters"
        fmt.Println("Before sleep")
        random_sleep()
        mutex.Lock()
        defer mutex.Unlock()
        m[word] = added_word
        fmt.Println("Added word %v", word)
    }
    
    
    func main() {
        words_map := make(map[string]string)
        words := []string{"giraffe", "cat", "dog", "turtle"}
        for _, this_word := range words {
            wg.Add(1)
            go add_to_map(words_map, this_word)
        }
        wg.Wait()
        fmt.Println(words_map)
    }
    
    $ go run try_async.go 
    Before sleep
    Before sleep
    Before sleep
    Before sleep
    Added word %v dog
    Added word %v giraffe
    Added word %v cat
    Added word %v turtle
    map[turtle:turtle plus more letters dog:dog plus more letters giraffe:giraffe plus more letters cat:cat plus more letters]