Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
VisualDL
提交
67124a3c
V
VisualDL
项目概览
PaddlePaddle
/
VisualDL
大约 1 年 前同步成功
通知
88
Star
4655
Fork
642
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
5
Wiki
分析
仓库
DevOps
项目成员
Pages
V
VisualDL
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
5
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
67124a3c
编写于
9月 16, 2020
作者:
走神的阿圆
提交者:
GitHub
9月 16, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add visualdl dev (#812)
上级
25c40a78
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
283 addition
and
25 deletion
+283
-25
docs/file_system/BOS.md
docs/file_system/BOS.md
+1
-1
visualdl/__init__.py
visualdl/__init__.py
+3
-0
visualdl/io/bfile.py
visualdl/io/bfile.py
+80
-23
visualdl/server/app.py
visualdl/server/app.py
+6
-1
visualdl/server/args.py
visualdl/server/args.py
+13
-0
visualdl/server/serve.py
visualdl/server/serve.py
+119
-0
visualdl/utils/dir.py
visualdl/utils/dir.py
+37
-0
visualdl/utils/md5_util.py
visualdl/utils/md5_util.py
+24
-0
未找到文件。
docs/file_system/BOS.md
浏览文件 @
67124a3c
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
### VisualDL
### VisualDL
VisualDL在2.0.0b8版本之后增加了对BOS的支持,可使用下述命令安装
VisualDL在2.0.0b8版本之后增加了对BOS的支持,可使用下述命令安装
```
shell
```
shell
pip
install
visualdl
==
2.0.0b8
pip
install
visualdl
```
```
### BOS
### BOS
...
...
visualdl/__init__.py
浏览文件 @
67124a3c
...
@@ -19,5 +19,8 @@ import os
...
@@ -19,5 +19,8 @@ import os
from
visualdl.writer.writer
import
LogWriter
# noqa
from
visualdl.writer.writer
import
LogWriter
# noqa
from
visualdl.version
import
vdl_version
as
__version__
from
visualdl.version
import
vdl_version
as
__version__
from
visualdl.utils.dir
import
init_vdl_config
init_vdl_config
()
ROOT
=
os
.
path
.
dirname
(
__file__
)
ROOT
=
os
.
path
.
dirname
(
__file__
)
visualdl/io/bfile.py
浏览文件 @
67124a3c
...
@@ -202,17 +202,76 @@ class HDFileSystem(object):
...
@@ -202,17 +202,76 @@ class HDFileSystem(object):
return
([
'hdfs://'
+
root
,
dirs
,
files
]
for
root
,
dirs
,
files
in
walks
)
return
([
'hdfs://'
+
root
,
dirs
,
files
]
for
root
,
dirs
,
files
in
walks
)
class
BosFileSystem
(
object
):
def
get_object_info
(
path
):
def
__init__
(
self
):
path
=
path
[
6
:]
self
.
max_contents_count
=
1
index
=
path
.
index
(
'/'
)
self
.
max_contents_time
=
1
bucket_name
=
path
[
0
:
index
]
self
.
get_bos_config
()
object_key
=
path
[
index
+
1
:]
return
bucket_name
,
object_key
class
BosConfigClient
(
object
):
def
__init__
(
self
,
bos_ak
,
bos_sk
,
bos_sts
,
bos_host
=
"bj.bcebos.com"
):
self
.
config
=
BceClientConfiguration
(
credentials
=
BceCredentials
(
bos_ak
,
bos_sk
),
endpoint
=
bos_host
,
security_token
=
bos_sts
)
self
.
bos_client
=
BosClient
(
self
.
config
)
self
.
bos_client
=
BosClient
(
self
.
config
)
self
.
file_length_map
=
{}
self
.
_file_contents_to_add
=
b
''
def
exists
(
self
,
path
):
self
.
_file_contents_count
=
0
bucket_name
,
object_key
=
get_object_info
(
path
)
self
.
_start_append_time
=
time
.
time
()
try
:
self
.
bos_client
.
get_object_meta_data
(
bucket_name
,
object_key
)
return
True
except
exception
.
BceError
:
return
False
def
makedirs
(
self
,
path
):
if
not
path
.
endswith
(
'/'
):
path
+=
'/'
if
self
.
exists
(
path
):
return
bucket_name
,
object_key
=
get_object_info
(
path
)
if
not
object_key
.
endswith
(
'/'
):
object_key
+=
'/'
init_data
=
b
''
self
.
bos_client
.
append_object
(
bucket_name
=
bucket_name
,
key
=
object_key
,
data
=
init_data
,
content_md5
=
content_md5
(
init_data
),
content_length
=
len
(
init_data
))
@
staticmethod
def
join
(
path
,
*
paths
):
result
=
os
.
path
.
join
(
path
,
*
paths
)
result
.
replace
(
'
\\
'
,
'/'
)
return
result
def
upload_object_from_file
(
self
,
path
,
filename
):
if
not
self
.
exists
(
path
):
self
.
makedirs
(
path
)
bucket_name
,
object_key
=
get_object_info
(
path
)
object_key
=
self
.
join
(
object_key
,
filename
)
# if not object_key.endswith('/'):
# object_key += '/'
print
(
'Uploading file `%s`'
%
filename
)
self
.
bos_client
.
put_object_from_file
(
bucket
=
bucket_name
,
key
=
object_key
,
file_name
=
filename
)
class
BosFileSystem
(
object
):
def
__init__
(
self
,
write_flag
=
True
):
if
write_flag
:
self
.
max_contents_count
=
1
self
.
max_contents_time
=
1
self
.
get_bos_config
()
self
.
bos_client
=
BosClient
(
self
.
config
)
self
.
file_length_map
=
{}
self
.
_file_contents_to_add
=
b
''
self
.
_file_contents_count
=
0
self
.
_start_append_time
=
time
.
time
()
def
get_bos_config
(
self
):
def
get_bos_config
(
self
):
bos_host
=
os
.
getenv
(
"BOS_HOST"
)
bos_host
=
os
.
getenv
(
"BOS_HOST"
)
...
@@ -231,24 +290,22 @@ class BosFileSystem(object):
...
@@ -231,24 +290,22 @@ class BosFileSystem(object):
credentials
=
BceCredentials
(
access_key_id
,
secret_access_key
),
credentials
=
BceCredentials
(
access_key_id
,
secret_access_key
),
endpoint
=
bos_host
,
security_token
=
bos_sts
)
endpoint
=
bos_host
,
security_token
=
bos_sts
)
def
set_bos_config
(
self
,
bos_ak
,
bos_sk
,
bos_sts
,
bos_host
=
"bj.bcebos.com"
):
self
.
config
=
BceClientConfiguration
(
credentials
=
BceCredentials
(
bos_ak
,
bos_sk
),
endpoint
=
bos_host
,
security_token
=
bos_sts
)
self
.
bos_client
=
BosClient
(
self
.
config
)
def
isfile
(
self
,
filename
):
def
isfile
(
self
,
filename
):
return
exists
(
filename
)
return
exists
(
filename
)
def
read_file
(
self
,
filename
,
binary
=
True
):
def
read_file
(
self
,
filename
,
binary
=
True
):
bucket_name
,
object_key
=
BosFileSystem
.
_
get_object_info
(
filename
)
bucket_name
,
object_key
=
get_object_info
(
filename
)
result
=
self
.
bos_client
.
get_object_as_string
(
bucket_name
,
object_key
)
result
=
self
.
bos_client
.
get_object_as_string
(
bucket_name
,
object_key
)
return
result
return
result
@
staticmethod
def
_get_object_info
(
path
):
path
=
path
[
6
:]
index
=
path
.
index
(
'/'
)
bucket_name
=
path
[
0
:
index
]
object_key
=
path
[
index
+
1
:]
return
bucket_name
,
object_key
def
exists
(
self
,
path
):
def
exists
(
self
,
path
):
bucket_name
,
object_key
=
BosFileSystem
.
_
get_object_info
(
path
)
bucket_name
,
object_key
=
get_object_info
(
path
)
try
:
try
:
self
.
bos_client
.
get_object_meta_data
(
bucket_name
,
object_key
)
self
.
bos_client
.
get_object_meta_data
(
bucket_name
,
object_key
)
return
True
return
True
...
@@ -263,7 +320,7 @@ class BosFileSystem(object):
...
@@ -263,7 +320,7 @@ class BosFileSystem(object):
path
+=
'/'
path
+=
'/'
if
self
.
exists
(
path
):
if
self
.
exists
(
path
):
return
return
bucket_name
,
object_key
=
BosFileSystem
.
_
get_object_info
(
path
)
bucket_name
,
object_key
=
get_object_info
(
path
)
if
not
object_key
.
endswith
(
'/'
):
if
not
object_key
.
endswith
(
'/'
):
object_key
+=
'/'
object_key
+=
'/'
init_data
=
b
''
init_data
=
b
''
...
@@ -280,7 +337,7 @@ class BosFileSystem(object):
...
@@ -280,7 +337,7 @@ class BosFileSystem(object):
return
result
return
result
def
read
(
self
,
filename
,
binary_mode
=
False
,
size
=
0
,
continue_from
=
None
):
def
read
(
self
,
filename
,
binary_mode
=
False
,
size
=
0
,
continue_from
=
None
):
bucket_name
,
object_key
=
BosFileSystem
.
_
get_object_info
(
filename
)
bucket_name
,
object_key
=
get_object_info
(
filename
)
offset
=
0
offset
=
0
if
continue_from
is
not
None
:
if
continue_from
is
not
None
:
offset
=
continue_from
.
get
(
"last_offset"
,
0
)
offset
=
continue_from
.
get
(
"last_offset"
,
0
)
...
@@ -311,7 +368,7 @@ class BosFileSystem(object):
...
@@ -311,7 +368,7 @@ class BosFileSystem(object):
if
not
force
and
not
self
.
ready_to_append
():
if
not
force
and
not
self
.
ready_to_append
():
return
return
file_content
=
self
.
_file_contents_to_add
file_content
=
self
.
_file_contents_to_add
bucket_name
,
object_key
=
BosFileSystem
.
_
get_object_info
(
filename
)
bucket_name
,
object_key
=
get_object_info
(
filename
)
if
not
self
.
exists
(
filename
):
if
not
self
.
exists
(
filename
):
init_data
=
b
''
init_data
=
b
''
self
.
bos_client
.
append_object
(
bucket_name
=
bucket_name
,
self
.
bos_client
.
append_object
(
bucket_name
=
bucket_name
,
...
@@ -394,7 +451,7 @@ class BosFileSystem(object):
...
@@ -394,7 +451,7 @@ class BosFileSystem(object):
else
:
else
:
raise
StopIteration
raise
StopIteration
bucket_name
,
object_key
=
BosFileSystem
.
_
get_object_info
(
dir
)
bucket_name
,
object_key
=
get_object_info
(
dir
)
if
object_key
in
[
'.'
,
'./'
]:
if
object_key
in
[
'.'
,
'./'
]:
prefix
=
None
prefix
=
None
...
...
visualdl/server/app.py
浏览文件 @
67124a3c
...
@@ -32,6 +32,7 @@ from flask_babel import Babel
...
@@ -32,6 +32,7 @@ from flask_babel import Babel
import
visualdl.server
import
visualdl.server
from
visualdl.server.api
import
create_api_call
from
visualdl.server.api
import
create_api_call
from
visualdl.server.serve
import
upload_to_dev
from
visualdl.server.args
import
(
ParseArgs
,
parse_args
)
from
visualdl.server.args
import
(
ParseArgs
,
parse_args
)
from
visualdl.server.log
import
info
from
visualdl.server.log
import
info
from
visualdl.server.template
import
Template
from
visualdl.server.template
import
Template
...
@@ -167,7 +168,11 @@ def run(logdir=None, **options):
...
@@ -167,7 +168,11 @@ def run(logdir=None, **options):
def
main
():
def
main
():
args
=
parse_args
()
args
=
parse_args
()
_run
(
args
)
if
args
.
get
(
'dest'
)
==
'service'
:
if
args
.
get
(
'behavior'
)
==
'upload'
:
upload_to_dev
(
args
.
get
(
'logdir'
),
args
.
get
(
'model'
))
else
:
_run
(
args
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
...
visualdl/server/args.py
浏览文件 @
67124a3c
...
@@ -40,6 +40,8 @@ class DefaultArgs(object):
...
@@ -40,6 +40,8 @@ class DefaultArgs(object):
self
.
model
=
args
.
get
(
'model'
,
''
)
self
.
model
=
args
.
get
(
'model'
,
''
)
self
.
product
=
args
.
get
(
'product'
,
default_product
)
self
.
product
=
args
.
get
(
'product'
,
default_product
)
self
.
telemetry
=
args
.
get
(
'telemetry'
,
True
)
self
.
telemetry
=
args
.
get
(
'telemetry'
,
True
)
self
.
dest
=
args
.
get
(
'dest'
,
''
)
self
.
behavior
=
args
.
get
(
'behavior'
,
''
)
def
get_host
(
host
=
default_host
,
port
=
default_port
):
def
get_host
(
host
=
default_host
,
port
=
default_port
):
...
@@ -99,6 +101,8 @@ class ParseArgs(object):
...
@@ -99,6 +101,8 @@ class ParseArgs(object):
self
.
model
=
args
.
model
self
.
model
=
args
.
model
self
.
product
=
args
.
product
self
.
product
=
args
.
product
self
.
telemetry
=
args
.
telemetry
self
.
telemetry
=
args
.
telemetry
self
.
dest
=
args
.
dest
self
.
behavior
=
args
.
behavior
def
parse_args
():
def
parse_args
():
...
@@ -190,6 +194,15 @@ def parse_args():
...
@@ -190,6 +194,15 @@ def parse_args():
default
=
True
,
default
=
True
,
help
=
"disable telemetry"
help
=
"disable telemetry"
)
)
parser
.
add_argument
(
'dest'
,
nargs
=
'?'
,
help
=
'set destination for log'
)
parser
.
add_argument
(
"behavior"
,
nargs
=
'?'
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
...
...
visualdl/server/serve.py
0 → 100644
浏览文件 @
67124a3c
#!/user/bin/env python
# Copyright (c) 2020 VisualDL Authors. All Rights Reserve.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =======================================================================
import
requests
import
json
import
os
from
visualdl.io
import
bfile
from
visualdl.reader.reader
import
is_VDLRecord_file
from
visualdl.utils.dir
import
CONFIG_PATH
from
visualdl.server.log
import
logger
def
get_server_url
():
with
open
(
CONFIG_PATH
,
'r'
)
as
fp
:
server_url
=
json
.
load
(
fp
)[
'server_url'
]
return
server_url
def
apply_for_token
():
url
=
get_server_url
()
+
'/sts/'
res
=
requests
.
post
(
url
=
url
).
json
()
return
res
def
get_url
(
path
=
''
,
model
=
''
,
**
kwargs
):
server_url
=
get_server_url
()
+
'/url/'
data
=
json
.
dumps
({
'path'
:
path
,
'model'
:
model
})
headers
=
{
"Content-Type"
:
"application/json"
}
res
=
requests
.
post
(
url
=
server_url
,
headers
=
headers
,
data
=
data
).
json
()
err_code
=
res
.
get
(
'code'
)
msg
=
res
.
get
(
'msg'
)
if
'000000'
==
err_code
:
url
=
msg
.
get
(
'url'
)
return
url
else
:
logger
.
error
(
msg
)
return
def
get_vdl_log_file
(
logdirs
):
"""Get logs.
Every dir(means `run` in vdl) has only one log(meads `actual log file`).
Returns:
walks: A dict like {"exp1": "vdlrecords.1587375595.log",
"exp2": "vdlrecords.1587375685.log"}
"""
walks
=
{}
for
logdir
in
logdirs
:
for
root
,
dirs
,
files
in
bfile
.
walk
(
logdir
):
walks
.
update
({
root
:
files
})
walks_temp
=
{}
for
run
,
tags
in
walks
.
items
():
tags_temp
=
[
tag
for
tag
in
tags
if
is_VDLRecord_file
(
tag
)]
tags_temp
.
sort
(
reverse
=
True
)
if
len
(
tags_temp
)
>
0
:
walks_temp
.
update
({
run
:
tags_temp
[
0
]})
return
walks_temp
def
upload_to_dev
(
logdir
=
None
,
model
=
None
):
if
not
logdir
and
not
model
:
logger
.
error
(
"Must specify directory to upload via `--logdir` or specify model to upload via `--model`."
)
return
walks
=
{}
if
logdir
:
walks
=
get_vdl_log_file
(
logdir
)
res
=
apply_for_token
()
err_code
=
res
.
get
(
'code'
)
msg
=
res
.
get
(
'msg'
)
if
'000000'
==
err_code
:
sts_ak
=
msg
.
get
(
'sts_ak'
)
sts_sk
=
msg
.
get
(
'sts_sk'
)
sts_token
=
msg
.
get
(
'token'
)
bucket_id
=
msg
.
get
(
'dir'
)
else
:
logger
.
error
(
msg
)
return
if
not
sts_ak
or
not
sts_sk
or
not
sts_token
:
return
bos_fs
=
bfile
.
BosConfigClient
(
bos_ak
=
sts_ak
,
bos_sk
=
sts_sk
,
bos_sts
=
sts_token
)
for
key
,
value
in
walks
.
items
():
filename
=
bos_fs
.
join
(
key
,
value
)
bos_fs
.
upload_object_from_file
(
path
=
bucket_id
,
filename
=
filename
)
if
model
:
if
os
.
path
.
getsize
(
model
)
>
1024
*
1024
*
100
:
logger
.
error
(
'Size of model must less than 100M.'
)
else
:
bos_fs
.
upload_object_from_file
(
path
=
bucket_id
,
filename
=
model
)
url
=
get_url
(
path
=
bucket_id
,
model
=
model
)
print
(
"You can view the visualization results on page`%s`."
%
url
)
visualdl/utils/dir.py
0 → 100644
浏览文件 @
67124a3c
# Copyright (c) 2020 VisualDL Authors. All Rights Reserve.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =======================================================================
import
os
import
json
VDL_SERVER
=
"http://paddlepaddle.org.cn/visualdl"
default_vdl_config
=
{
'server_url'
:
VDL_SERVER
}
USER_HOME
=
os
.
path
.
expanduser
(
'~'
)
VDL_HOME
=
os
.
path
.
join
(
USER_HOME
,
'.visualdl'
)
CONF_HOME
=
os
.
path
.
join
(
VDL_HOME
,
'conf'
)
CONFIG_PATH
=
os
.
path
.
join
(
CONF_HOME
,
'config.json'
)
def
init_vdl_config
():
if
not
os
.
path
.
exists
(
CONF_HOME
):
os
.
makedirs
(
CONF_HOME
)
if
not
os
.
path
.
exists
(
CONFIG_PATH
)
or
0
==
os
.
path
.
getsize
(
CONFIG_PATH
):
with
open
(
CONFIG_PATH
,
'w'
)
as
fp
:
fp
.
write
(
json
.
dumps
(
default_vdl_config
))
visualdl/utils/md5_util.py
0 → 100644
浏览文件 @
67124a3c
# Copyright (c) 2020 VisualDL Authors. All Rights Reserve.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =======================================================================
import
hashlib
def
md5
(
text
):
if
isinstance
(
text
,
str
):
text
=
text
.
encode
(
"utf8"
)
md5
=
hashlib
.
md5
()
md5
.
update
(
text
)
return
md5
.
hexdigest
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录