我正在尝试使用 Gitlab CI/CD 构建并运行我的 Docker 映像,但有一个问题我无法解决,即使本地一切正常。
这是我的 Dockerfile:
FROM <internal_docker_repo_image>
RUN apt update && \
apt install --no-install-recommends -y build-essential gcc
COPY requirements.txt /requirements.txt
RUN pip install --no-cache-dir --user -r /requirements.txt
COPY . /src
WORKDIR /src
ENTRYPOINT ["python", "-m", "dvc", "repro"]
Run Code Online (Sandbox Code Playgroud)
这就是我运行容器的方式:
docker run --volume ${PWD}:/src --env=GOOGLE_APPLICATION_CREDENTIALS=<path_to_json> <image_name> ./dvc_configs/free/dvc.yaml --force
在本地运行时一切正常,但在 Gitlab CI/CD 上运行时会失败。
stages:
- build_image
build_image:
stage: build_image
image: <internal_docker_repo_image>
script:
- echo "Building Docker image..."
- mkdir ~/.docker
- cat $GOOGLE_CREDENTIALS > ${CI_PROJECT_DIR}/key.json
- docker build . …Run Code Online (Sandbox Code Playgroud) q := i.client.Query(query)
job, err := q.Run(ctx)
if err != nil {
<handle>
}
status, err := job.Wait(ctx)
if err != nil {
<handle>
}
if err = status.Err(); err != nil {
<handle>
}
it, err := job.Read(ctx)
if err != nil {
<handle>
}
Run Code Online (Sandbox Code Playgroud)
这是我用来查询 BigQuery 中的表的代码。该client字段属于类型*bigquery.Client。
查询本身非常简单,例如:
SELECT field, another_field from some_table LIMIT K OFFSET N
Run Code Online (Sandbox Code Playgroud)
(我知道这种类型的分页不是 BQ 的最佳实践,但这是一个单独讨论的主题)。
此Run调用需要 2-4 秒,而在 GUI 中查询则需要几百毫秒。
这里可能出了什么问题?官方包文档或多或少使用相同的方法与 BigQuery 交互(但有时他们会跳过这一Wait部分)
编辑:
事实证明,使用 …
type MyObj struct {
Field1 string `json:"field_1"`
Field2 int64 `json:"field_2"`
Field3 string `json:"field_3"`
...
FieldK string `json:"field_k"`
FieldN MyInterface `json:"field_n"`
}
Run Code Online (Sandbox Code Playgroud)
我的代码中有一个模型(除了不相关的域详细信息)如下所示。该字段的想法FieldN是支持两种类型,例如MyType1和MyType2。它们具有相同的功能CommonMethod(),但模型非常不同,因此这与具有更多字段的父类型无关。
不出所料,Go 无法将 JSON 解组为接口值。我正在尝试使用自定义UnmarshalJSON()实现,但到目前为止它看起来真的很尴尬:
func (m *MyObj) UnmarshalJSON(data []byte) error {
out := &MyObj{}
var m map[string]json.RawMessage
if err := json.Unmarshal(data, &m); err != nil {
return err
}
if err := json.Unmarshal(m["field_1"], &out.Field1); err != nil {
return err
}
delete(m, "field_1")
if err := json.Unmarshal(m["field_2"], &out.Field2); …Run Code Online (Sandbox Code Playgroud) import random
def sp_noise(image,prob):
'''
Add salt and pepper noise to image
prob: Probability of the noise
'''
output = np.zeros(image.shape,np.uint8)
thres = 1 - prob
for i in range(image.shape[0]):
for j in range(image.shape[1]):
rdn = random.random()
if rdn < prob:
output[i][j] = 0
elif rdn > thres:
output[i][j] = 255
else:
output[i][j] = image[i][j]
return output
Run Code Online (Sandbox Code Playgroud)
这就是我想要达到的目标。我知道此函数不使用矢量化,但我不知道在这种情况下如何摆脱循环。如果有像素值的条件,那将是微不足道的。但在这种情况下,索引或像素值没有条件,我只需要保留像素值,或者根据随机变量的值将其设置为 0 或 1。
我如何矢量化?
\n\n6.2 使用指针接收器的方法
\n如果命名类型 T 的所有方法都有 T 本身的接收者类型\n(不是 *T ),则复制该类型的实例是安全的;调用任何方法都必然会生成一个副本。例如,time.Duration\n值可以自由复制,包括作为函数的参数。但是,如果任何方法有指针接收器,则应避免复制 T 的实例,因为这样做可能会违反内部不变量。例如,复制 bytes.Buffer 的实例将导致原始\n和副本别名 ( \xc2\xa72.3.2 ) 相同的底层字节数组。\n后续方法调用将产生不可预测的影响。
\n(Go 编程语言 Alan AA Donovan \xc2\xb7 Brian W. Kernighan)
\n
我理解这句话的一般含义,但我想知道复制该类型的实例是安全的是否正确。
\n如果结构体具有切片/映射字段,则所有副本都会收到自己的指向后备数组/哈希图的指针副本,因此仍然可以更改这些数据结构。
\n尽管所有方法都可以使用值接收器定义,但我们可以破坏结构的内部状态。
\n我明白为什么会发生这种情况,但是这种可能性是否与上面段落中所写的内容相矛盾?
\n无论方法接收者如何,复制值都可能会产生不良后果,并且还取决于字段类型。
\n我在这里缺少什么?
\npackage main\n\nimport "fmt"\n\ntype T struct {\n s []string\n}\n\nfunc main() {\n original := T{s: []string{"original"}}\n copycat := original\n copycat.s[0] = "copycat"\n fmt.Println(original.s[0] == "copycat") // true\n}\nRun Code Online (Sandbox Code Playgroud)\n 我想知道什么是更优雅的(如果这个词在这种情况下是合适的)方法来继续生成一个随机数,直到它不在使用的值集中。第一个选项是重复的,因为我们random type在 while 循环内部和外部都有相同的行。
然而,第二个需要添加一个条件语句来跳出循环。我知道这个特殊情况是微不足道的,两个版本都可以工作,但是在您看来哪个看起来更 Python/优雅?
def orchestrator(image = None):
used_values = set()
for _ in range(7):
toss = np.random.random()
if toss >= 0.5:
random_type = np.random.randint(1,7,1)[0]
while random_type in used_values:
random_type = np.random.randint(1,7,1)[0]
used_values.add(random_type)
print(random_type)
Run Code Online (Sandbox Code Playgroud)
def orchestrator(image = None):
used_values = set()
for _ in range(7):
toss = np.random.random()
if toss >= 0.5:
while True:
random_type = np.random.randint(1,7,1)[0]
if random_type not in used_values:
break
used_values.add(random_type)
print(random_type)
Run Code Online (Sandbox Code Playgroud) package main
import "fmt"
func square(numbers chan int, squares chan int) {
for n := range numbers {
squares <- n * n
}
close(squares)
}
func main() {
numbers := make(chan int)
squares := make(chan int)
go square(numbers, squares)
for i := 0; i < 10; i++ {
numbers <- i
}
close(numbers)
for s := range squares {
fmt.Println(s)
}
}
Run Code Online (Sandbox Code Playgroud)
我的意思是,我知道要使这段代码正常工作,应该将数字发送到numbers单独的 goroutine 中的通道,例如:
go func() {
for i := 0; i < 10; i++ { …Run Code Online (Sandbox Code Playgroud)