Python module not found in Nix-generated Python environment - python

I need my user environment configured with Python and the beancount module available. The way I'm currently doing this is to add this package to home.packages (I am using home-manager):
(python310.withPackages (_: [ python310Packages.beancount ]))
This gives me Python 3.10, but upon trying import beancount, I get a ModuleNotFoundError.
The reason I'm invoking withPackages in this way, and not with (python-packages: with python-packages; [ beancount ]) is because I am overriding the beancount module. I am on an Apple Silicon system and am having issues building beancount on aarch64-darwin, so I simply use the x86_64-darwin version, which works fine. This is done with the following two overlays:
(final: prev: (optionalAttrs (prev.stdenv.system == "aarch64-darwin") {
pkgs-x86 = import nixpkgs-unstable {
system = "x86_64-darwin";
inherit (nixpkgsConfig) config;
};
}))
(final: prev: (optionalAttrs (prev.stdenv.system == "aarch64-darwin") {
python310Packages.beancount = final.pkgs-x86.python310Packages.beancount;
}))
My suspicion is that the way I'm invoking withPackages is the reason the package is not added to Python's environment, but I'm not sure if this is the case. Either way, how would I go about fixing the issue?
I read somewhere that withPackages fetches packages from PyPi. Is there a way to force x86_64-darwin to be used here? Alternatively, is there a way to manually add modules to Nix's Python environment?

Please take a look at https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#overriding-python-packages-overriding-python-packages on how to overwrite python packages.
Example overlay from my that I used a while back:
final: prev: {
python3 = prev.python3.override {
packageOverrides = final: prev: {
python-swiftclient = prev.python-swiftclient.overrideAttrs (oldAttrs: rec {
postInstall = ''
install -Dm644 tools/swift.bash_completion $out/share/bash_completion.d/swift
'';
});
};
};
}

Related

Environment variable not visible in Python application started from pm2

I'm using a server for the first time. It has Ubuntu 18.04.
I've never worked with that OS, but after some guides I managed to get my code working, except for the environment variable.
In ~/.bashrc at the end of file I added export KEY="123asd".
Then I reloaded the terminal.
I checked if my environment variable is loaded via printenv KEY and it shows the correct value.
In my main.py there's:
import os
import telebot
API_KEY = os.getenv("KEY")
bot = telebot.TeleBot(API_KEY)
When I run it with pm2 start main.py --interpreter=python3 there's an error in logs:
raise Exception('Bot token is not defined')
Exception: Bot token is not defined
If I understand correctly it means that API_KEY is None so there's a problem with the environment variable.
I tried giving API_KEY an actual value, not an environment variable, and it worked fine.
So what else do I need to do to use an environment variable properly?
I was looking in the wrong place.
If I want to use pm2 then I need to create a ecosystem.config.js file and give it my variable. Like this:
module.exports = {
apps : [{
name: "main.py",
env: {
KEY: "123asd"
}
}]
}
It works, only I'm not sure if it's correct since there are more than 1 processes of my main.py (1 online, others are erorred)

Run Python with imports via java ScriptEngineManager

Similar question have been asked here an year ago but no answer yet.
Im running a Python script via Java and I'm getting
ImportError: No module named numpy in <script> at line number 1
This is my code:
public void runScript(String filePath) throws Exception {
StringWriter writer = new StringWriter();
ScriptContext context = new SimpleScriptContext();
context.setWriter(writer);
Options.importSite = false;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");
engine.eval(new FileReader(filePath), context);
System.out.println(writer);
}
How do I run script with it's imports?
Of course all the required installations have been installed (with pip install) and that the code runs perfectly when I run it not through java.

How to bundle python code with vsix (vscode extension)

