Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doing "from _ import _" in py4cl #50

Open
brandflake11 opened this issue Aug 31, 2021 · 11 comments
Open

Doing "from _ import _" in py4cl #50

brandflake11 opened this issue Aug 31, 2021 · 11 comments

Comments

@brandflake11
Copy link

Hello,
I am not a python expert at all, but I was using this lisp package to convert some python code into a lisp project I am working on. How would one go about using py4cl to do this kind of python code:

from SigMFUtils import SigMFUtil

I have attempted to do this with PYTHON-EVAL like this:
(py4cl:python-eval "from SigMFUtils import SigMFUtil")

but this doesn't work and results in a python syntax error. Is there a way to from _ import _ with IMPORT-MODULE?

Thank you very much for your time and any help you can offer.

@digikar99
Copy link
Contributor

Python like most non-lisp languages makes a distinction between expressions and non-expression-statements; so you'd rather need to use (py4cl:python-exec "from SigMFUtils import SigMFUtil") instead of python-eval.

@brandflake11
Copy link
Author

brandflake11 commented Sep 2, 2021

Thank you very much for your help @digikar99. I wanted to also ask you, which is related to this: How do I also change the directory where the python process for py4cl loads? The SigMFUtils I'm trying to load is in a specific folder, and I need to be in that directory in order for the python process to find SigMFUtils.

I know how to do this if I am just using python in a shell (cd directory && python .), but when it comes to py4cl, I'm not quite sure how that works.

@digikar99
Copy link
Contributor

There's also another way to change the process directory once the process has started: in the case of python, it is import os; os.chdir("directory/you/want"); so you could just call (python-exec "import os; os.chdir('directory/you/want')")

@brandflake11
Copy link
Author

@digikar99 Thanks so much for your help. As you can tell, I am not very good with python. :D I'll go ahead and close this.

@brandflake11
Copy link
Author

brandflake11 commented Sep 9, 2021

I apologize for reopening this issue. I'm actually having trouble with reading the .py file using the above code we talked about. Here is an example I'm having trouble with:

(ql:quickload :py4cl)

(py4cl:import-module "sigmf")
(py4cl:import-module "types")
(py4cl:import-module "json")
(py4cl:import-module "matplotlib.pyplot" :as "plt")
(py4cl:import-module "os")

(os:chdir "/home/brandon/my-dir/")
(os:getcwd)

(py4cl:python-exec "from SigMFUtils import SigMFUtil")

The above gives an error, even though the output of OS:GETCWD is the correct directory:


Python error: "No module named 'SigMFUtils'"
   [Condition of type py4cl:python-error]

Restarts:
 0: [retry] Retry SLIME interactive evaluation request.
 1: [*abort] Return to SLIME's top level.
 2: [abort] abort thread (#<thread "worker" running {10169097D3}>)

Backtrace:
  0: (py4cl::dispatch-messages #<uiop/launch-program::process-info {1009DEE2D3}>)
  1: (sb-int:simple-eval-in-lexenv (py4cl:python-exec "from SigMFUtils import SigMFUtil") #<NULL-LEXENV>)
  2: (eval (py4cl:python-exec "from SigMFUtils import SigMFUtil"))
  3: ((lambda nil :in swank:interactive-eval))
 --more--

However, if I run the same code using python 3.9.6 in my shell:

import sigmf
import types
import json
import matplotlib.pyplot as plt
import os

os.chdir("/home/brandon/my-dir")
from SigMFUtils import SigMFUtil

I don't get any error and SigMFUtil gets imported correctly. SigMFUtils is a .py file (named SigMFUtils.py) in the directory that I chdir to. Is this a bug, or am I missing something?

Thank you very much for your time!

@brandflake11 brandflake11 reopened this Sep 9, 2021
@digikar99
Copy link
Contributor

digikar99 commented Sep 9, 2021

Erm... Check for:

(python-exec "import sys")
(python-eval "sys.path") ; EDIT: corrected, thanks brandflake11!

Okay, I wasn't exactly clear about this, but the first item of this list, sys.path[0], is the directory containing the script that was used to invoke the Python interpreter; I had assumed it already contains the current-directory of the program, but turns out that isn't exactly the case. So, the current working directory would need to be added manually; hopefully that does it for you:

(python-exec "sys.path.append('./')") ; EDIT: corrected

@brandflake11
Copy link
Author

brandflake11 commented Sep 13, 2021

Okay, I looked at this and tried some of it. A couple of things:

  1. I was able to import sys. However, in order to see the sys.path I had to change your code to this:
    (python-eval "sys.path")

This needed to be a string in order for lisp to print out the paths from python. It just returned a symbol :sys.path otherwise.

  1. Then, to run the sys.append, I looked it up and the command should actually be:
    (python-exec "sys.path.append('./')")

It seems that sys.append is not a command you can run, but after a quick search sys.path.append was the right answer.

I sys.path.appended the directory that contains the SigMFUtils.py file I'm trying to import.

After appending the path to the directory I am working in, I am getting this error now:

Python error: "cannot import name 'SigMFFile' from 'sigmf' (/home/brandon/.local/lib/python3.9/site-packages/sigmf/__init__.py)"
   [Condition of type py4cl:python-error]

Restarts:
 0: [retry] Retry SLIME interactive evaluation request.
 1: [*abort] Return to SLIME's top level.
 2: [abort] abort thread (#<thread "worker" running {101A739C33}>)

Backtrace:
  0: (py4cl::dispatch-messages #<uiop/launch-program::process-info {101447E383}>)
  1: (sb-int:simple-eval-in-lexenv (py4cl:python-exec "from SigMFUtils import SigMFUtil") #<NULL-LEXENV>)
  2: (eval (py4cl:python-exec "from SigMFUtils import SigMFUtil"))
  3: ((lambda nil :in swank:interactive-eval))
 --more--

Everything looks normal as if I was running python from the shell. I just can't seem to import this. Let me know if you have any more ideas, and if not, that's fine too! Thanks again for your help!

@digikar99
Copy link
Contributor

My bad at several places! Apologies, and corrected.

cannot import name 'SigMFFile' from 'sigmf'

Okay... the value in sys.path while running as a script includes the absolute path to the directory-containing-script instead of the relative; does appending the absolute path instead of the relative path './' work?

May be the value of sys.path could be set from the py4cl/2 end in the future.

@brandflake11
Copy link
Author

No problem @digikar99! I actually have tried to add the ./ and absolute path to the sys.path. Does the order of sys.path matter? Do I need to start sbcl in the same directory as the .py file I'm trying to load? I run sbcl from slime if that matters.

@digikar99
Copy link
Contributor

I don't think I know if the order matters; so your best bet (as usual in programming) would be to try and see, and/or consult stackoverflow. For a simple sample file I created on my system to test this, it worked as expected; but for anything more complex, I don't know python enough or have a module to test this with.

You could also try changing the path of the lisp program to the relevant directory using uiop:chdir (or starting sbcl in the relevant directory itself) before starting the python process; but I'm unsure if that'd work.

@brandflake11
Copy link
Author

Thanks so much @digikar99 for all of your help. I'll keep experimenting and see if I can find a solution. I appreciate your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants