I have troubles launching a simple HelloWorld program via Pexpect module.
I have a directory with the HelloWorld binary - hw, expect script - m.py, and a directory with the same script inside.
├── hw
├── m.py
├── main.cpp
└── dir
└── m.py
Here is my expect script:
import pexpect
child = pexpect.spawn("./hw", cwd = /absolute/path/to/parent/directory")
child.expect("!")
print(child.before)
If i run the script from the parent directory, everything works great. However, If I run it from any other directory, like dir here, I get the following error:
pexpect.ExceptionPexpect: The command was not found or was not executable: ./hw.
How do I fight this?
I have tried this on Mac OS and Ubuntu. HelloWorld binary works fine, it is set as executable. Python 2.7.6, pexpect 3.3
To run an executable hw, either its parent directory should be in PATH envvar or you should provide the full path. If the path is relative (not recommended) then it is a path relative to your current working directory regardless of cwd value.
If you want to run hw from its directory:
import os
import pexpect # $ pip install pexpect
hw = '/absolute/path/to/parent/directory/hw'
child = pexpect.spawn(hw, cwd=os.path.dirname(hw))
# ...
#jfs answer is pretty clear, just want to add some more,
If you got an executable script (script.sh) in the directory /path/to/parent/dir
child = pexpect.spawn("./script.sh", cwd="/path/to/parent/dir") # wont work
As with ./ it is trying to execute from the scripts current working directory, if you somehow need that to work then you can add os.chdir(), so
os.chdir("/path/to/parent/dir")
child = pexpect.spawn("./script.sh") # works
If you don't need to change the script path all to run the child process, can spawn the pexpect process with,
child = pexpect.spawn("/path/to/parent/dir/script.sh") # wont works for my script
This won't works if there is relative paths mentioned the script.sh, cz the cwd(current working directory) is the python script's cwd. In my case script.sh needs resources from the directory it exists,
So in order to execute it,
child = pexpect.spawn("/path/to/parent/dir/script.sh", cwd="/path/to/parent/dir") # works
if you don't got the hard coded parent path of script.sh, use os.path.dirname("<absolute path to script.sh>") as mentioned in the previous answer
Related
I'm trying to write universal scripts that would work on any PC that meets requirements and I have a little problem with getting directories and paths right. Currently I have two folders in one location: C:\Users\myProject, one with my Scripts and other named Tests. In Scripts folder I store my python scripts with all instructions and in Tests I have .bat files used to execute scripts. To get parents path I decided to use (__file__), for example in my script - Test_Script.py:
__file__ = 'Test_Script.py'
print(r'__file__', __file__)
curr_path = os.path.dirname(os.path.abspath(__file__))
print (curr_path)
And it works, but in two ways. If I run cmd in folder with Scripts and type: py Test_Script.py, I get:
Test_Script.py
C:\Users\myProject\Scripts
But when I run it from Tests directory, I get:
Test_Script.py
C:\Windows\system32
How do I fix this to have same output as in first case while running script via cmd?
I am struggling with running python script in shell. I use PyCharm where is everything ok, but I want to run script without running PyCharm.
So my project folder is like:
data/
file.txt
main/
__init__.py
script.py
tools/
__init__.py
my_strings.py
I want to run main/script.py, which start with from tools import my_strings and working directory should be data/.
My PyCharm config is:
Script path: <PROJECT>/main/script.py
Working directory: <PROJECT>/data
Add content roots to PYTHONPATH: YES
Add source roots to PYTHONPATH: YES
So I want to run main/script.py in shell on Ubuntu. I tried:
PYTHONPATH=<PROJECT>
cd <PROJECT>/data
python3 ../main/script.py
But I just got: ImportError: No module named 'tools'
Check out this post, it's explains the PYTHONPATH variable.
How to use PYTHONPATH and the documentation the answer points to https://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH
When you run from the data directory by default python can't find your tools directory.
Also regarding your comment about needing to run from the data directory, you could just use open('../data/file.txt') if you decided to run from the main directory instead.
Ideally, you should be able to run your script from anywhere though. I find this snippet very useful os.path.dirname(sys.argv[0]). It returns the directory in which the script exists.
I simply forgot to export $PYTHONPATH as suggested by Steve.
I am facing a small problem in executing custom made python code from Hiero. As everybody knows, the first place to look for details is the offical documentation "Nukepedia", the Python Dev Guide and the Hiero User Guide. Well according to the Python Dev Guide, Hiero creates a ".hiero" directory by default which lets people add plugin paths to use them in the software. Well, I can't find that directory and I deduced after several tests that Hiero is using the init.py saved in the ".nuke" directory.
So I thought that maybe I could add the plugin paths there but kept getting the famous Import Error for the _fnpython module (before creating Python/Startup directory).
I added Python/Startup folders in .nuke and added the plugins in Startup, I got the same error, I even tried it by adding the path to the plugins in init.py and got the same error too.
Then I created a ".hiero" folder and did the same thing as before but Hiero never took that folder into consideration, I deduced that by printing some strings in the console, Hiero always took the init.py saved in the ".nuke" folder and kept showing the same error.
Finally, I tried to look into the installation process and try to seperate Nuke and Hiero's folders maybe that would create the ".hiero" directory but everything was automated.
The code that I want to run is given by Nuke and Hiero (in the examples directory), I just can't figure out what to do in order to run it from the program.
What should I do in order to fix this problem ?
Thank you in advance.
The setup for The Foundry HIERO is a little different than for NUKE.
HIERO has a core module. You'll see it in __init__.py file:
import FnRedirect
import FnPythonFixes
import core
import ui
try:
if hasattr(core, "taskRegistry"):
import importers
import exporters
except ImportError as e:
pass
I'm running HIERO and NUKE STUDIO on a Mac, so there's a full path to HIERO's __init__.py file inside package contents:
/Applications/Nuke10.5v5/Contents/MacOs/pythonextensions/site-packages/hiero/__init__.py
You need to import this module using:
import hiero.core
or using a reference to the core package:
from core import *
To find HIERO's current paths you have to run this line in its Script Editor:
print hiero.core.pluginPath()
Click this link for further details: Hiero's Environment Setup
All these instructions are suitable for macOS 10.9 and above. Here are two blocks of steps: first for Terminal Mode and second for UI Mode.
BLOCK 1: setup for Terminal Sessions
You need to manually create .hiero directory in your Home area.
The recommended default location for running Python on startup is:
~/.hiero/Python/Startup
~/.hiero/Python/StartupUI
Type in your bash Terminal (when you're inside your Home user directory) the following line:
mkdir .hiero/
then:
mkdir .hiero/Python/
and then:
mkdir .hiero/Python/StartupUI/
then navigate to Home directory with:
cd ~
and check it with:
ls -a
Also you can specify any number of user-defined paths using the environment variable HIERO_PLUGIN_PATH, just like the standard Unix PATH environment variable.
For that you need to set up an environment variable in .bash_profile. To run in Terminal PICO editor just type (remember you need an administrator's password for sudo command):
sudo pico .bash_profile
and paste these three lines in it (change swift for <yourName> and save this file):
echo HIERO environment var is set...
export HIERO_PLUGIN_PATH=/Users/swift/.hiero/Python/StartupUI/
export PATH=$PATH:$HIERO_PLUGIN_PATH
Write out a file with ctrl o
Exit pico editor with ctrl x
Restart Terminal
In Terminal you could print this environment variable typing:
printenv HIERO_PLUGIN_PATH
You should put inside that StartupUI directory menu.py, any set of xxxx.py or xxxx.pyc files, as well as __init__.py file.
Now you can use /Users/swift/.hiero/Python/StartupUI/ path in Terminal Mode.
BLOCK 2: setup for UI Sessions
To assign the current paths that HIERO searches when loading plug-ins, you need to create __init__.py file with the following lines:
import hiero.core
path='/Users/swift/.hiero/Python/Startup/'
hiero.core.addPluginPath(path)
After that make Python/Startup/ subdirectories under ~/.nuke/ folder.
It's not a mistake: I typed .nuke.
Then place this __init__.py file into /Users/swift/.nuke/Python/Startup/ directory.
Restart HIERO (or NUKE STUDIO) if it works.
After that launch HIERO or NUKE STUDIO and run
print hiero.core.pluginPath()
command in the HIERO's Script Editor or in NUKE STUDIO's Script Editor and you'll see this result:
After that you'll find new __init__.pyc file in /Users/swift/.nuke/Python/Startup/ directory.
Each package or module discovered when you launch HIERO is imported and added to the built-in package hiero.plugins.
TEST 1: custom_guides.py
I do not have a commercial version of HIERO so I tested custom_guides.py script ( found here ) using NUKE STUDIO NC.
I placed custom_guides.py in ~/.nuke/Python/Startup directory and then added two lines to NUKE's init.py file located in ~/.nuke directory.
import nuke
nuke.pluginAddPath("./Python/Startup")
The only thing I could say: "it works" Do the same actions as I did and it'll work for HIERO.
Look at safe_zone and masking_ratio dropdown menus. They are different: before and after.
Before uploading custom_guides.py script:
After uploading custom_guides.py script:
# file custom_guides.py contains these lines:
viewer_masks = [
hiero.ui.guides.MaskGuide("NTSC", 0.91),
hiero.ui.guides.MaskGuide("PAL", 1.09),
hiero.ui.guides.MaskGuide("NTSC_16:9", 1.21),
hiero.ui.guides.MaskGuide("PAL_16:9", 1.46),
hiero.ui.guides.MaskGuide("Cinemascope 2:1", 2.0)
]
TEST 2: web_browser.py
I placed web_browser.py file in ~/.nuke/Python/Startup directory. This Python script creates dockable panel with web browser written with PySide Qt.
I do not have a commercial version of HIERO so I tested web_browser.py script ( found here ) using NUKE STUDIO NC.
A script at /foo/bar.py tries to run a second script /main.py using the subprocess module. Although main.py runs fine with python main.py in the Windows command prompt, running bar.py which calls main.py causes an error
ConfigParser.NoSectionError: No section: 'user'
Why is there now a problem with the path to settings.ini, and how can we fix it?
~/settings.ini
[user]
id: helloworld
~/foo/bar.py
subprocess.Popen([sys.executable, "../main.py"])
~/main.py
Config = ConfigParser.ConfigParser()
Config.read("settings.ini")
userId = Config.get('user', 'id')
If settings.ini is presumed to be in the same directory as main.py you can deduce its full path from __file__ and read the settings using the full path.
main.py:
import os
ini_path = os.path.join(os.path.dirname(__file__), "settings.ini")
Config = ConfigParser.ConfigParser()
Config.read(ini_path)
Check that the read() method returns a non-empty list otherwise it means that settings.ini is not found. Relative paths are resolved relative to the current working directory (place where you've run python), not script's directory (where bar.py is stored).
You should probably use appdirs.user_config_dir(), to get the directory where to put user's configuration files. Different OSes such as Windows, macOS, Linux distributions may use different defaults. appdirs follows conventions that are appropriate for a given OS.
If you want to get data stored in a file that is packaged with your installed Python modules then you could use pkgutil.get_data() or setuptools' pkg_resources.resource_string() that work even if your package is inside an archive. It is not recommended to construct the paths manually but if you need the directory with the current script then you could put get_script_dir() function into your script—it is more general than os.path.dirname(os.path.abspath(__file__)). If the relative position is always the same then you could use:
#!/usr/bin/env python
import os
import subprocess
import sys
main_script_dir = os.path.join(get_script_dir(), os.pardir)
subprocess.check_call([sys.executable, '-m', 'main'], cwd=main_script_dir)
See Python : How to access file from different directory
I am trying to create a github repository that can be run from any clone without hardcoding directory dependencies.
Let us say in my repo I have a python script called myscript.py and its located at:
/d/e/f/github/myrepo/myscript/myscript.py
But I know that my script depends on general utility tools always located at:
/d/e/f/github/myrepo/myutils/myutils.py
Thus, how can I tell my script to always load myutils.py, where the relative path to myutils.py with respect to myscript.py is always ../myutils/myutils.py
As of now myscript.py looks like:
# Import modules
import sys
sys.path.append('/d/e/f/github/myrepo/myutils/')
import myutils
As one can see now the fullpath to myutils.py is hardcoded, so if anyone else clones their repo in their own computer it won't work.
Ideally, users should be able to run myscript.py as follows:
cd /d/e/f/github/myrepo/myscript/
python myscript.py -h
Or,
python /d/e/f/github/myrepo/myscript/myscript.py -h
And it should work without having to hardcode the full path to the myutils module, but rather just the relative path...
By doing some research seems this could be a possible answer:
# Import modules
import subprocess, sys, os
script_path = os.path.dirname(__file__)
myutils_path = os.path.join(script_path, '../myutils')
sys.path.append(myutils_path)
import myutils