I am creating a vscode extension where I need machine learning tasks to be performed. I have python files that have code that is required in vscode extension. I don't want things to be done using request-response on any python server. What I want is to perform the ML tasks on device (integrated with the vsix).
We have child-process available in js to run basic python file using spawn. It is running fine on both, extension host window and external vscode editor after packaging, with the python code that has basic imports like import sys. But if I try to import some other libraries like numpy, pygments, it is working only on extension host environment, not on other vs window after packaging it. How can I run the typical python code with the vsix?
Below are both the codes that is working fine and not working at all-
TS file (MLOps.ts)-
import { ChildProcessWithoutNullStreams, spawn } from "child_process";
import { join } from "path";
import * as vscode from 'vscode'
export async function pythonOps(): Promise<string> {
var result = "testt"
var promise = await new Promise((resolve, reject) => {
var p = __dirname.split('\\')
p.pop()
var path = p.join('\\')
var pyPath = join(path, 'src', 'py_operations.py')
var result = "blank result"
var arg1 = "arg one"
var arg2 = "arg two"
var py_process = spawn('python', [pyPath, arg1, arg2])
py_process.stdout.on('data', (data: any) => {
vscode.window.showInformationMessage(data.toString())
result = data.toString()
})
})
}
Working Python code (py_operations.py)- This code is working on both, on extension host window and after packaging the extension and installing the vsix on other system.
import sys
print("Some text with: ",sys.argv[0], sys.argv[1], sys.argv[2])
sys.stdout.flush()
Not working Python code- This code is working only on extension host window, and not working after packaging this and isntalling on other system.
import sys
from pygments.lexers.javascript import TypeScriptLexer
lexer = TypeScriptLexer()
src = "alert('text here')"
lexer_tokens = lexer.get_tokens(src)
l = []
for t in lexer_tokens:
l.append(t[1])
print("list: ",l)
sys.stdout.flush()
How can I run the second python code with packaged vsix?

scons uninstall runs Substfile

I have created the SConstruct to install the systemd user services but when I try to scons uninstall the temporary services files are creates which should not happen.
import os
PATH_WD = os.path.abspath(os.curdir)
env = Environment(
SUBSTFILESUFFIX = '.service',
SUBST_DICT = { '{{PATH_ROOT}}' : os.path.dirname(PATH_WD) },
ENV = {
'DBUS_SESSION_BUS_ADDRESS' : os.environ['DBUS_SESSION_BUS_ADDRESS'],
'XDG_RUNTIME_DIR' : os.environ['XDG_RUNTIME_DIR']
}
)
INSTALLED = env.Install(
target = os.path.expanduser('~/.config/systemd/user/'),
source = [
env.Substfile('service1'),
env.Substfile('service2'),
]
)
env.AddPostAction(INSTALLED, env.Action('systemctl --user daemon-reload'))
Alias('install', INSTALLED)
NoClean(INSTALLED)
Command('uninstall', INSTALLED, Delete(INSTALLED))
Default('install')
Second try..
Here's a trivial example which should work for you..
env=Environment()
prog=env.Program('main.c')
Default(prog)
installed_prog = env.Install('install_dir', prog)
Alias('install', installed_prog)
NoClean(installed_prog)
# You don't have to specify targets to Alias.. so it won't
# try to build those before executing the Action
Alias('uninstall', action=Delete(installed_prog))
AlwaysBuild('uninstall')
SCons builder calls are statements of relationships between nodes. You've associated the target "uninstall" with the source INSTALLED by calling the Command builder. So in order to "build" this target, you need the source, and the source is the list of nodes returned by calling the Install builder. So the Install has to happen before the uninstall can take place. Is there a reason you don't want SCons' clean functionality to be used here? To see this, try: scons --tree=all,linedraw -n uninstall

ImportError: Cannot import site module and its dependencies: No module named site

