import from local file in chimerax-python script

Hi there, I'm running a python script either from within ChimeraX (with "open http://myScript.py") or from the command line (using "chimerax http://myScript.py"). As the script gets longer and longer, I would like to store some class definitions in a separate file (http://classDefinitions.py within the same directory as http://myScript.py and then import those into the main script with some command like "from classDefinitions import testClass". This, however, gives me an "ModuleNotFoundError: No module named 'testClass'". What is the correct way to do this? Any help would be much appreciated! Cheers, Maik

Hi Maik, This is a general Python issue. Python will only look for files in directories listed in its sys.path variable. If the current directory "." is not in that path it will not find files in the same directory. Also if you open a Python file in ChimeraX, ChimeraX itself may be running with a current directory that is not the one containing your Python script file. I don't know a very nice way to handle all this. But an ugly hack would be in myScript.py to check if sys.path contains the directory with your script and if not add it to sys.path. A more sane Python method is to make a Python module which is a directory containing an __init__.py file and other Python files, and then you use "import mydirectory" and then use relative imports in your Python files like "from . import myclasses". But that just changes the problem to how do you get ChimeraX to import your Python module which is a directory. Hopefully someone else will suggest a nicer way to handle this. Tom
On Apr 17, 2024, at 2:03 PM, Engeholm, Maik via ChimeraX-users <chimerax-users@cgl.ucsf.edu> wrote:
Hi there,
I'm running a python script either from within ChimeraX (with "open myScript.py") or from the command line (using "chimerax myScript.py"). As the script gets longer and longer, I would like to store some class definitions in a separate file (classDefinitions.py within the same directory as myScript.py) and then import those into the main script with some command like "from classDefinitions import testClass". This, however, gives me an "ModuleNotFoundError: No module named 'testClass'". What is the correct way to do this?
Any help would be much appreciated!
Cheers,
Maik
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu <mailto:chimerax-users@cgl.ucsf.edu> To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu <mailto:chimerax-users-leave@cgl.ucsf.edu> Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/

Hi Maik. I don't know if this is the "correct" solution, but this code in myScript.py will put those class definitions (well, any global definitions in classDefinitions.py) into myScript.py's global namespace: from os.path import join, dirname with open(join(dirname(__file__), "classDefinitions.py")) as f: exec(f.read(), globals(), locals()) --Eric Eric Pettersen UCSF Computer Graphics Lab
On Apr 17, 2024, at 2:03 PM, Engeholm, Maik via ChimeraX-users <chimerax-users@cgl.ucsf.edu> wrote:
Hi there,
I'm running a python script either from within ChimeraX (with "open myScript.py") or from the command line (using "chimerax myScript.py"). As the script gets longer and longer, I would like to store some class definitions in a separate file (classDefinitions.py within the same directory as myScript.py) and then import those into the main script with some command like "from classDefinitions import testClass". This, however, gives me an "ModuleNotFoundError: No module named 'testClass'". What is the correct way to do this?
Any help would be much appreciated!
Cheers,
Maik
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu <mailto:chimerax-users@cgl.ucsf.edu> To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu <mailto:chimerax-users-leave@cgl.ucsf.edu> Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/ <https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/>

