I am developing a web app that relies on NodeJS and the Express module in which I am trying to run a Python script from an express route. What I would like to do is store the Python script in /public/scripts/test.py and refer to it using a relative URL such as /scripts/test.py so that Node doesn't need to know anything about the environment in which it is running.
I've attempted to execute the Python script both by using the python-shell module and by simply using Node's built-in ChildProcess. In both cases I'm running into the same issue – the path to the Python script seems to treated as being absolute and thus the script isn't executed, resulting in a file not found error.
How can I go about invoking a Python script with a relative URL? I'm rather new to web development, so I would not be surprised if I was simply misunderstanding the situation.
EDIT:
As jfreind00 pointed out, process.cwd() can be used to identify the present working directory on top of which a URL to the script can be built. Worked like a charm.
Turning my comments into an answer so you can mark this question as resolved.
Invoking a program from node follows all the normally expected path rules. If you precede the path with a /, then the system looks in the root of the current directory volume. If you don't want node to know about your external directory structure, then set an environment variable for the location or path prefix for your python script and have the node script read that environment variable. Either way, node has to either know about the actual path, it has to be in the node current working directory or it has to be in the path and you have to run it with something that will search the path.
If you want to see what the current working directory is in your particular configuration, then you can use:
console.log(process.cwd());
to see what the current working directory is so you can see how to base your path on that.
Related
How do I get the full path of the current file's directory?
Yes, I already tried these methods. They all give me the folder that contains Blender.exe
which is D:\program\Blender 2.90
And what I supposed to get is C:\Users\username\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons\someAddonFolder right?
Is something changed in version 2.9?
Without the Blender environment, I mean run under normal Python. Methods from that topic all work well.
Did I miss something?
The old way I made the script work is by putting .blend .json .py all together in the same folder.
and refer to the relative path using //
bpy.utils.user_resource('SCRIPTS', "addons")
use this code can get you the path your custom addon you install at.
for me, it's 'C:\Users\Naoki\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons'
found the answer over here:
https://blender.stackexchange.com/questions/20850/how-to-automatically-get-a-add-on-folders-path-regardless-of-os
I have a Python script which imports the datetime module. It works well until someday I can run it in a directory which has a Python script named datetime.py. Of course, there are a few ways to resolve the issue. First, I run the script in a directory that does not contain the script datetime.py. Second, I can rename the Python script datetime.py. However, neither of the 2 approaches are perfect ways. Suppose one ship a Python script, he never knows where users will run the Python script. Another possible fix is to prevent Python from search the current working directory for modules. I tried to remove the empty path ('') from sys.path but it works in an interactive Python shell but not in a Python script. The invoked Python script still searches the current path for modules. I wonder whether there is any way to disable Python from searching the current path for modules?
if __name__ == '__main__':
if '' in sys.path:
sys.path.remove('')
...
Notice that it deosn't work even if I put the following code to the beginning of the script.
import sys
if '' in sys.path:
sys.path.remove('')
Below are some related questions on StackOverflow.
Removing path from Python search module path
pandas ImportError C extension when io.py in same directory
initialization of multiarray raised unreported exception python
Are you sure that Python is searching for that module in the current directory, and not on the script directory? I don't think Python adds the current directory to the sys.path, except in one case. Doing so could even be a security risk (akin to having . on the UNIX PATH).
According to the documentation:
As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first
So, '' as a representation of the current directory happens only if run from interpreter (that's why your interactive shell test worked) or if the script is read from the standard input (something like cat modquest/qwerty.py | python). Neither is a rather 'normal' way of running Python scripts, generally.
I'm guessing that your datetime.py stands side by side with your actual script (on the script directory), and that it just happens that you're running the script from that directory (that is script directory == current directory).
If that's the actual scenario, and your script is standalone (meaning just one file, no local imports), you could do this:
sys.path.remove(os.path.abspath(os.path.dirname(sys.argv[0])))
But keep in mind that this will bite you in the future, once the script gets bigger and you split it into multiple files, only to spend several hours trying to figure out why it is not importing the local files...
Another option is to use -I, but that may be overkill:
-I
Run Python in isolated mode. This also implies -E and -s. In isolated mode sys.path contains neither the script’s directory nor the user’s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting malicious code.
I have a script called "test.py" and refers to a config file called "cfg.yaml". These two reside in the same directory called "test/scripts".
test/scripts/test.py
test/script/cfg.yaml
Now I am writing a bash script inside "test/data1/data2" called task.sh
From inside of task.sh, I want to make a call to the python script
test.sh contents are as below:
#!/bin/sh
python ../../scripts/test.py
test.py opens and reads the cfg.yaml like open("cfg.yaml") but when the test.sh is called, it fails because "cfg.yaml" is NOT referred with relative path. How do I resolve this?
try
#!/bin/sh
cd ../../scripts
python test.py
I assume in test.py you are referencing the yaml with a local path that expects the script to be running from the scripts directory (not from data1/data2)
as an aside you can always print os.getcwd() to see what your working directory is while running the python script (or just pwd in bash)
If you want to refer to a file in terms of its relative location to the script, you can't just use a relative path for that, because the script may not be in the current working directory. In fact, in your case, it's guaranteed not to be in the current working directory.
The usual quick&dirty solution is to get the script path explicitly:
import os
import sys
scriptdir = os.path.abspath(os.path.dirname(sys.argv[0]))
That sys.argv[0] is the full name of your script—which on most platforms means either an absolute path, or a relative path that's at least still valid at this point. If you're worried about those other platforms, you may want to look at __file__. Of course if you're running the script out of a zipfile or similar, neither one will be useful.
open(os.path.join(scriptdir, "cfg.yaml"))
(Or you can even forcibly os.chdir(scriptdir) if you want, but that can be a bad idea if you're, e.g., accepting pathnames from the user.)
The right solution is to write your script and data files to be installed (even if you don't actually install anything and run it out of the source tree), and then use pkg_resources to find the data files. That will also solve a whole lot of other problems for you—but it does require a bit more learning first. See the Python Packaging User Guide if you want to get started on that road, and Package Data and Data Files as particular starting points.
I realise this question may already exist, but the answers I've found haven't worked and I have a slightly different setup.
I have a python file /home/pi/python_games/frontend.py that I am trying to start when lxde loads by placing #python /home/pi/python_games/frontend.py in /etc/xdg/lxsession/LXDE/autostart.
It doesn't run and there are no error messages.
When trying to run python /home/pi/python_games/frontend.py, python complains about not being able to find the files that are loaded using relative links eg: /home/pi/python_games/image.png is called with image.png. Obviously one solution would be to give these resources absolute paths, but the python program also calls other python programs in its directory that also have relative paths, and I don't want to go changing all them.
Anyone got any ideas?
Thanks
Tom
you could change your current working directory inside the script before you start calling your relative imports, use os.chdir("absolute path on where your script lives").
Rather than change your current working directory, in yourfrontend.pyscript you could use the value of the predefined__file__module attribute, which will be the absolute pathname of the script file, to determine absolute paths to the other files in the same directory.
Functions in theos.pathmodule, such assplit()andjoin(), will make doing this fairly easy.
I am experiencing an odd problem that I'm not quite sure how to tackle. I have a Python-selenium script that uses relative paths to log results to a text-file.
Here is the part of the script which sets up the log-file:
log_file = './demo-logfiles/log_file_template.txt'
sys.stdout = open('log_file_template.txt', 'a',)
As you can see, it uses a relative path to a folder. If I run this script as:
python demo.py firefox MAC, it runs flawlessly and the logfile gets sent to the proper folder.
If I run this exact Python script from within a larger shell-script, it returns an error that the './demo-logfiles/log_file_template.txt' doesn't exist.
I have found that if I change the script to '../demo-logfiles/log_file_template.txt' it works in the larger shell script, but stops working if I run it normally.
It either works in one, or the other. What is the reason for the relative directories being interpreted in different ways? I would not like to have two separate scripts for running in Python/shell.
The original python script is in the directory /blah/blah/DEMO/demo.py, and the the shell script that runs it is in /blah/blah/DEMO/demo-autotest/autotest_logger.sh
I have confirmed that this problem occurs for any script I try to run. I shouldn't have to change the original Python code to make it work with the shell script. I already accounted for it in the shell script, and it successfully runs the file.
Thanks.
You should never use a "." (or any relative path) in a directory path in a script unless you really mean you want to refer to the directory that the user is running the script from. If you want to refer to a location relative to the script that's running, you can do the following:
import os
import sys
directory = os.path.dirname(os.path.abspath(__file__))
sys.stdout = open(os.path.join(directory, "demo-logfiles", "log_file_template.txt"), "a")
Best practices side note: you should probably use the logging module rather than reassigning sys.stdout.
The term "relative directories" means a path is relative to something. You probably assume it's relative to the script which contains the path but that's not correct.
Relative paths are relative to the current directory of the process which interprets the script, i.e. the folder in which you started python. If you're in the shell, you can see the current directory with echo $PWD
If you start python in /blah/blah, then that becomes the current directory and all relative paths are relative to /blah/blah.
See the answer of David Hollman for how to get the path of the current script and then how to build paths relative to that.