diff --git a/inst/@sym/function_handle.m b/inst/@sym/function_handle.m
index e130e7e4a..61d63a787 100644
--- a/inst/@sym/function_handle.m
+++ b/inst/@sym/function_handle.m
@@ -1,4 +1,5 @@
%% Copyright (C) 2014-2019 Colin B. Macdonald
+%% Copyright (C) 2022 Alex Vong
%%
%% This file is part of OctSymPy.
%%
@@ -255,13 +256,13 @@
%!test
%! % output to disk
%! fprintf('\n')
+%! temp_path = make_temp_dir__ (tempdir (), 'octsympy-temp-dir-');
%! if (exist ('OCTAVE_VERSION', 'builtin'))
-%! temp_file = tempname('', 'oct_');
+%! temp_file = [temp_path '/oct_temp_file'];
%! else
-%! temp_file = tempname();
+%! temp_file = [temp_path '/temp_file'];
%! end
%! % allow loading function from temp_file
-%! [temp_path, ans, ans] = fileparts(temp_file);
%! addpath(temp_path);
%! f = function_handle(2*x*y, 2^x, 'vars', {x y z}, 'file', temp_file);
%! assert( isa(f, 'function_handle'))
@@ -280,13 +281,13 @@
%!test
%! % output to disk: also works with .m specified
+%! temp_path = make_temp_dir__ (tempdir (), 'octsympy-temp-dir-');
%! if (exist ('OCTAVE_VERSION', 'builtin'))
-%! temp_file = [tempname('', 'oct_') '.m'];
+%! temp_file = [temp_path '/oct_temp_file.m'];
%! else
-%! temp_file = [tempname() '.m'];
+%! temp_file = [temp_path '/temp_file.m'];
%! end
%! % allow loading function from temp_file
-%! [temp_path, ans, ans] = fileparts(temp_file);
%! addpath(temp_path);
%! f = function_handle(2*x*y, 2^x, 'vars', {x y z}, 'file', temp_file);
%! assert( isa(f, 'function_handle'))
@@ -319,13 +320,13 @@
%! H = [x y z];
%! M = [x y; z 16];
%! V = [x;y;z];
+%! temp_path = make_temp_dir__ (tempdir (), 'octsympy-temp-dir-');
%! if (exist ('OCTAVE_VERSION', 'builtin'))
-%! temp_file = tempname('', 'oct_');
+%! temp_file = [temp_path '/oct_temp_file'];
%! else
-%! temp_file = tempname();
+%! temp_file = [temp_path '/temp_file'];
%! end
%! % allow loading function from temp_file
-%! [temp_path, ans, ans] = fileparts(temp_file);
%! addpath(temp_path);
%! h = function_handle(H, M, V, 'vars', {x y z}, 'file', temp_file);
%! assert( isa(h, 'function_handle'))
diff --git a/inst/make_temp_dir__.m b/inst/make_temp_dir__.m
new file mode 100644
index 000000000..0eab4cdad
--- /dev/null
+++ b/inst/make_temp_dir__.m
@@ -0,0 +1,50 @@
+%% Copyright (C) 2022 Alex Vong
+%%
+%% This file is part of OctSymPy.
+%%
+%% OctSymPy is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published
+%% by the Free Software Foundation; either version 3 of the License,
+%% or (at your option) any later version.
+%%
+%% This software is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty
+%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+%% the GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public
+%% License along with this software; see the file COPYING.
+%% If not, see .
+
+%% -*- texinfo -*-
+%% @documentencoding UTF-8
+%% @deftypefun {@var{path} =} make_temp_dir__ (@var{tmpdir}, @var{prefix})
+%% Try to create temporary directory in temporary directory @var{tmpdir} with
+%% prefix @var{prefix} in the most secure and portable way possible.
+%%
+%% This function is not really intended for end users.
+%%
+%% @end deftypefun
+
+
+function path = make_temp_dir__ (tmpdir, prefix)
+ cmd = {'import tempfile'
+ '(tmpdir, prefix) = _ins'
+ 'return tempfile.mkdtemp(dir=tmpdir, prefix=prefix)'};
+ path = pycall_sympy__ (cmd, tmpdir, prefix);
+end
+
+
+%!test
+%! % general test
+%! path = make_temp_dir__ (tempdir (), 'octsympy-');
+%! assert (~isempty (strfind (path, tempdir ())));
+%! assert (~isempty (strfind (path, 'octsympy-')));
+%! assert (isfolder (path));
+%! assert (isequal (ls (path), ''));
+%! assert (rmdir (path));
+
+%!error
+%! if (exist ('OCTAVE_VERSION', 'builtin'))
+%! make_temp_dir__ ('/nonexistent', '');
+%! end