I have in my python workspace two Modules which need sip.pyd
Module1.pyd needs sip.pyd (which implements v 8.0-8.1)
Module2.pyd needs sip.pyd (another file, that implements v6.0)
So I can't just choose the newer one, it doesn't work: I have to keep them both!
(RuntimeError: the sip module implements API v6.0 but the fbx module requires API v8.1)
How can I import a module in .pyd extension (a python dll, not editable), and specify which sip.pyd to source?
As for a workaround, I manage to do that:
One sip.pyd is in my root site-packages location.
If I have to import the module that need the other sip.pyd, I remove root path form sys.path, and I append the precise folder path where the other sip.pyd are.
I can import my Module and restore previous sys.path.
Assuming you don't have a piece of code needing both files at once. I'd recommend the following:
install both files in 2 separate directories (call them e.g. sip-6.0 and sip-8.0), that you'll place in site-packages/
write a sip_helper.py file with code looking like
sip_helper.py contents:
import sys
import re
from os.path import join, dirname
def install_sip(version='6.0'):
assert version in ('6.0', '8.0'), "unsupported version"
keep = []
if 'sip' in sys.modules:
del sys.modules['sip']
for path in sys.path:
if not re.match('.*sip\d\.\d', path):
keep.append(path)
sys.path[:] = keep # remove other paths
sys.path.append(join(dirname(__file__), 'sip-%s' % version))
put sip_helper.py in site_packages (the parent directory of the sip-6.0 and sip-8.0 directories)
call sip_helper.install_sip at the startup of your programs
VirtualEnv is done to handle those case.
virtualenv is a tool to create isolated Python environments.
Using virtualenv, you will be able to create 2 environements, one with the sip.pyd in version 8.x another in version 6.0
I don't know if that works (if a module's name has to match its contents), but can't you just rename them to sip6.pyd resp. sip8.pyd and then do
if need6:
import sip6 as sip
else:
import sip8 as sip
?
Related
here is my Maya.env
λ cat C:\Users\roroco\Documents\maya\2018\Maya.env
MAYA_SCRIPT_PATH=C:/Users/roroco/OneDrive/maya/script
MAYA_PLUGIN_IN_PATH=C:/Users/roroco/OneDrive/maya/plugin
I'm sure my script exist:
λ cat C:\Users\roroco\OneDrive\maya\script\ro.py
def init():
print("prpr")
and in maya script editor, my script dir exist in MAYA_PATH_DIR
getenv MAYA_SCRIPT_PATH;
// Result: C:/Users/roroco/Documents/maya/projects/default/scripts;C:/Users/roroco/OneDrive/maya/script;C:/Users/roroco/Documents/maya/2018/scripts;C:/Users/roroco/Documents/maya/scripts;C:/Users/roroco/Documents/maya/2018/presets;C:/Users/roroco/Documents/maya/2018/prefs/shelves;C:/Users/roroco/Documents/maya/2018/prefs/markingMenus...
but when I import ro in script editor, it raise:
# Error: ImportError: file <maya console> line 1: No module named ro #
I hope I can write my maya script and auto sync to onedrive, how should i do
I don't understand maya doc say i can set MAYA_SCRIPT_PATH why it doesn't work
My tmp solution is add my script_dir in maya startup script
in C:\Users\roroco\Documents\maya\scripts\userSetup.py, add following code:
import imp
import os
imp.load_source("", "c:/users/" + os.environ["USERNAME"] + "/OneDrive/maya/script/userSetup.py")
and in my_script_dir/userSetup.py add my_script_dir to sys.path
import sys
import os
ro_script = os.path.dirname(__file__)
if ro_script not in sys.path:
sys.path.insert(0, ro_script)
you should be able to add python paths to your running maya dynamically with sys.path.insert or sys.path.append. You should not need to do anything more elaborate than that; you script should be importable if it's on the sys path.
For what you're trying to do a very common and clean solution is to use maya modules. Modules will allow you to append to the usual search directories, and they support network shares -- so you would add a module (in your maya modules path) and point its scripts directory to your onedrive. Modules can have their own userSetup.pys as well, which is very nice for keeping a clean separation between your code and anything else running on a particular machine.
More on modules here and here. The docs are here
You shouldn't have to add your path dynamically through userSetup.py.
Make sure you include PYTHONPATH in your Maya.env:
PYTHONPATH=C:\Users\roroco\OneDrive\maya\script
Checking my Windows home setup, I'm using back slashes in Maya.env, so you can see if switching helps. Instead of checking MAYA_PATH_DIR, check your sys.path to see if your directory is there. All Python modules need to be in one of these directories to import it:
import sys
for p in sys.path:
print p
You can also copy and paste your path to os.path.exists to confirm it really does exist. Sometimes it's the right path but the slashes make it so it doesn't resolve properly.
I'm totally new to Python, and I want to create my first Python library for peronal uses.
I'm using Python 2.7.5, and running the IDLE interface.
So far, what I understood from the documentation and related questions is that:
Python goes through a list of directories listed in sys.path to find scripts and libraries
The package directory must contain a __init__.py file, which can be empty
The module I want to create should be a modulename.py file with the code inside the package directory
(Sources: http://www.johnny-lin.com/cdat_tips/tips_pylang/path.html --- https://docs.python.org/2/tutorial/modules.html)
And here is what I tried that fails:
Created a personal package directory C:\....\pythonlibs
Created a subpackage dir C:\....\pythonlibs\package
Created the __init__.py file inside both folders
Created the mymodule.py file in the packacge dir
And then in the IDLE used this code:
import sys
sys.path.append(r'C:\....\pythonlibs')
First issue:
Currently I have to do this append every time I enter the IDLE. How can I keep the directory in sys.path permanently just as there are a lot of other directories there?
Then I tried importing my package:
import pythonlibs #fails!! why?
import pythonlibs.package #fails!! why?
import package #works
The error is: ImportError: No module named pythonlibs
Second issue?
This seems to be against the documentation, why can't I import from the root pythonlibs folder?
With line
sys.path.append(r'C:\....\pythonlibs')
you are instructing interpreter to start looking for modules (libraries) in this directory. Since this directory does not contain pythonlibs folder (the parent does), it can't import it.
Similarly - because it contains the module package, it can import it.
I created a test file called test.py (contained a class named test) and saved it into documents(Mac OS X 10.9.3)
I then attempted to use this file by writing from test import test. However, I got an error telling me that there was no module named test. Please can you shed some light into this issue.
The problem is that the Documents folder isn't usually in the PATH or PYTHONPATH, so the interpreter can't see scripts that are stored there (unless Documents happens to be the current working directory).
I can think of two solutions:
Move the file test.py to somewhere within Python's path.
You can find your PYTHONPATH with this script:
import os
try:
user_paths = os.environ['PYTHONPATH'].split(os.pathsep)
except KeyError:
user_paths = []
(From Mark Ransom’s answer to How do I find out my python path using python?)
You can find the system PATH with
import sys
print sys.path
Both of these return a list of folders. If you put test.py in one of those folders, then it will be seen by the interpreter.
For example, I usually install custom modules at
/Library/Python/2.7/site-packages
and then I can import them as normal.
Manually append Documents to your path.
You can use sys.path.append to add a directory to the path.
If you only need to use test.py in a handful of scripts, then you can add this code to each script you want to use test.py in:
import os
import sys
sys.path.append(os.path.join(os.environ['HOME'], 'Documents'))
from test import test
I am writing a simple scheduling service. I don't want to hard-code all of the tasks it can schedule and instead would like to support plugins that can be dropped in a folder and loaded dynamically at runtime.
My plan is to have a JSON file (or any configuration file) that maps a task name to the location of a Python file (a module) which will have a class called Plugin. Pretty simple I thought. When someone schedules a task to run, they pass the task name and the time to run it. When the time elapses, the plugin is loaded (or reloaded) and is ran with any additional arguments passed to the scheduler.
I have been looking at the imp module to see how to load modules at runtime. I am not sure whether I want to list plugins using their physical location (file system path) or to use their module names like you'd see in a import statement. It seems imp wants to use physical location.
I got two different versions of this code "working". Here is one that uses importlib:
pluginName = self.__pluginLookup[pluginName]
module = import_module(pluginName)
module = reload(module) # force reload
plugin = module.Plugin()
return plugin
This is one I wrote using imp:
path = self.__pluginLookup[pluginName]
path, moduleName = split(path)
moduleName, extension = splitext(moduleName)
file, path, description = find_module(moduleName, [path])
with file:
module = load_module(moduleName, file, path, description)
plugin = module.Plugin()
return plugin
The problem I am running into is handling dependencies. If I have a plugin.py file that depends on a dependency.py file in the same folder, saying import dependency doesn't seem to work. Instead, it looks up the dependency from the PYTHONPATH.
How can I make the imports relative to the plugins themselves?
You could append path to sys.path:
import sys
sys.path.append(path)
where path is the directory containing the dependency.py.
If you have a plugins directory with an __init__.py, you can add that directory to sys.path. Then modules inside there can do from . import dependency to import another plugin. Or, if the plugin is itself a subpackage (i.e., a directory with its own __init__.py) then it can do from . import dep to import a dependency within the same plugin, or from .. import dep to import a dependency from the global plugins directory. With this setup you don't even need to use imp or the like; you can use the __import__ function, which works by module name.
One possible wrinkle, though, is you say the plugins directory will be "under the current working directory". What does that mean exactly? You mean you want people to be able to add plugins anywhere on the drive and still use them? It would be better to have one central plugins directory for your app, and add that to sys.path, and tell people to put their plugins there.
I have a Python project in which I am using many non-code files. Currently these are all images, but I might use other kinds of files in the future. What would be a good scheme for storing and referencing these files?
I considered just making a folder "resources" in the main directory, but there is a problem; Some images are used from within sub-packages of my project. Storing these images that way would lead to coupling, which is a disadvantage.
Also, I need a way to access these files which is independent on what my current directory is.
You may want to use pkg_resources library that comes with setuptools.
For example, I've made up a quick little package "proj" to illustrate the resource organization scheme I'd use:
proj/setup.py
proj/proj/__init__.py
proj/proj/code.py
proj/proj/resources/__init__.py
proj/proj/resources/images/__init__.py
proj/proj/resources/images/pic1.png
proj/proj/resources/images/pic2.png
Notice how I keep all resources in a separate subpackage.
"code.py" shows how pkg_resources is used to refer to the resource objects:
from pkg_resources import resource_string, resource_listdir
# Itemize data files under proj/resources/images:
print resource_listdir('proj.resources.images', '')
# Get the data file bytes:
print resource_string('proj.resources.images', 'pic2.png').encode('base64')
If you run it, you get:
['__init__.py', '__init__.pyc', 'pic1.png', 'pic2.png']
iVBORw0KGgoAAAANSUhE ...
If you need to treat a resource as a fileobject, use resource_stream().
The code accessing the resources may be anywhere within the subpackage structure of your project, it just needs to refer to subpackage containing the images by full name: proj.resources.images, in this case.
Here's "setup.py":
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='proj',
packages=find_packages(),
package_data={'': ['*.png']})
Caveat:
To test things "locally", that is w/o installing the package first, you'll have to invoke your test scripts from directory that has setup.py. If you're in the same directory as code.py, Python won't know about proj package. So things like proj.resources won't resolve.
The new way of doing this is with importlib. For Python versions older than 3.7 you can add a dependency to importlib_resources and do something like
from importlib_resources import files
def get_resource(module: str, name: str) -> str:
"""Load a textual resource file."""
return files(module).joinpath(name).read_text(encoding="utf-8")
If your resources live inside the foo/resources sub-module, you would then use get_resource like so
resource_text = get_resource('foo.resources', 'myresource')
You can always have a separate "resources" folder in each subpackage which needs it, and use os.path functions to get to these from the __file__ values of your subpackages. To illustrate what I mean, I created the following __init__.py file in three locations:
c:\temp\topp (top-level package)
c:\temp\topp\sub1 (subpackage 1)
c:\temp\topp\sub2 (subpackage 2)
Here's the __init__.py file:
import os.path
resource_path = os.path.join(os.path.split(__file__)[0], "resources")
print resource_path
In c:\temp\work, I create an app, topapp.py, as follows:
import topp
import topp.sub1
import topp.sub2
This respresents the application using the topp package and subpackages. Then I run it:
C:\temp\work>topapp
Traceback (most recent call last):
File "C:\temp\work\topapp.py", line 1, in
import topp
ImportError: No module named topp
That's as expected. We set the PYTHONPATH to simulate having our package on the path:
C:\temp\work>set PYTHONPATH=c:\temp
C:\temp\work>topapp
c:\temp\topp\resources
c:\temp\topp\sub1\resources
c:\temp\topp\sub2\resources
As you can see, the resource paths resolved correctly to the location of the actual (sub)packages on the path.
Update: Here's the relevant py2exe documentation.
# pycon2009, there was a presentation on distutils and setuptools. You can find all of the videos here
Eggs and Buildout Deployment in Python - Part 1
Eggs and Buildout Deployment in Python - Part 2
Eggs and Buildout Deployment in Python - Part 3
In these videos, they describe how to include static resources in your package. I believe its in part 2.
With setuptools, you can define dependancies, this would allow you to have 2 packages that use resources from 3rd package.
Setuptools also gives you a standard way of accessing these resources and allows you to use relative paths inside of your packages, which eliminates the need to worry about where your packages are installed.