Hi Tom, hi Eric, thanks a lot for Eric's suggestion! This is very neat and works like a charm! @Tom: In a "normal" python script importing code from another module in the same directory is actually not a problem. As far as I understand, that is because calling "python http://myScript.py" prepends myScript's directory to sys.path (see e.g. https://docs.python.org/3/library/sys.html#sys.path With pymol this also works, which is how I got used to organising all my pymol scripts that way. I suppose opening a script with chimerax just doesn't prepend its directory to sys.path then and there is no simple way to change this? Thanks a lot once more, Maik ________________________________ From: Eric Pettersen <pett@cgl.ucsf.edu> Sent: Thursday, April 18, 2024 3:13:10 AM To: Engeholm, Maik Cc: chimerax-users@cgl.ucsf.edu Subject: Re: [chimerax-users] import from local file in chimerax-python script Hi Maik. I don't know if this is the "correct" solution, but this code in http://myScript.py will put those class definitions (well, any global definitions in http://classDefinitions.py into http://myScript.py's global namespace: from os.path import join, dirname with open(join(dirname(__file__), "classDefinitions.py")) as f: exec(f.read(), globals(), locals()) --Eric Eric Pettersen UCSF Computer Graphics Lab On Apr 17, 2024, at 2:03 PM, Engeholm, Maik via ChimeraX-users <chimerax-users@cgl.ucsf.edu<mailto:chimerax-users@cgl.ucsf.edu>> wrote: Hi there, I'm running a python script either from within ChimeraX (with "open http://myScript.py") or from the command line (using "chimerax http://myScript.py"). As the script gets longer and longer, I would like to store some class definitions in a separate file (http://classDefinitions.py within the same directory as http://myScript.py and then import those into the main script with some command like "from classDefinitions import testClass". This, however, gives me an "ModuleNotFoundError: No module named 'testClass'". What is the correct way to do this? Any help would be much appreciated! Cheers, Maik _______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu<mailto:chimerax-users@cgl.ucsf.edu> To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu<mailto:chimerax-users-leave@cgl.ucsf.edu> Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/

Hi Maik, You can put "." in the Python system path if you like import sys sys.path.insert(0, '.') and then python will import files in the current directory working directory of the application. ChimeraX does not do that because then any Python code that does "import something" can accidentally pick up something.py in the current directory. That seems unlikely but because ChimeraX uses hundreds of Python modules so a name collision is a real possibility and a naive user will probably not figure out why ChimeraX no longer works. For a silly example suppose ChimeraX had "." in sys.path by default and on your desktop you made some test code math.py. ChimeraX would no longer start because it uses the actual Python math module. The other trouble with using "." in sys.path is that it refers to the application current working directory which may not be your script directory. So for instance I might use "open ~/myscript.py" in ChimeraX but by default ChimeraX starts in ~/Desktop so "." in sys.path will only import python files in ~/Desktop. A way to deal with that is make ChimeraX change its current working directory to the script directory (it does that for ChimeraX command scripts *.cxc). That has the unpleasant effect that when your Python script writes a bunch of output files they now appear in ~/ instead of the directory where you started ChimeraX -- probably not what you intended. In summary, the situation is a bit complicated and ChimeraX in general tries to be reliable and not too smart so doesn't add "." to sys.path. Tom
On Apr 18, 2024, at 12:02 AM, Engeholm, Maik via ChimeraX-users <chimerax-users@cgl.ucsf.edu> wrote:
Hi Tom, hi Eric,
thanks a lot for Eric's suggestion! This is very neat and works like a charm!
@Tom: In a "normal" python script importing code from another module in the same directory is actually not a problem. As far as I understand, that is because calling "python myScript.py" prepends myScript's directory to sys.path (see e.g. https://docs.python.org/3/library/sys.html#sys.path). With pymol this also works, which is how I got used to organising all my pymol scripts that way. I suppose opening a script with chimerax just doesn't prepend its directory to sys.path then and there is no simple way to change this?
Thanks a lot once more,
Maik
From: Eric Pettersen <pett@cgl.ucsf.edu <mailto:pett@cgl.ucsf.edu>> Sent: Thursday, April 18, 2024 3:13:10 AM To: Engeholm, Maik Cc: chimerax-users@cgl.ucsf.edu <mailto:chimerax-users@cgl.ucsf.edu> Subject: Re: [chimerax-users] import from local file in chimerax-python script
Hi Maik. I don't know if this is the "correct" solution, but this code in myScript.py will put those class definitions (well, any global definitions in classDefinitions.py) into myScript.py's global namespace:
from os.path import join, dirname with open(join(dirname(__file__), "classDefinitions.py")) as f: exec(f.read(), globals(), locals())
--Eric
Eric Pettersen UCSF Computer Graphics Lab
On Apr 17, 2024, at 2:03 PM, Engeholm, Maik via ChimeraX-users <chimerax-users@cgl.ucsf.edu <mailto:chimerax-users@cgl.ucsf.edu>> wrote:
Hi there,
I'm running a python script either from within ChimeraX (with "open myScript.py") or from the command line (using "chimerax myScript.py"). As the script gets longer and longer, I would like to store some class definitions in a separate file (classDefinitions.py within the same directory as myScript.py) and then import those into the main script with some command like "from classDefinitions import testClass". This, however, gives me an "ModuleNotFoundError: No module named 'testClass'". What is the correct way to do this?
Any help would be much appreciated!
Cheers,
Maik
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu <mailto:chimerax-users@cgl.ucsf.edu> To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu <mailto:chimerax-users-leave@cgl.ucsf.edu> Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu <mailto:chimerax-users@cgl.ucsf.edu> To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu <mailto:chimerax-users-leave@cgl.ucsf.edu> Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/
participants (3)
-
Engeholm, Maik
-
Eric Pettersen
-
Tom Goddard