netkiller-gantt
Best project gantt charts in Python
Python Gantt 工具
安装依赖
MacOS 环境
brew install cairo
brew install pkg-config
pip3 install pycairo -i https://pypi.tuna.tsinghua.edu.cn/simple
Linux 环境
dnf install -y cairo-devel python3-cairo python3-pillow
配置镜像
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
root@netkiller ~# cat /root/.config/pip/pip.conf
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
安装 netkiller-gantt
pip install netkiller-gantt -i https://pypi.tuna.tsinghua.edu.cn/simple
命令帮助
root@netkiller ~# gantt
Usage: gantt [options]
Options:
-h, --help show this help message and exit
--stdin cat gantt.json | gantt -s file.svg
-c /path/to/gantt.csv, --csv=/path/to/gantt.csv
/path/to/gantt.csv
-l /path/to/gantt.json, --load=/path/to/gantt.json
load data from file.
-d, --debug debug mode
loading data from mysql:
-H localhost, --host=localhost
-u root, --username=root
-p PASSWORD, --password=PASSWORD
-D test, --database=test
Charts:
-t 项目甘特图, --title=项目甘特图
甘特图标题
-W 5, --workweeks=5
workweeks default 5
-g, --gantt Gantt chart
-w, --workload Workload chart
-s /path/to/gantt.svg, --save=/path/to/gantt.svg
save file
Homepage: https://www.netkiller.cn Author: Neo <netkiller@msn.com>
生成甘特图
从标准输出载入json数据生成甘特图
准备 json 文件
{
"1": {
"id": 1,
"name": "开发需求排期",
"start": "2023-02-22",
"finish": "2023-03-03",
"subitem": {
"11": {
"id": 11,
"name": "用户登录开发",
"start": "2023-02-22",
"finish": "2023-02-24",
"progress": 4,
"resource": "陈景峰"
},
"12": {
"id": 12,
"name": "权限角色开发",
"start": "2023-02-27",
"finish": "2023-03-03",
"resource": "Neo",
"progress": 5,
"predecessor": 11
},
"2": {
"id": "2",
"name": "测试任务排期",
"start": "2023-03-01",
"finish": "2023-03-15",
"subitem": {
"21": {
"id": 21,
"name": "用户登陆测试",
"start": "2023-03-01",
"finish": "2023-03-08",
"resource": "陈景峰",
"progress": 4
},
"22": {
"id": 22,
"name": "权限角色测试",
"start": "2023-03-09",
"finish": "2023-03-15",
"resource": "netkiller",
"progress": 0,
"predecessor": 21
}
}
}
}
},
"3": {
"id": 3,
"name": "任务组测试",
"start": "2023-02-25",
"finish": "2023-03-10",
"resource": "陈景峰",
"progress": 3,
"subitem": {
"4": {
"id": 4,
"name": "Java",
"start": "2023-02-24",
"finish": "2023-02-27",
"resource": "司空摘星",
"progress": 2
},
"5": {
"id": 5,
"name": "PHP",
"start": "2023-03-03",
"finish": "2023-03-15",
"resource": "阿不都沙拉木",
"progress": 5,
"predecessor": 4,
"subitem": {
"83": {
"id": 83,
"name": "V7.0",
"start": "2023-03-03",
"finish": "2023-03-05",
"predecessor": 82,
"subitem": {
"83": {
"id": 83,
"name": "V8.0",
"start": "2023-03-06",
"finish": "2023-03-10",
"predecessor": 82,
"subitem": {
"83": {
"id": 83,
"name": "V8.5",
"start": "2023-03-13",
"finish": "2023-03-16",
"predecessor": 82
}
}
}
}
}
}
},
"6": {
"id": "6",
"name": "Go",
"start": "2023-03-10",
"finish": "2023-03-20",
"milestone": true
},
"7": {
"id": 7,
"name": "Python",
"start": "2023-03-06",
"finish": "2023-03-08",
"predecessor": 5
},
"8": {
"id": 8,
"name": "Swift",
"start": "2023-02-27",
"finish": "2023-03-16",
"subitem": {
"81": {
"id": 81,
"name": "LLVM",
"start": "2023-02-28",
"finish": "2023-03-06",
"predecessor": 4
},
"82": {
"id": 82,
"name": "Clang",
"start": "2023-03-07",
"finish": "2023-03-10",
"predecessor": 81
},
"83": {
"id": 83,
"name": "Rust",
"start": "2023-03-13",
"finish": "2023-03-16",
"predecessor": 82
}
}
}
}
}
}
开始生成 Gantt 甘特图
neo@MacBook-Pro-M2 ~> cat gantt.json | gantt --stdin
/Users/neo/workspace/GitHub/devops
Usage: gantt [options] message
Options:
-h, --help show this help message and exit
-l /path/to/gantt.json, --load=/path/to/gantt.json
load data from file.
-s /path/to/gantt.svg, --save=/path/to/gantt.svg
save file
--stdin cat gantt.json | gantt -s file.svg
-d, --debug debug mode
从 CSV 文件生成
从禅道导出 csv 文件
select id, parent, name,estStarted,deadline,assignedTo from zt_task
INTO OUTFILE '/tmp/project.csv'
FIELDS ENCLOSED BY '"'
TERMINATED BY ‘,’
ESCAPED BY '"'
LINES TERMINATED BY '\r\n';
命令行执行方法
rm -rf /tmp/project.csv
cat <<EOF | mysql -h127.0.0.1 -uroot -p123456 zentao
SELECT 'id','name','start','finish', 'resource', 'parent'
UNION
select id, name,estStarted,deadline,assignedTo, parent from zt_task
INTO OUTFILE '/tmp/project.csv'
FIELDS ENCLOSED BY '"'
TERMINATED BY ','
ESCAPED BY '"'
LINES TERMINATED BY '\r\n';
EOF
如果导出指定的资源,可以通过查询 assignedTo 实现
select id, name,estStarted as start, deadline as finish, assignedTo as resource, parent from zt_task where `group` = 4 order by id desc limit 100;
select id, name,estStarted as start, deadline as finish, assignedTo as resource, parent from zt_task where assignedTo in ('neo','netkiller','tom','jerry') order by id desc limit 100;
从 MySQL 数据库生成甘特图
注意:MySQL 5.7 和 MySQL 8.0 有略微差别
MySQL 5.7
CREATE TABLE `project` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT '任务名称',
`start` date NOT NULL COMMENT '开始日期',
`finish` date NOT NULL COMMENT '完成日期',
`resource` varchar(255) DEFAULT NULL COMMENT '资源',
`predecessor` bigint(20) DEFAULT NULL COMMENT '前置任务',
`milestone` bit(1) DEFAULT NULL COMMENT '里程碑',
`parent` bigint(20) DEFAULT NULL COMMENT '父任务',
`status` enum('Enabled','Disabled') DEFAULT 'Enabled' COMMENT '状态',
PRIMARY KEY (`id`),
KEY `project_has_subproject` (`parent`),
CONSTRAINT `project_has_subproject` FOREIGN KEY (`parent`) REFERENCES `project` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4
MySQL 8.0
CREATE TABLE `project` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务名称',
`start` date NOT NULL DEFAULT (curdate()) COMMENT '开始日期',
`finish` date NOT NULL DEFAULT (curdate()) COMMENT '完成日期',
`resource` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '资源',
`predecessor` bigint unsigned DEFAULT NULL COMMENT '前置任务',
`milestone` bit(1) DEFAULT b'0' COMMENT '里程碑',
`parent` bigint unsigned DEFAULT NULL COMMENT '父任务',
PRIMARY KEY (`id`),
KEY `project_has_subproject` (`parent`),
KEY `task_has_predecessor_idx` (`predecessor`),
CONSTRAINT `project_has_subproject` FOREIGN KEY (`parent`) REFERENCES `project` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
插入测试数据
INSERT INTO `project` (`id`,`name`,`start`,`finish`,`resource`,`predecessor`,`milestone`,`parent`) VALUES (1,'任务组','2023-03-26','2023-04-10','小明',NULL,'0',NULL);
INSERT INTO `project` (`id`,`name`,`start`,`finish`,`resource`,`predecessor`,`milestone`,`parent`) VALUES (2,'任务A','2023-03-26','2023-03-29','小明',NULL,'0',1);
INSERT INTO `project` (`id`,`name`,`start`,`finish`,`resource`,`predecessor`,`milestone`,`parent`) VALUES (3,'任务B','2023-03-31','2023-04-01','小张',2,'0',1);
INSERT INTO `project` (`id`,`name`,`start`,`finish`,`resource`,`predecessor`,`milestone`,`parent`) VALUES (4,'任务C','2023-04-02','2023-04-08','小张',3,'0',1);
INSERT INTO `project` (`id`,`name`,`start`,`finish`,`resource`,`predecessor`,`milestone`,`parent`) VALUES (5,'里程碑','2023-04-06','2023-04-06',NULL,NULL,'1',NULL);
bit(1) 类型数据更新注意事项
UPDATE `test`.`project` SET `milestone` = b'001' WHERE (`id` = '11');
生成甘特图
gantt --host mysql.netkiller.cn -u root -p passw0rd --database test -g
Metadata
Release files for netkiller-gantt 0.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| netkiller-gantt-0.0.6.tar.gz | 43.4 MB | Without provenance | Details for netkiller-gantt-0.0.6.tar.gz |
Release files / netkiller-gantt-0.0.6.tar.gz
| Download URL | netkiller-gantt-0.0.6.tar.gz |
|---|---|
| Size | 43.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
403868c0fc0af96c2374a7d30a8bf7d541c6283c9c3fc944a727e73ff4c5ffd1
|
|
BLAKE2b-256 checksum How to use checksums |
4dda9465aafc0080f7e93fd9378ed02eaebc381f0aeec82059c294e8c598ec6e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.10.5
|
Security for netkiller-gantt 0.0.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.