一直以来都是看别人的文章、博客和主页,自己很少写东西。一是水平有限,怕写错了闹笑话;二是觉得自己想写的网上基本都有了,自己再写也是徒劳。
之所以今天有这么大的动力写这篇文章,是因为自己在网上搜了好久,没有说的特别详细的;二是总是抄别人的,自己不贡献点东西,有一种愧疚感。希望和我一样初学superset的工作者,不用再像我当初一样挖坑、填坑。。。循环(险些神经衰弱。。。。)
废话不多说,进入主题:
系统基本要求:最好是较完整版的centos7,支持yum install安装命令
下面都是些安装流程,代码居多,字会比较少:
安装python3(因为想写成详细版,就把一些基础的环境安装也加了进来,可适自己的情况选择跳过):
python3依赖包安装
yum groupinstall "Development tools"
yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
# 本文以/home/software作为主目录,所有软件都安装于此
mkdir -p /home/software
cd /home/software
wget https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tar.xz
tar -xf Python-3.5.3.tar.xz
mv Python-3.5.3 python3.5.3
cd python3.5.3
./configure prefix=/home/software/python3
make
make install
配置python3和pip3:
ln -s /home/software/python3/bin/python3 /usr/bin/python3
ln -s /home/software/python3/bin/pip3 /usr/bin/pip3
设置后执行下python3,然后再执行下pip3,如果有反应说明配置成功
安装superset:
yum install cyrus-sasl-lib.x86_64 cyrus-sasl-devel.x86_64 libgsasl-devel.x86_64
yum install build-essential libssl-dev libffi-dev python-dev python-pip libsasl2-dev libldap2-dev
pip3 install superset
安装好之后superset项目会出现在/home/software/lirui/python3/lib/python3.5/site-packages/superset文件夹下
配置superset:
vi ~/.bashrc
加入:alias superset='/home/software/python3/lib/python3.5/site-packages/superset/bin/superset'
# 保存并退出
source ~/.bashrc
此时,执行supeset会出现一些命令提示
安装superset一些依赖模块:
pip3 install flask_compress
pip3 install unicodecsv
pip3 install geopy
配置fabmanager环境变量:
ln -s /home/software/python3/bin/fabmanager /usr/bin/fabmanager
初始化superset管理员账户:
fabmanager create-admin --app superset
# 按照命令提示依次输入想要设置的用户信息,我是依次输入的admin,admin,admin,admin,1111@qq.com,123,123
初始化superset账户
superset db upgrade
superset load_examples
superset init
安装nodejs(make && make install步骤耗时较长,将近半小时,可以干点别的或四处走走):
资源包下载:wget https://nodejs.org/dist/v8.10.0/node-v8.10.0-linux-x64.tar.xz
xz -d node-v8.10.0-linux-x64.tar.xz
tar -xvf node-v8.10.0-linux-x64.tar
# 二进制安装文件下载:
wget https://nodejs.org/dist/v8.10.0/node-v8.10.0.tar.gz
tar -zxvf node-v8.10.0.tar.gz
cd node-v8.10.0
# 编译和安装
./configure --prefix=/home/software/nodejs
make && make install
nodejs主要是利用里面的一些模块处理前端的一些代码,比如webpack模块,用于代码打包
# 配置node和npm路径:
vi /etc/profile
# 加入以下内容:
export NODE_HOME=/home/software/nodejs
PATH变量后面追加(注意要包含冒号) :$NODE_HOME/bin
保存并退出
source /etc/profile
退出后可以执行命令node,npm
安装cnpm,更新npm和cnpm(用了淘宝的国内链接,安装和更新比较快)
npm install -g cnpm --registry=https://registry.npm.taobao.org #安装cnpm
cnpm install npm -g # cnpm更新npm
cnpm install -g n # cnpm自更新
安装uwsgi(自己实际安装的时候发现,pip3 install uwsgi有时会安装到python2的环境上去,经大神指教,改成如下):
python3 -m pip install uwsgi
安装nginx:
wget http://nginx.org/download/nginx-1.10.3.tar.gz
tar zxvf nginx-1.10.3.tar.gz
mv nginx-1.10.3 nginx
cd nginx
./configure --prefix=/home/software/nginx --with-http_stub_status_module --with-http_gzip_static_module
make
make install
配置nginx环境变量:
vi ~/.bashrc
添加:alias nginx='/home/software/nginx/sbin/nginx'
保存并退出
source ~/.bashrc
关闭防火墙:
systemctl stop firewalld.service
systemctl disable firewalld.service
运行:
cd /home/software/python3/lib/python3.5/site-packages/superset/static/assets
cnpm install -d //生成依赖包目录node_modules,下载依赖
cnpm run dev //监听页面变动并自动打包(生产环境需要运行cnpm run prod,此命令执行耗时大概10小时左右,非上线请勿执行)
执行完以上命令,会把打包后的文件放到/home/software/python3/lib/python3.5/site-packages/superset/static/assets/dist文件夹下
然后,在/home/software/python3/lib/python3.5/site-packages/superset中创建run.py,此文件为uwsgi的文件入口,项目的内容通过此文件与uwsgi交互
vi run.py
加入以下代码:
from superset import app
if __name__ == '__main__':
app.run(host='0.0.0.0')
保存并退出
uwsgi配置
mkdir -p /home/uwsgi_conf
cd /home/uwsgi_conf
vi uwsgi.ini
加入以下内容(里面有些配置项我也不是很懂,但一般都是这么配):
[uwsgi]
# 指定uwsgi协议入口文件
wsgi-file=/home/software/python3/lib/python3.5/site-packages/superset/run.py
# 指定入口文件中调用run方法的变量名
callable=app
# 指定sock的文件路径
socket= /home/uwsgi_conf/uwsgi.sock
# 指定静态文件(static-map=网页地址=本地文件位置,静态文件一般在nginx中配置)
#static-map=/static=/home/myproject/static
# 设置日志目录
daemonize= /home/uwsgi_conf/uwsgi.log
# pid文件位置
pidfile= /home/uwsgi_conf/uwsgi.pid
# 进程个数
workers=4
# 指定IP端口(因为后期靠nginx分发,所以不需要wsgi的http接口)
http=localhost:8088
# 启动uwsgi的用户名和用户组(都用root启动,是出于权限的考虑,其他权限可能会启动失败)
uid=root
gid=root
# 启用主进程
master=true
# 自动移除unix Socket和pid文件当服务停止的时候
vacuum=true
# 序列化接受的内容,如果可能的话
thunder-lock=true
# 启用线程
enable-threads=true
# 设置自中断时间
harakiri=30
# 设置缓冲
post-buffering=4096
# 设置代码改动后自动加载
py-autoreload = 1
保存并退出
执行
uwsgi --ini /home/uwsgi_conf/uwsgi.ini
打开浏览器,访问127.0.0.1:8088
如果正常访问,则说明配置没有问题
nginx配置:
修改nginx配置文件
文件路径:/home/software/nginx/conf/nginx.conf(此文件内容较多,只改一部分)
vi /home/software/nginx/conf/nginx.conf
文件头3行改为(root权限,4个进程,报错的日志文件路径):
user root;
worker_processes 4;
error_log /home/uwsgi_conf/error.log;
找到server配置项,原有的location项删除掉,替换成下面这些(注意因为项目引用了2个模块的js资源文件,所以要设置2个静态路径):
location / {
include uwsgi_params; # 导入一个Nginx模块他是用来和uWSGI进行通讯的
uwsgi_connect_timeout 30; # 设置连接uWSGI超时时间
uwsgi_pass unix:/home/uwsgi_conf/uwsgi.sock; # 指定uwsgi的sock文件所有动态请求就会直接丢给他
root html;
index index.html index.htm;
}
location /static\/appbuilder/ {
alias /home/software/python3/lib/python3.5/site-packages/flask_appbuilder/static/;
index index.html index.htm;
}
location /static\/assets/ {
alias /home/software/python3/lib/python3.5/site-packages/superset/static/;
index index.html index.htm;
}
保存并退出
执行
nginx -c /home/software/nginx/conf/nginx.conf
打开浏览器,访问 127.0.0.1如果可以访问,说明配置成功,如果出现报错的话,去/home/uwsgi_conf/error.log中找问题
顺便提一句,关闭所有uwsgi和nginx进程的命令:
ps -aux|grep -E 'uwsgi|nginx'|awk '{print $2}'|xargs kill -9
关闭后重启服务可以执行:
uwsgi --ini /home/uwsgi_conf/uwsgi.ini & nginx -c home/software/nginx/conf/nginx.conf
######################################分####割######线################################
一些配置:
所有的配置项均在 /home/software/python3/lib/python3.5/site-packages/superset/config.py下
数据库的配置
本人用不习惯sqlite,所以将数据库改成了mysql,改动如下:
SQLALCHEMY_DATABASE_URI = 'mysql://用户名:密码@mysql地址:端口(默认3306)/数据库名称?charset=utf8'
pymysql模块安装
pip3 install pymysql
安装之后需要还要修改一下sqlalchemy的配置文件,才能让superset识别pymysql
vi /home/software/python3/lib/python3.5/site-packages/sqlalchemy/dialects/mysql/__init__.py
在最上面加入2行:
import pymysql
pymysql.install_as_MySQLdb()
保存并退出
修改完之后记得重新执行:
supeset db upgrade
superset load_examples
superset init
执行完毕后,执行,
uwsgi --ini /home/uwsgi_conf/uwsgi.ini & nginx -c home/software/nginx/conf/nginx.conf
访问:127.0.0.1,,大功告成
顺便说下centos7下mysql的安装:
yum -y install mariadb # 安装
systemctl start mariadb # 启动
输入 mysql,进入mysql客户端
use mysql #进入mysql配置库
select user(); #选中当前用户
set password=password('123456'); # 为当前用户设置密码为123456
退出之后,就需要密码才能登陆了,命令如下
mysql -hlocalhost -uroot -p
之后输入自己的密码登陆
设置远程访问
GRANT ALL PRIVILEGES ON *.* TO '用户名'@'%'IDENTIFIED BY '数据库的密码' WITH GRANT OPTION;
flush privileges; # 确认设置
退出后,可远程连接mysql
###########################分######割#######线#################################
项目构成的简单介绍
此框架后端以flask为主,通过flask的一些衍生模块进行快捷的开发,如:flask_appbuilder,flask_bootstrap
路由以及和前端交互的主逻辑都在superset/views/core.py下
前端主要框架是react和redux(负责数据存储),也混合了一些jquery,最后将这些代码打包生成了dist下面的可执行的js文件。
打包入口文件在superset/static/assets/webpack.config.js的entry配置项中,如果懂react的朋友和从此文件开始下手,改一些前端的效果,当然,改完之后需要经过编译才能生效,测试编译命令(需要在superset/static/assets下执行):cnpm run dev,在测试确定页面没有问题的情况下,在此目录下执行cnpm run prod,此命令大概需要10小时,执行之后就去睡觉吧,第二天就能看到结果了。
下面说几个改过的简单的例子:
1、pivot_table列顺序排列修改
列排序依赖于view/core.py文件中的explore_json方法,此方法返回一个json对象,json解析后的json_obj['data']['html']决定了页面最终的列的排序,json的生成依赖于根目录下的viz.py文件的get_payload方法,BaseViz.get_payload方法中的get_data方法
会生成json,注意此get_data为PivotTableViz类下的方法(非BaseViz下的),此文件生成的df顺序为最终返回在json顺序,在return前做出修改,加入以下代码:
如果后缀是数据,则返回数组,否则返回当前字符串
def tarns_to_num(str_tem):
target_str = str_tem[-1].split('_')[-1].replace('%', '')
result = float(target_str) if target_str.replace(',', '').isdigit() else target_str
return result
生成列重新排序后的df
columns_list = list(df.columns)
sort_columns_list = sorted(columns_list, key=tarns_to_num, reverse=False)
df = df.loc[:, sort_columns_list]
2、pivot_table按照多列groupby的时候,排序功能会消失
此问题的df得到方式和例子1一致,都在viz.py的PivotTableViz类下的get_data方法中,通过修改最终产生的df,将多列groupby改成单列groupby,并把其余的列追加到columns中去;
除此之外statis/assets/visualizations/pivot_table.js文件中也对此做了限制,当groupby列数多于1列时,不在提供排序功能,所以要对此文件也做出修改,综上所述,改动如下:
viz.py文件的PivotTableViz类下的get_data方法,在return 方法之前加入以下代码:
多列groupby的index类与单列的区别在于是否是pd.core.indexes.multi.MultiIndex的子类
if isinstance(df.index, pd.core.indexes.multi.MultiIndex):
index_list = list(zip(*list(df.index)))
columns = list(df.columns)
index_names = [(columns[0][0], x) for x in list(df.index.names)]
index_names[0] = index_names[0][1]
columns = list(df.columns)
index = pd.Index(index_list[0], dtype='object', name=index_names[0])
for i in range(1, len(index_names)):
df[(index_names[i])] = index_list[i]
df.index = index
print(index_names[1:] + columns)
df = df.loc[:, index_names[1:] + columns]
statis/assets/visualizations/pivot_table.js的第42行左右:
将if (fd.groupby.length === 1) 改为 if (fd.groupby.length >= 1)
改完之后npm run dev编译后即可。
唉,感觉废话太多,有点跑偏了,但真心希望看到这篇文章的同学不再经历我的血泪史,所以有点啰嗦,希望对看到的朋友能有帮助吧,有疑问请加qq:270239148,欢迎一起讨论