Python analog of Unix 'which' - python

In *nix systems one can use which to find out the full path to a command. For example:
$ which python
/usr/bin/python
or whereis to show all possible locations for a given command
$ whereis python
python: /bin/python.exe /bin/python2.5-config /usr/bin/python.exe /usr/bin/python2.5-config /lib/python2.4 /lib/python2.5 /usr/lib/python2.4 /usr/lib/python2.5 /usr/include/python2.4 /usr/include/python2.5 /usr/share/man/man1/python.1
Is there an easy way to find out the location of a module in the PYTHONPATH. Something like:
>>> which (sys)
'c:\\Python25\Lib\site-packages'

If you do:
modulename.__file__
You will get a full path return of that exact module. For example, importing django:
>>>> import django
>>> django.__file__
'/home/bartek/.virtualenvs/safetyville/lib/python2.6/site-packages/django/__init__.pyc'
Edit: I recommend seeing the comments below for some good insight if you haven't had a chance to.

This is a bit kludgy but you can type python pywhich os django PIL:
import os, os.path
import sys
def pywhich(mod):
for p in sys.path:
try:
if any(p.startswith(mod + '.py') for p in os.listdir(p)):
return os.path.join(p, mod)
except OSError:
pass
return "Not found"
if __name__ == '__main__':
for arg in sys.argv[1:]:
print arg, pywhich(arg)

Related

Check if python script running from another python script linux

I have actualy python script running on background, you can see how it's displayed when i use command "ps -aux" :
root 405 0.0 2.6 34052 25328 ? S 09:52 0:04 python3 -u /opt/flask_server/downlink_server/downlink_manager.py
i want to check if this script are running from another python script, so i try to us psutil module, but it just detect that python3 are running but not my script precisely !
there is my python script :
import os
import psutil
import time
import logging
import sys
for process in psutil.process_iter():
if process.cmdline() == ['python3', '/opt/flask_server/downlink_server/downlink_manager.py']:
print('Process found: exiting.')
It's look like simple, but trust me, i already try other function proposed on another topic, like this :
def find_procs_by_name(name):
"Return a list of processes matching 'name'."
ls = []
for p in psutil.process_iter(attrs=["name", "exe", "cmdline"]):
if name == p.info['name'] or \
p.info['exe'] and os.path.basename(p.info['exe']) == name or \
p.info['cmdline'] and p.info['cmdline'][0] == name:
ls.append(p)
return ls
ls = find_procs_by_name("downlink_manager.py")
But this function didn't fin my script, it's work, when i search python3 but not the name of the script.
Of course i try to put all the path of the script but nothing, can you please hepl me ?
I resolve the issue with this modification :
import psutil
proc_iter = psutil.process_iter(attrs=["pid", "name", "cmdline"])
process = any("/opt/flask_server/downlink_server/downlink_manager.py" in p.info["cmdline"] for p in proc_iter)
print(process)

Python3: command not found, when running from cli

I am trying to run my python module as a command, however I am always getting the error: command not found.
#!/usr/bin/env python
import sys
import re
from sys import stdin
from sys import stdout
class Grepper(object):
def __init__(self, pattern):
self.pattern = pattern
def pgreper(self):
y = (str(self.pattern))
for line in sys.stdin:
regex = re.compile(y)
x = re.search(regex, line)
if x:
sys.stdout.write(line)
if __name__ == "__main__":
print("hello")
pattern = str(sys.argv[1])
Grepper(pattern).pgreper()
else:
print("nope")
I am sure whether it has something to do with the line:
if __name__ == "__main__":
However I just can't figure it out, this is a new area for me, and it's a bit stressful.
Your script name should have a .py extension, so it should be named something like pgreper.py.
To run it, you need to do either python pgreper.py pattern_string or if it has executable permission, as explained by Gabriel, you can do ./pgreper.py pattern_string. Note that you must give the script path (unless the current directory is in your command PATH); pgreper.py pattern_string will cause bash to print the "command not found" error message.
You can't pass the pattern data to it by piping, IOW, cat input.txt | ./pgreper.py "pattern_string" won't work: the pattern has to be passed as an argument on the command line. I guess you could do ./pgreper.py "$(cat input.txt)" but it'd be better to modify the script to read from stdin if you need that functionality.
Sorry, I didn't read the body of your script properly. :embarrassed:
I now see that your pgreper() method reads data from stdin. Sorry if the paragraph above caused any confusion.
By way of apology for my previous gaffe, here's a slightly cleaner version of your script.
#! /usr/bin/env python
import sys
import re
class Grepper(object):
def __init__(self, pattern):
self.pattern = pattern
def pgreper(self):
regex = re.compile(self.pattern)
for line in sys.stdin:
if regex.search(line):
sys.stdout.write(line)
def main():
print("hello")
pattern = sys.argv[1]
Grepper(pattern).pgreper()
if __name__ == "__main__":
main()
else:
print("nope")
Make sure you have something executable here : /usr/bin/env.
When you try to run your python module as a command, it will call this as an interpreter. You may need to replace it with /usr/bin/python or /usr/bin/python3 if you don't have an env command.
Also, make sure your file is executable : chmod +x my_module.py and try to run it with ./my_module.py.

