I know this might seem like a duplicated question, but I really could not find what I'm doing wrong... I wrote a .pyx file in order to compile it into a .pyd with cython. Long story short, it compiles my file just fine and creates a .pyd file. However, when I try to import that .pyd file I get an error saying No module named: "name_of_module". Note that this is my first time trying cython...
I am using venv with python3.9 on windows 10. I have cython installed along with minGW. To compile it into the .pyd file, I imply type in the command prompt in the same directory as the .pyx file:
python setup.py build_ext --inplace
Here is my setup.py file to cythonize my .pyx file:
from setuptools import setup, Extension
from Cython.Build import cythonize
extensions = [Extension('negamax_cy', ['negamax_cy.pyx'])]
setup(ext_modules=cythonize(extensions, language_level=3))
This is my .pyx file:
from connect4.constants import COLS, ROWS
from .position import Position
cdef int COLUMN_ORDER[7]
cdef int x
for x in range(COLS):
COLUMN_ORDER.append(COLS // 2 + (1 - 2 * (x % 2)) * (1 + x) // 2)
cpdef int negamax(pos, int depth, int alpha, int beta):
if pos.can_win(): # Check if current player can win this move
return 1000 - pos.moves*2
cdef long next_move = pos.possible_non_loosing_moves()
if next_move == 0: # Check for moves which are not losing moves
return -1000 + pos.moves # If we have 2 or more forcing moves we lose
if depth == 0: # Check if we have reached max depth
return 0
if pos.moves == ROWS * COLS: # Check for a draw game
return 0
cdef int col = 0
for col in COLUMN_ORDER[col]:
if next_move & Position.column_mask(col):
pos_cp = Position(position=pos)
pos_cp.play_col(col)
score = -negamax(pos_cp, depth - 1, -beta, -alpha)
if score >= beta:
return score
alpha = max(alpha, score)
return alpha
My project structure is as follow (I am trying to do a connect4 game with an A.I. in pygame):
connect4
/venv
/ai
__init__.py
setup.py
file_where_pyd_is_imported.py
negamax_cy.pyx
negamax_cy.pyd
negamax_cy.c
/connect4
__init__.py
other_files.py
__init__.py
main.py
Note that main.py imports file_where_pyd_is_imported.py
When I import I simply type:
import negamax_cy
this is the error I get:
Traceback (most recent call last):
File "D:\Users\dalla\Documents\Coding Projects\python\games\connect4\main.py", line 5, in <module>
from ai.negamax import mp_best_move, best_move, print_avg
File "D:\Users\dalla\Documents\Coding Projects\python\games\connect4\ai\negamax.py", line 7, in <module>
import negamax_cy
ModuleNotFoundError: No module named 'negamax_cy'
As I said I don't know what is wrong. Maybe it has to do with my project structure or something, or my setup.py file, but I am unsure... If anyone has an idea let me know.
Well turns out I'm really stupid and in python3 I have to upload like this:
from . import negamax_cy
Sorry for wasting anyone's time...
Related
I am trying to learn Cython at the moment and have followed a tutorial here.
I have it working within Ubuntu (on vmware) but right now I am trying to get it working on windows (using VSCode). I took all the files that I had created in Ubuntu and put them on my machine.
When I try to run my python file testing.py I receive this error:
Exception has occurred: ModuleNotFoundError
No module named 'example_cy'
here is the code for the testing.py
import timeit
cy = timeit.timeit('example_cy.test(5000)', setup = 'import example_cy', number = 1000)
py = timeit.timeit('example_py.test(5000)', setup = 'import example_py', number = 1000)
print(cy, py)
print('Cython is {}x faster'.format(py/cy))
This is the example_cy.pyx file
cpdef int test(int x):
cdef int y = 0
cdef int i
for i in range(x):
y += i
return y
The example_py.py file
def test(x):
y = 0
for i in range(x):
y += i
return y
and the setup.py code
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize('example_cy.pyx'))
I have a working cpp project which builds fine with cmake. Now I need to create a Python wrapper for the same. So I chose cython to bridge the gap between C++ and Python.
Instead of writing the CMakeLists.txt logic in pyx file, I tried compiling the library with cmake itself and later wrap the Cython wrapper around it. Following is the setup.py file:
import os
import sys
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
try:
build_dir = os.path.join(os.getcwd(), "build")
print("building bobcore.a")
if not os.path.exists(build_dir):
os.makedirs(build_dir)
if not os.path.exists(build_dir):
raise Exception("Not able to create `build` directory")
os.chdir(build_dir)
assert os.system("cmake ..") == 0
assert os.system("make -j4") == 0
os.chdir(os.path.abspath(os.path.join(os.getcwd(), os.pardir)))
except:
if not os.path.exists("build/bobcli"):
print("Error building external library, please create libsample.a manually.")
sys.exit(1)
_ext_modules = cythonize([
Extension("call_core",
sources=["call_core.pyx"],
language="c++",
extra_compile_args=["-std=c++11", "-lpthread", "-lz", "-ldl"],
extra_link_args=["-std=c++11"],
include_dirs=[os.path.join(os.getcwd(), "src")], # path to .h file(s)
library_dirs=[os.path.join(os.getcwd(), "build")], # path to .a or .so file(s)
libraries=["bobcli"] # name of pre-built .so file.
)
])
setup(
name='Demos',
ext_modules=_ext_modules,
)
Here is the call_core.pyx file:
cdef extern from "src/api/Api.h" namespace "cli":
cdef cppclass Api:
int getVal()
cdef Api *api = new Api()
def getHelp():
return api.getVal()
del api
Now this file works fine if I implement the getVal() method in the header file itself. But as soon as I move the implementation to .cpp file, Cython compiler shows the following error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: /usr/local/lib/python2.7/dist-packages/call_core.so: undefined symbol: _ZN3cli9Api6getValEv
NOTE: The above snippets work perfectly for the functions with their implementation in the .h files.
I am using Python 3 to try and get a test file for sample application working yet it keeps throwing ImportError: No module named 'calculate'
My file structure is:
/calculate
__init__.py
calculate.py
test/
__init__.py
calculate_test.py
I cannot figure out why this is the case, any help would be much appreciated.
The __init__.py files are empty.
calculate.py contains:
class Calculate(object):
def add(self, x, y):
return x + y
if __name__ == '__main__':
calc = Calculate()
result = calc.add(2, 2)
print(result)
calculate_test.py contains:
import unittest
from calculate import Calculate
class TestCalculate(unittest.TestCase):
def setUp(self):
self.calc = Calculate()
def test_add_method_returns_correct_result(self):
self.assertEqual(4, self.calc.add(2,2))
if __name__ == '__main__':
unittest.main()
I am running python test/calculate_test.py from the root /calculate folder and am getting the error
Traceback (most recent call last):
File "test/calculate_test.py", line 2, in <module>
from calculate import Calculate
ImportError: No module named 'calculate'
I have been fiddling around with different structures and cannot understand what the problem is.
Your project's structure is the reason. The test script doesn't have the outer directory in the search path when you start it. Here are some ways to fix that
Move the test file into the same directory that contains the module it imports. That will require no changes in the test file.
Use this structure
./project/
calculate_test.py
calculate/
__init__.py
calculate.py
This will require you to change the import signature in calculate_test.py to something like from calculate import calculate
It's my first post here, please understand that I'm a beginner and that I'm learning "on-the-job".
Can someone explain how can I import files from a different module in a Maya python script? I'm getting the following error:
Error: ImportError: file E:/.../bin/mainScript.py line 17: No module named tools
Here are my directories and codes:
Main_folder\
|-- install.mel
|-- ReadMeFirst.txt
`-- bin\
|-- __init__.py
|-- mainScript.py
|-- tools.py
`-- presets\
|-- bipedPreset.txt
|-- quadrupedPreset.txt
`-- [...] .txt
I'm trying to import tools.py in mainScript.py
EDIT:
Ok, as it won't fit in a comment I edit this post to add precisions. I moved the 'Main_folder' on my Desktop and ran the script once again in Maya. It still doesn't work but I have a more complete error traceback. Here it is:
# Error: Error in maya.utils._guiExceptHook:
# File "C:\Program Files\Autodesk\Maya2014\Python\lib\site-packages\maya\utils.py", line 332, in formatGuiException
# result = u'%s: file %s line %s: %s' % (exceptionType.__name__, file, line, exceptionMsg)
# UnicodeDecodeError: 'ascii' codec can't decode byte 0xfc in position 11: ordinal not in range(128)
#
# Original exception was:
# Traceback (most recent call last):
# File "<maya console>", line 3, in <module>
# File "C:/Users/UKDP/Desktop/Main_folder/bin/mainScript.py", line 17, in <module>
# from tools import ClassTest
# ImportError: No module named tools #
You need to make sure any importable modules are on you python path.
If your files are in E:/main_folder you'll need to do
import sys
sys.path.append("E:/main_folder")
import bin.tools
import bin.mainScript
and so on. The way you have it set up (with 'bin/__init__.py') you're telling python that the module is named bin and it has submodules named 'mainScript' and 'tools'. Long discussion here
Try importing like:
>>>import san.libs.stringops
Where the san is dir(in san create __init__.py)
libs is a dir(in libs create __init__.py)
and stringops.py is imported
Try this
I have a folder that is on my desktop and the folder is called Combo and has a script called combo.py and here is how I access it:
import sys #imports system's directory module
sys.path.insert(0,"C:/Users/dharmin.doshi/Desktop") #Add your directory, do not add your folder in the path unless the script is inside of folder inside of folder. Path needs to be in quotes and 0 is added as needed by the argument.
from Combo(Folder name) import combo (my python script)
reload (combo) #Optional to reload it every time you make changes to the script.
combo.run() #Call the function that runs the code.
In your case if you need to access tools.py then your path will be like:
sys.path.insert(0, "MainFolder/bin")
import tools
Hope this helps :)
exe1.py
import san.libs.stringops
import san.libs.maths
import san.libs.utils.ran
import san.printing
newstr = san.libs.stringops.add2string("hey","hi")
san.printing.myprint(newstr)
result = san.libs.maths.add(2,3)
san.printing.myprint(result)
random_number = san.libs.utils.ran.getnumber()
san.printing.myprint(random_number)
I use a custom random number generator build with Cython. I don't understand why, but it no longer works... I guess it is related to Python 2.7, or maybe a new version of Cython.
In dcmtrand.pyx, I have:
...
import dcmt
...
cdef class RandomState:
...
def __reduce__(self):
return (dcmt.__RandomState_ctor, (), self.get_state())
...
dcmt is a folder. In it, I have init.py file:
from dcmtrand import *
def __RandomState_ctor():
return RandomState.__new__(RandomState)
I compile it using
python setup.py build_ext --inplace
then I copy resulting dcmtrand.so file into dcmt folder, and I move dcmt folder into my project.
Now, if I import dcmt, everything is ok:
import dcmt
import cPickle
dc = dcmt.DynamicCreator(5)
a = dc[0]
cPickle.dumps(a)
But if I want to put dcmt into a subpackage, it no longer works:
from prng import dcmt
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "prng/dcmt/__init__.py", line 1, in <module>
from dcmtrand import *
File "dcmtrand.pyx", line 10, in init dcmtrand (dcmtrand.c:6955)
ImportError: No module named dcmt
To make it work, I need to add prng to Python path.
Why it is no longer working? How to make it work again?
Yes, you have 3 choices:
Set PYTHONPATH to have dmct in it: PYTHONPATH=$PYTHONPATH:prng
Use sys.path:
from os.path import dirname, join
import sys
sys.path.append(join(dirname(__file__), 'prng')
Do the same inclusion as in your .py: from prng import dcmt