Python module is not detected/known to C++ in embedding application - boost-python

I am writing a python embedding in C++ application. The related code snippet that I declare the module of python(user-defined one) that needs to be embedded as below:
boost::python::object main_module = boost::python::import("__main__");
boost::python::object main_namespace = main_module.attr("__dict__");
boost::python::exec("import python_module", main_namespace); //This line is the culprit
However, I'm stuck when I receive the following error:
terminate called after throwing an instance of 'boost::python::error_already_set'
My user-defined python module resides in the same directory as my C++ code. When I try like to use numpythat works, the problem is that only with my user-defined one, it doesn't. What could be done in order to debug it?
EDIT:
After I include the code in try/catch block, I obtained the following compile error:
ImportError: No module named python_module
I also try to add this:
boost::python::exec("import sys; sys.path.append('/path/to/python_module.py');", main_namespace);
boost::python::exec("import python_module", main_namespace);
but not yet working.
The problem now is how do I make it known to my C++ code?

You can try a couple of things:
In your C++ app: boost::python::exec("import sys; sys.path.append('/path/to'); import python_module; del sys"), main_namespace);, or
In your shell: cd /path/to; call-your-c++-app. Then, in C++, you would need only to boost::python::exec("import python_module");, or
Set your environment variable to export PYTHONPATH=/path/to:${PYTHONPATH} and execute your program. Your C++ in this case would need only to boost::python::exec("import python_module"); as in the above solution.
The issue: You need to append the path leading to the module to sys.path and not the path to the module file itself.
Another hint: by default, Python will load modules from the current directory. If you cd there and execute your application from that directory, it should find the module on the current directory.

Related

Perl executable crashes even though file is not missing

I get the following error:
Can't load '...\AppData\Local\Temp\par-6e72616f\cache-20221205133501\5743946b.xs.dll' for module GD:
load_file:
The specified module could not be found at <embedded>/DynaLoader.pm line 193.
at <embedded>/PAR/Heavy.pm line 140.
(Line breaks added for readability.)
Here is the file t2.pl:
use GD;
Here is the command to convert it to an exe (I use a batch file that timestamps it):
pp -T 20221205133501 -o t2_20221205133501.exe t2.pl
On my laptop, the exe works, but on a barebones Citrix environment it fails.
My environment:
Strawberry Perl v5.32.1 built for MSWin32-x86-multi-thread-64int
GD v2.73
I know the file is simple, but that one line is enough to cause the crash.
The file it complains about exists and is located where it is looking.
I have looked and is looks like I need to add -m GD, or -l xxx to make it work. I tried adding all the dll files I could find for GD, but failed.
I have a corporate environment so I can't really use anything that depends on external programs not in Windows 10. pp_simple depends on wxpar which I do not have. I have used:
objdump -x C:\Strawberry\perl\vendor\lib\auto\GD\GD.xs.dll | find "DLL"
which got me a list of DLLs, and I did try using them with -l.
From Re: Par with strawberry-Perl
There are likely missing DLLs that need to be added to the pp call
using the --link option.
Finding these manually can be a pain, so have a look at pp_autolink or
pp_simple (the former is mine, but adapted from the latter).
https://github.com/shawnlaffan/perl-pp-autolink
https://www.perlmonks.org/?node_id=1148802

fish shell functions not accessing user paths

I've recently started using fish, and I needed to use a jar file for google's bundletool.
As such, I needed to set up an alias/function for bundletool, and I chose a function since it seems more "fishy".
My function is simple:
function bundletool
java -jar bundletool-all-1.12.1.jar $argv
end
The bundletool jar itself lives at ~/.local/bin, which is on my fish user path:
lase#laser-razer /m/c/U/matth [1]> echo $fish_user_paths
/home/lase/.local/bin /usr/local/go/bin /home/lase/.nvm /home/lase/.cargo/bin /home/lase/.cargo
In a regular shell, I can execute java -jar bundletool-all-1.12.1.jar, and the command runs as expected. However, in the function, fish doesn't seem to know about my fish_user_paths, and reports it cannot find the jar file.
To remedy this, I had to update my function to specify the full path:
function bundletool
java -jar ~/.local/bin/bundletool-all-1.12.1.jar $argv
end
This works, but I feel like I'm doing something incorrectly. Should I be setting up my paths or functions in a different fashion?
Your function will run in the ordinary environment.
It will run with the current $PATH [0] and, more importantly to you, the current working directory.
What happens is this:
java -jar bundletool-all-1.12.1.jar
Will tell java to run the jar found at bundletool-all-1.12.1.jar.
Notably, fish just hands java the string "bundletool-all-1.12.1.jar", and java will then not look at $PATH. It does not care about $PATH. It simply looks at "bundletool-all-1.12.1.jar", and tries to open a file by that name.
And it will find that file, if it is in the current directory.
And that's the reason this worked for you when you executed it interactively - because you happened to be in that directory
And then you tried it with the function, but you tried it from a different directory, and so it didn't work.
This works, but I feel like I'm doing something incorrectly. Should I be setting up my paths or functions in a different fashion?
No, giving the full path to the file instead of relying on the working directory is the right thing to do.
[0]: $fish_user_paths is just a variable you set, that fish will then take care to add to $PATH. $PATH is the actual variable that fish and other tools (including any command fish starts, if it wants to) will use to find commands.

calling source from within a function

