I think targeting the AST as Hy does is the way forward. Targeting the bytecode is impossible to maintain (this is why clojure-py does not support Python 3).
The other huge advantage of Hy is that it does not attempt to reproduce the Clojure object model, but just the Python one. Namespaces are just modules, objects are not wrapped in Vars, simple binary ops (+, -, etc.) are not wrapped in 1/ a Var and then 2/ a function that calls the BINARY_ADD opcode, etc. I saw somewhere a comparison of fibonacci according to which Hy is much faster than clojure-py; if you look at the bytecode it's not a surprise:
$ hy -c '(import dis) (defn f [n] (if (< n 2) 1 (+ (f (- n 1)) (f (- n 2))))) (dis.dis f)'
1 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (2)
6 COMPARE_OP 0 (<)
9 POP_JUMP_IF_FALSE 16
12 LOAD_CONST 2 (1)
15 RETURN_VALUE
>> 16 LOAD_GLOBAL 0 (f)
19 LOAD_FAST 0 (n)
22 LOAD_CONST 2 (1)
25 BINARY_SUBTRACT
26 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
29 LOAD_GLOBAL 0 (f)
32 LOAD_FAST 0 (n)
35 LOAD_CONST 1 (2)
38 BINARY_SUBTRACT
39 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
42 BINARY_ADD
43 RETURN_VALUE
(which is the same as the bytecode for the naive Python implementation, of course)
$ clojurepy [13-11-09 17:25:16]
clojure-py 0.2.4
Python 2.7.5 (default, Sep 6 2013, 09:55:21)
[GCC 4.8.1 20130725 (prerelease)]
user=> (defn f [n] (if (< n 2) 1 (+ (f (- n 1)) (f (- n 2)))))
#'user/f
user=> (dis/dis f)
0 0 LOAD_CONST 1 (<function <_auto_ at 0x1004f50>)
3 LOAD_FAST 0 (n)
6 LOAD_CONST 2 (2)
9 CALL_FUNCTION 2
12 STORE_FAST 1 (p0__1443#)
15 LOAD_FAST 1 (p0__1443#)
18 LOAD_CONST 0 (None)
21 COMPARE_OP 9 (is not)
24 POP_JUMP_IF_FALSE 45
27 LOAD_FAST 1 (p0__1443#)
30 LOAD_CONST 3 (False)
33 COMPARE_OP 9 (is not)
36 POP_JUMP_IF_FALSE 45
39 LOAD_CONST 4 (1)
42 JUMP_ABSOLUTE 117
>> 45 LOAD_CONST 5 (#'clojure.core/+)
48 LOAD_ATTR 0 (deref)
51 CALL_FUNCTION 0
54 LOAD_CONST 6 (#'user/f)
57 LOAD_ATTR 0 (deref)
60 CALL_FUNCTION 0
63 LOAD_CONST 7 (#'clojure.core/-)
66 LOAD_ATTR 0 (deref)
69 CALL_FUNCTION 0
72 LOAD_FAST 0 (n)
75 LOAD_CONST 4 (1)
78 CALL_FUNCTION 2
81 CALL_FUNCTION 1
84 LOAD_CONST 6 (#'user/f)
87 LOAD_ATTR 0 (deref)
90 CALL_FUNCTION 0
93 LOAD_CONST 7 (#'clojure.core/-)
96 LOAD_ATTR 0 (deref)
99 CALL_FUNCTION 0
102 LOAD_FAST 0 (n)
105 LOAD_CONST 2 (2)
108 CALL_FUNCTION 2
111 CALL_FUNCTION 1
114 CALL_FUNCTION 2
>> 117 RETURN_VALUE
nil
Oh my...
So basically Hy is just a nice (if you like lisp) way to write Python code. Which is good to have, of course, and I think if you want to use Clojure libs on top of that you basically "just" need to reimplement whatever parts are needed of the Clojure API in Python.
Antony