I am trying to run jython servlets on Windows. I can’t run even the most simple HelloWorld.py. I get the following 500 error:
message Servlet.init() for servlet [PyServlet] threw exception
...
description Le serveur a rencontré une erreur interne qui l''a empêché de satisfaire la requête.
exception
javax.servlet.ServletException: Servlet.init() for servlet [PyServlet] threw exception
...
cause mère
ImportError: Cannot import site module and its dependencies: No module named site
Determine if the following attributes are correct:
* sys.path: ['C:\\apache-tomcat-8.5.24\\webapps\\jython\\WEB-INF\\lib\\Lib', '__classpath__', '__pyclasspath__/']
This attribute might be including the wrong directories, such as from CPython
* sys.prefix: C:\apache-tomcat-8.5.24\webapps\jython\WEB-INF\lib
This attribute is set by the system property python.home, although it can
be often automatically determined by the location of the Jython jar file
You can use the -S option or python.import.site=false to not import the site module
org.python.core.Py.ImportError(Py.java:328)
org.python.core.Py.importSiteIfSelected(Py.java:1563)
org.python.util.PythonInterpreter.<init>(PythonInterpreter.java:116)
...
Jython is deployed under C:\jython2.7.0
My very basic webapp is under C:\apache-tomcat-8.5.24\webapps\jython
jython.jar (not the standalone jar) is copied asC:\apache-tomcat-8.5.24\webapps\jython\WEB-INF\lib\jython.jar
My web.xmlis taken from http://www.jython.org/javadoc/org/python/util/PyServlet.html:
<!-- C:\apache-tomcat-8.5.24\webapps\jython\WEB-INF\web.xml -->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="3.1">
<servlet>
<servlet-name>PyServlet</servlet-name>
<servlet-class>org.python.util.PyServlet</servlet-class>
<init-param>
<param-name>python.home</param-name>
<param-value>C:\\jython2.7.0</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>PyServlet</servlet-name>
<url-pattern>*.py</url-pattern>
</servlet-mapping>
</web-app>
The error message says it, the wrong directory is included in sys.path. python.home is not taken from my initialization parameter (why so?), it is guessed from the location of jython.jar.
PyServlet initialization
I had a look at the initialization code for PyServlet:
#Override
public void init() {
Properties props = new Properties();
// Config parameters
Enumeration<?> e = getInitParameterNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
props.put(name, getInitParameter(name));
}
// ...
init(props, getServletContext());
}
reset();
}
/**
* PyServlet's initialization can be performed as a ServletContextListener or as a regular
* servlet, and this is the shared init code. If both initializations are used in a single
* context, the system state initialization code only runs once.
*/
protected static void init(Properties props, ServletContext context) {
String rootPath = getRootPath(context);
context.setAttribute(INIT_ATTR, true);
Properties baseProps = PySystemState.getBaseProperties();
// Context parameters
Enumeration<?> e = context.getInitParameterNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
props.put(name, context.getInitParameter(name));
}
if (props.getProperty("python.home") == null
&& baseProps.getProperty("python.home") == null) {
props.put("python.home", rootPath + "WEB-INF" + File.separator + "lib");
}
PySystemState.initialize(baseProps, props, new String[0]);
// ...
PySystemState.add_classdir(rootPath + "WEB-INF" + File.separator + "classes");
PySystemState.add_extdir(rootPath + "WEB-INF" + File.separator + "lib", true);
}
I would expect the python.home initialization parameter to be added as a property and that property to be used to construct the sys.path as shown in the JavaDoc!
What am I missing?
Using jython-standalone.jar works for me.
In Maven:https://mvnrepository.com/artifact/org.python/jython-standalone
pom.xml:
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.1</version>
</dependency>
Looks like the python path is referring to a default location. So you have two options to fix this. First is to copy the Jython library inside "C:\apache-tomcat-8.5.24\webapps\jython\WEB-INF\lib\Lib". In order to copy the jython library you need to unzip the contents of jython standalone jar in to this folder.
The other option is to set the python path to point to the location where the jython standalone jar is unzipped. The code looks something like this:
PythonInterpreter interpreter = null;
try{
Properties p = new Properties();
p.setProperty("python.path", "PATH OF JYTHON");
p.setProperty("python.home", "PATH OF JYTHON");
p.setProperty("python.prefix", "PATH OF JYTHON");
PythonInterpreter.initialize(System.getProperties(), p, new String[] {});
interpreter = new PythonInterpreter();
}catch(Exception ex){
log.error("Exception while creating python interpreter: "+ex.toString());
}
I came across this error and the above solution did not work for me.
We need to add jython-standalone.jar to python home not the extracted Lib folder.
p.setProperty("python.path", "PATH TO jython-standalone-2.7.0.jar");
Or
JAVA_OPTS="$JAVA_OPTS -Dpython.home=/PATH TO /jython-standalone-2.7.0.jar"
Hope this helps someone.
As someone suggested. I used jython-standalone and works well.
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.2</version>
</dependency>
#Test
public void givenPythonScript_whenPythonProcessInvoked_thenSuccess() throws Exception {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile(".\\src\\test\\resources\\hello.py");
}

Categories