I'm currently moving from zsh to fish. Most of my aliases etc are pretty easy to port, but I'm running into problems with the following one:
alias idf.py='unalias idf.py; source $IDF_PATH/export.sh; idf.py'
I know in fish aliases are just syntactic sugar for functions so I started writing the following function:
function "idf.py"
source $IDF_PATH/export.fish
functions --erase idf.py
idf.py $argv
end
the export.fish script is from the esp-idf and starts complaining about needing to be sourced. After that the function gets removed correctly but idf.py can not be found:
his script should be sourced, not executed:
realpath: /home/robert/Programs/esp-idf/export.fish/..: Not a directory
.
fish: Unknown command: idf.py
fish:
idf.py $argv
^
in function 'idf.py'
Do you have any idea how I can source to the global scope from within this function?
Just going on the commit history of the project you linked to -- The ESP-IDF script you linked is the latest version, but the error you are receiving was from a bug in an earlier version of the script that has since been fixed.
The script attempts to detect whether it is being called with the source command by testing status current-command, but since you are calling it from within the function idf.py, that's the name returned, rather than source.
It was a bug, and it was fixed about two years ago by simply removing the source check.
Upgrading to the latest ESP-IDF release should take care of it.

Can't find application class in #INC when starting Mojolicious-generated app

I generated a mojolicious app with the command mojo generate app first-app. It generated the app structure that should allow a running example when running the dev server with morbo ./script/first-app.
The file structure looks like this:
mojo app structure
My error when running morbo ./script/first-app in the root of the project directory is this error:
Can't load application from file "/home/djnorrisdev/Documents/mojo-practice/first-app/script/first-app":
Can't find application class "first-app" in #INC. (
/home/djnorrisdev/Documents/mojo-practice/first-app/lib
/home/djnorrisdev/perl5/perlbrew/perls/perl-5.30.0/lib/site_perl/5.30.0/x86_64-linux
/home/djnorrisdev/perl5/perlbrew/perls/perl-5.30.0/lib/site_perl/5.30.0
/home/djnorrisdev/perl5/perlbrew/perls/perl-5.30.0/lib/5.30.0/x86_64-linux
/home/djnorrisdev/perl5/perlbrew/perls/perl-5.30.0/lib/5.30.0)
Compilation failed in require at (eval 72) line 1
(Line breaks added for readability. An indented line is a continuation of the previous line.)
I tried using the full path for morbo (as mentioned in a 6 year old SO post), but that gives the same error as above. That command was this: /home/djnorrisdev/perl5/perlbrew/pls/perl-5.30.0/bin/morbo ./script/first-app
I'm guessing anyone familiar with a full mojolicious app would be familiar with the script file, but here's the contents of script/first-app :
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::File 'curfile';
use lib curfile->dirname->sibling('lib')->to_string;
use Mojolicious::Commands;
# Start command line interface for application
Mojolicious::Commands->start_app('first-app');
Considering this is a mojolicious-generated app, I would assume it should not get an #INC error and run with morbo without issue. Does anyone have insight into this?
For your setup to work, first-app.pm would have to contain package first-app;, but that's not legal code because of the dash. Håkon Hægland suggests that mojo generate app first-app should not have worked (presumably to avoid this very problem), so it's unclear how you came to have the setup you describe.
To fix the problem, you could rerun mojo generate app with a more suitable name (such as FirstApp) and start over.
Alternatively, you should theoretically be able to fix the problem with as little as three changes:
Rename lib/first-app.pm to a more conventional name such as lib/FirstApp.pm.
Change the argument passed to ->start_app to 'FirstApp'.
Change the package directive in now-named lib/FirstApp.pm to package FirstApp;.
A module's path, a module's package directive, and the use statement used to load the module —the value passed to ->start_app in this case— must all match. The three changes ensures this for the module in question.
[Note: I have no experience with Mojo.]

How to run a pytest-bdd test?

I am not understanding how to properly run a simple test(feature file and python file)
with the library pytest-bdd.
From the official documentation, I can't understand what command to issue to run a test.
I tried using pytest command, but I saw the NO test ran.
Do I need to use another library behave to run a feature file?
I figured out trying for 2 days,that ,
for running a pytest-bdd test, there are certain requirements, at least in my view.
put both the feature file and python file in the same directory (maybe this can be changed with configuration files)
the python file name needs to start with test_
the python file needs to contain a method of which name will start with test_
the method starting with test_ , need to be assigned to the #scenario sentence
to run the test, issue pytest command in the same directory(maybe it is also configurable)
After issuing you will only see the method with the name starting with test_ has passed, but all the tests actually ran. To test, you can assert False in any #when or #then annotated method, it will throw errors.
The system contained : pytest-bdd==3.0.2 (copied from pip freeze output)
Features files and python files can be placed in different folders using the bdd_features_base_dir hook provided by pytest-bdd; I think it is better having features files in different folders too.
Here you can see a working example (a simple hello world BDD test):
https://github.com/davidemoro/pytest-play-docker/tree/master/tests
https://github.com/davidemoro/pytest-play-docker/blob/master/tests/pytest.ini (see bdd_features_base_dir in [pytest] section)
https://github.com/davidemoro/pytest-play-docker/tree/master/tests/bdd
If you want to try out pytest-bdd without installation you can use Docker. Create a folder with inside your pytest BDD files and if you want a separate features folder targeted in bdd_features_base_dir and run:
docker run --rm -it -v $(pwd):/src davidemoro/pytest-play:latest
I've found out, that in the python file you don't have to put:
the method starting with test_ , need to be assigned to the #scenario sentence
You can just add: scenarios("") - to allow the tests to be started, which are using steps defined in this specific python file.
Remember to import scenarios!: from pytest_bdd import scenarios
Example:
Code example
Command..
pytest -v path_to_test_file.py
Things to note here..
Check format of feature file as filename.feature
Always __init__ modules, otherwise test-runner will not find test files
Glue right step definitions to test function
Add feature in features module
If you are using python3 execute test with python3
So,
python3 -m pytest -v path_to_test_file.py
Documentation
https://pytest-bdd.readthedocs.io/en/stable/#