You're looking for Property Maps. From the docs:
Property maps are a way of associating additional information to the vertices, edges or to the graph itself. There are thus three types of property maps: vertex, edge and graph. All of them are handled by the same class, PropertyMap.
Property maps are far more flexible than simple edge weights because you can attach arbitrary objects to graph nodes and edges, but using them to map edges to floating-point or integer values can achieve the same effect.
Example code from the documentation:
from itertools import izip
from numpy.random import randint
g = Graph()
g.add_vertex(100)
# insert some random links
for s,t in izip(randint(0, 100, 100), randint(0, 100, 100)):
g.add_edge(g.vertex(s), g.vertex(t))
vprop_double = g.new_vertex_property("double") # Double-precision floating point
vprop_double[g.vertex(10)] = 3.1416
vprop_vint = g.new_vertex_property("vector<int>") # Vector of ints
vprop_vint[g.vertex(40)] = [1, 3, 42, 54]
eprop_dict = g.new_edge_property("object") # Arbitrary python object.
eprop_dict[g.edges().next()] = {"foo": "bar", "gnu": 42} # In this case, a dict.
gprop_bool = g.new_edge_property("bool") # Boolean
gprop_bool[g] = True
For the second part of your question, here is the graph-tool drawing and layout documentation, which contains a few different algorithms you can use for the graph display instead of graph_draw
. Take a look at the algorithms that accept an edge property map as an input argument. I haven't used them before, but it looks like passing in the correct edge weight property map when you create the layout object should take care of the edge length scaling for you.