-
Notifications
You must be signed in to change notification settings - Fork 188
/
Copy pathpyinit.jl
115 lines (94 loc) · 4.26 KB
/
pyinit.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Initializing Python (surprisingly complicated; see also deps/build.jl)
#########################################################################
# global PyObject constants, initialized to NULL and then overwritten in __init__
# (eventually, the ability to define global const in __init__ may go away,
# and in any case this is better for type inference during precompilation)
const inspect = PyNULL()
const builtin = PyNULL()
const BuiltinFunctionType = PyNULL()
const TypeType = PyNULL()
const MethodType = PyNULL()
const MethodWrapperType = PyNULL()
const ufuncType = PyNULL()
const format_traceback = PyNULL()
const pyproperty = PyNULL()
const jlfun2pyfun = PyNULL()
const c_void_p_Type = PyNULL()
# other global constants initialized at runtime are defined via Ref
# or are simply left as non-const values
const pynothing = Ref{PyPtr}(0)
const pyxrange = Ref{PyPtr}(0)
#########################################################################
function __init__()
# issue #189
libpy_handle = libpython === nothing ? C_NULL :
Libdl.dlopen(libpython, Libdl.RTLD_LAZY|Libdl.RTLD_DEEPBIND|Libdl.RTLD_GLOBAL)
already_inited = 0 != ccall((@pysym :Py_IsInitialized), Cint, ())
if !already_inited
Py_SetPythonHome(libpy_handle, PYTHONHOME, wPYTHONHOME, pyversion)
if !isempty(pyprogramname)
if pyversion.major < 3
ccall((@pysym :Py_SetProgramName), Void, (Cstring,), pyprogramname)
else
ccall((@pysym :Py_SetProgramName), Void, (Ptr{Cwchar_t},), wpyprogramname)
end
end
ccall((@pysym :Py_InitializeEx), Void, (Cint,), 0)
end
# Will get reinitialized properly on first use
is_windows() && (PyActCtx[] = C_NULL)
# Make sure python wasn't upgraded underneath us
new_pyversion = convert(VersionNumber, split(unsafe_string(ccall(@pysym(:Py_GetVersion),
Ptr{UInt8}, ())))[1])
if new_pyversion.major != pyversion.major
error("PyCall precompiled with Python $pyversion, but now using Python $new_pyversion; ",
"you need to relaunch Julia and re-run Pkg.build(\"PyCall\")")
end
copy!(inspect, pyimport("inspect"))
copy!(builtin, pyimport(pyversion.major < 3 ? "__builtin__" : "builtins"))
copy!(pyproperty, pybuiltin(:property))
pyexc_initialize() # mappings from Julia Exception types to Python exceptions
types = pyimport("types")
copy!(TypeType, pybuiltin("type")) # for pytypeof
# cache Python None -- PyPtr, not PyObject, to prevent it from
# being finalized prematurely on exit
pynothing[] = @pyglobalobj(:_Py_NoneStruct)
# xrange type (or range in Python 3)
pyxrange[] = @pyglobalobj(:PyRange_Type)
# ctypes.c_void_p for Ptr types
copy!(c_void_p_Type, pyimport("ctypes")["c_void_p"])
# traceback.format_tb function, for show(PyError)
copy!(format_traceback, pyimport("traceback")["format_tb"])
init_datetime()
pyjlwrap_init()
# jl_FunctionType is a class, and when assigning it to an object
# obj[:foo] = some_julia_function
# it won't behave like a regular Python method because it's not a Python
# function (in particular, `self` won't be passed to it). The solution is:
# obj[:foo] = jlfun2pyfun(some_julia_function)
# This is a bit of a kludge, obviously.
copy!(jlfun2pyfun,
pyeval_("""lambda f: lambda *args, **kwargs: f(*args, **kwargs)"""))
if !already_inited
# some modules (e.g. IPython) expect sys.argv to be set
if pyversion.major < 3
argv_s = ""
argv = unsafe_convert(Ptr{UInt8}, argv_s)
ccall(@pysym(:PySys_SetArgvEx), Void, (Cint,Ptr{Ptr{UInt8}},Cint), 1, &argv, 0)
else
argv_s = Cwchar_t[0]
argv = unsafe_convert(Ptr{Cwchar_t}, argv_s)
ccall(@pysym(:PySys_SetArgvEx), Void, (Cint, Ptr{Ptr{Cwchar_t}}, Cint), 1, &argv, 0)
end
# Some Python code checks sys.ps1 to see if it is running
# interactively, and refuses to be interactive otherwise.
# (e.g. Matplotlib: see PyPlot#79)
if isinteractive()
let sys = pyimport("sys")
if !haskey(sys, "ps1")
sys["ps1"] = ">>> "
end
end
end
end
end