Why is `subprocess.call` not invoking the command

I'm trying to run a .wav file through ffmpeg using the subprocess.call(shell=True) in the following code and it doesn't seem to run. I know this because the output_file isn't created and I'm getting an exception in the open() method.
What am I doing wrong?
try:
import pocketsphinx
except:
import pocketsphinx as ps
import sphinxbase
import subprocess
import os
hmmd = "../../Pocketsphinx_Files/en-us-8khz"
lmdir = "../../Pocketsphinx_Files/cmusphinx-5.0-en-us.lm"
dictp = "../../Pocketsphinx_Files/cmu07a.dic"
output_filename = "../../temp/ps_output.wav"
def recognize(filename="../../temp/temp_output.wav"):
command = "ffmpeg -i "+filename+" -ac 1 -ab 16 -ar 16000 "+output_filename
subprocess.call(command,shell=True)
wavFile = open(output_filename,"rb")
speechRec = ps.Decoder(hmm = hmmd, lm = lmdir, dict = dictp)
wavFile.seek(44)
speechRec.decode_raw(wavFile)
result = speechRec.get_hyp()
#os.remove(filename)
#os.remove(output_filename)
return result
if __name__=="__main__":
print(recognize())
edit: I've got ffmpeg installed.
Furthermore, when I run the subprocess.call() command from the python interpreter it seems to work. This is why I'm stumped.
I would recommend that you try using subprocess.check_call() or check_output instead of simply call. They will raise an exception if your program fails to execute correctly, instead of leaving you wondering why no output was generated.
I'm going to guess that you may somehow be having path issues with your executable in a Python environment
Try using this function with 'ffmpeg':
def is_exe(prog):
for path in os.environ["PATH"].split(os.pathsep):
if os.path.isfile(os.path.join(path, prog)):
if os.access(os.path.join(path, prog), os.X_OK):
return os.path.join(path, prog)
else:
print "Program '%s' found in '%s', but lacks executable permissions." % (prog, path)
return False
If it returns False, you're having problems with Python running ffmpeg, otherwise it's ffmpeg which is having problems making sense of your arguments.

Python script for changing windows path to unix path

I want a script where I can paste a windows path as argument, and then the script converts the path to unix path and open the path using nautilus.
I want to be able to use the script as follows:
mypythonscript.py \\thewindowspath\subpath\
The script currently looks like this:
import sys, os
path = "nautilus smb:"+sys.argv[1]
path = path.replace("\\","/")
os.system(path)
I almost works :)
The problem is that I have to add ' around the argument... like this:
mypythonscript.py '\\thewindowspath\subpath\'
Anyone who knows how I can write a script that allows that argument is without ' , ... i.e. like this:
mypythonscript.py \\thewindowspath\subpath\
EDIT: I think I have to add that the problem is that without ' the \ in the argument is treated as escape character. The solution does not necessarily have to be a python script but I want (in Linux) to be able to just paste a windows path as argument to a script.
Unless you're using a really early version of Windows: "/blah/whatever/" just works for your OP.
Actually I had something like this a while ago, I made a bash script to automatically download links I copy into clipboard, here it is edited to use your program (you first need to install xclip if you don't already have it):
#!/bin/bash
old=""
new=""
old="$(xclip -out -selection c)"
while true
do
new="$(xclip -out -selection c)"
if [ "$new" != "$old" ]
then
old="$new"
echo Found: $new
mypythonscript.py $new
fi
sleep 1
done
exit 0
Now whenever you copy something new into the clipboard, your Python script will be executed with an argument of whatever is in your clipboard.
To avoid dealing with escapes in the shell you could work with the clipboard directly:
import os
try:
from Tkinter import Tk
except ImportError:
from tkinter import Tk # py3k
# get path from clipboard
path = Tk().selection_get(selection='CLIPBOARD')
# convert path and open it
cmd = 'nautilus'
os.execlp(cmd, cmd, 'smb:' + path.replace('\\', '/'))
ntpath, urlparse, os.path modules might help to handle the paths more robustly.
#!/usr/bin/python
#! python3
#! python2
# -*- coding: utf-8 -*-
"""win2ubu.py changes WINFILEPATH Printing UBUNTU_FILEPATH
Author: Joe Dorocak aka Joe Codeswell (JoeCodeswell.com)
Usage: win2ubu.py WINFILEPATH
Example: win2ubu.py "C:\\1d\ProgressiveWebAppPjs\\Polymer2.0Pjs\\PolymerRedux\\zetc\\polymer-redux-polymer-2"
prints /mnt/c/1d/ProgressiveWebAppPjs/Polymer2.0Pjs/PolymerRedux/zetc/polymer-redux-polymer-2
N.B. spaceless path needs quotes in BASH on Windows but NOT in Windows DOS prompt!
"""
import sys,os
def winPath2ubuPath(winpath):
# d,p = os.path.splitdrive(winpath) # NG only works on windows!
d,p = winpath.split(':')
ubupath = '/mnt/'+d.lower()+p.replace('\\','/')
print (ubupath)
return ubupath
NUM_ARGS = 1
def main():
args = sys.argv[1:]
if len(args) != NUM_ARGS or "-h" in args or "--help" in args:
print (__doc__)
sys.exit(2)
winPath2ubuPath(args[0])
if __name__ == '__main__':
main()
may want to try
my_argv_path = " ".join(sys.argv[1:])
as the only reason it would split the path into separate args is spaces in pasted path
(eg: C:\Program Files would end up as two args ["c:\Program","Files"])

how can i get the executable's current directory in py2exe?

I use this bit of code in my script to pinpoint, in a cross-platform way, where exactly it's being run from:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
Pretty simple. I then go on to use SCRIPT_ROOT in other areas of my script to make sure everything is properly relative. My problem occurs when I run it through py2exe, because the generated executable doesn't set __file__, therefore my script breaks. Does anyone know how to fix or work around this?
Here is the py2exe documentation reference and here are the relevant items:
sys.executable is set to the full pathname of the exe-file.
The first item in sys.argv is the full pathname of the executable, the rest are the command line arguments.
sys.frozen only exists in the executable. It is set to "console_exe" for a console executable, to "windows_exe" for a console-less gui executable, and to "dll" for a inprocess dll server.
__file__ is not defined (you might want to use sys.argv[0] instead)
It is not apparent from those docs whether "the exe-file" and "the executable" are the same thing, and thus whether sys.executable and sys.argv[0] are the same thing. Looking at code that worked for both script.py and py2exe_executable.exe last time I had to do this, I find something like:
if hasattr(sys, 'frozen'):
basis = sys.executable
else:
basis = sys.argv[0]
required_folder = os.path.split(basis)[0]
As I say that worked, but I don't recall why I thought that was necessary instead of just using sys.argv[0].
Using only basis was adequate for the job in hand (read files in that directory). For a more permanent record, split something like os.path.realpath(basis).
Update Actually did a test; beats guesswork and armchair pontification :-)
Summary: Ignore sys.frozen, ignore sys.executable, go with sys.argv[0] unconditionally.
Evidence:
=== foo.py ===
# coding: ascii
import sys, os.path
print 'sys has frozen:', hasattr(sys, 'frozen')
print 'using sys.executable:', repr(os.path.dirname(os.path.realpath(sys.executable)))
print 'using sys.argv[0]:', repr(os.path.dirname(os.path.realpath(sys.argv[0] )))
=== setup.py ===
from distutils.core import setup
import py2exe
setup(console=['foo.py'])
=== results ===
C:\junk\so\py2exe>\python26\python foo.py
sys has frozen: False
using sys.executable: 'C:\\python26'
using sys.argv[0]: 'C:\\junk\\so\\py2exe' # where foo.py lives
C:\junk\so\py2exe>dist\foo
sys has frozen: True
using sys.executable: 'C:\\junk\\so\\py2exe\\dist'
using sys.argv[0]: 'C:\\junk\\so\\py2exe\\dist' # where foo.exe lives
Py2exe does not define __file__: http://www.py2exe.org/index.cgi/Py2exeEnvironment
The OP requested a py2exe friendly version of:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
The best answer is to determine if python is frozen in an exe, py2exe has documentation on this:
http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe
import imp, os, sys
def main_is_frozen():
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze
def get_main_dir():
if main_is_frozen():
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.realpath(__file__))
SCRIPT_ROOT = get_main_dir()
Since, the python is EAFP, here's an EAFP version ...
try:
if sys.frozen or sys.importers:
SCRIPT_ROOT = os.path.dirname(sys.executable)
except AttributeError:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
Cheers!
sys.argv[0] is a reliable way to get the path, as it will give the same result irrespective of being run as a script or exe
. To get the directory os.path.dirname(sys.argv[0])
Try this:
import os
import sys
os.path.realpath(os.path.dirname(sys.argv[0]))

Categories

Resources